move theme related data from blog
to theme
This commit is contained in:
parent
2965ca04b0
commit
7b7be55499
68 changed files with 1393 additions and 1251 deletions
|
@ -24,7 +24,6 @@
|
||||||
"rules": {
|
"rules": {
|
||||||
"@typescript-eslint/no-empty-interface": "off",
|
"@typescript-eslint/no-empty-interface": "off",
|
||||||
"@typescript-eslint/explicit-module-boundary-types": "off",
|
"@typescript-eslint/explicit-module-boundary-types": "off",
|
||||||
"react/jsx-uses-vars": "error",
|
|
||||||
"react/react-in-jsx-scope": ["off"]
|
"react/react-in-jsx-scope": ["off"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf build"
|
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf build"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@developomp-site/theme": "workspace:*",
|
||||||
"@fortawesome/fontawesome-svg-core": "^6.2.1",
|
"@fortawesome/fontawesome-svg-core": "^6.2.1",
|
||||||
"@fortawesome/free-brands-svg-icons": "^6.2.1",
|
"@fortawesome/free-brands-svg-icons": "^6.2.1",
|
||||||
"@fortawesome/free-regular-svg-icons": "^6.2.1",
|
"@fortawesome/free-regular-svg-icons": "^6.2.1",
|
||||||
|
@ -33,8 +34,8 @@
|
||||||
"styled-components": "^5.3.6"
|
"styled-components": "^5.3.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@developomp-site/tsconfig": "workspace:0.0.0",
|
"@developomp-site/eslint-config": "workspace:*",
|
||||||
"@developomp-site/eslint-config": "workspace:0.0.0",
|
"@developomp-site/tsconfig": "workspace:*",
|
||||||
"@types/ejs": "^3.1.1",
|
"@types/ejs": "^3.1.1",
|
||||||
"@types/elasticlunr": "^0.9.5",
|
"@types/elasticlunr": "^0.9.5",
|
||||||
"@types/highlight.js": "^10.1.0",
|
"@types/highlight.js": "^10.1.0",
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
import darkTheme from "@developomp-site/theme/dist/dark.json"
|
||||||
|
import lightTheme from "@developomp-site/theme/dist/light.json"
|
||||||
|
|
||||||
import { useContext, useEffect, useState } from "react"
|
import { useContext, useEffect, useState } from "react"
|
||||||
import { Routes, Route, useNavigate, useLocation } from "react-router-dom"
|
import { Routes, Route, useNavigate, useLocation } from "react-router-dom"
|
||||||
import styled, { ThemeProvider } from "styled-components"
|
import styled, { ThemeProvider } from "styled-components"
|
||||||
|
@ -5,7 +8,7 @@ import { Helmet } from "react-helmet-async"
|
||||||
import { isIE } from "react-device-detect"
|
import { isIE } from "react-device-detect"
|
||||||
|
|
||||||
import Loading from "./components/Loading"
|
import Loading from "./components/Loading"
|
||||||
import Navbar from "./components/Navbar"
|
import Header from "./components/Header"
|
||||||
import Footer from "./components/Footer"
|
import Footer from "./components/Footer"
|
||||||
|
|
||||||
import Home from "./pages/Home"
|
import Home from "./pages/Home"
|
||||||
|
@ -14,17 +17,16 @@ import Page from "./pages/Page"
|
||||||
import NotFound from "./pages/NotFound"
|
import NotFound from "./pages/NotFound"
|
||||||
import Portfolio from "./pages/Portfolio"
|
import Portfolio from "./pages/Portfolio"
|
||||||
|
|
||||||
import theming from "./styles/theming"
|
|
||||||
import GlobalStyle from "./styles/globalStyle"
|
import GlobalStyle from "./styles/globalStyle"
|
||||||
|
|
||||||
import { ActionsEnum, globalContext } from "./globalContext"
|
import { globalContext } from "./globalContext"
|
||||||
|
|
||||||
const IENotSupported = styled.p`
|
const IENotSupported = styled.p`
|
||||||
margin: auto;
|
margin: auto;
|
||||||
font-size: 2rem;
|
font-size: 2rem;
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-family: ${theming.font.regular};
|
font-family: ${(props) => props.theme.theme.font.sansSerif};
|
||||||
`
|
`
|
||||||
|
|
||||||
const StyledContentContainer = styled.div`
|
const StyledContentContainer = styled.div`
|
||||||
|
@ -34,7 +36,7 @@ const StyledContentContainer = styled.div`
|
||||||
`
|
`
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const { globalState, dispatch } = useContext(globalContext)
|
const { globalState } = useContext(globalContext)
|
||||||
const { locale } = globalState
|
const { locale } = globalState
|
||||||
|
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
|
@ -73,10 +75,8 @@ export default function App() {
|
||||||
return (
|
return (
|
||||||
<ThemeProvider
|
<ThemeProvider
|
||||||
theme={{
|
theme={{
|
||||||
currentTheme: globalState.theme,
|
currentTheme: globalState.currentTheme,
|
||||||
setTheme(setThemeTo) {
|
theme: globalState.currentTheme === "dark" ? darkTheme : lightTheme,
|
||||||
dispatch({ type: ActionsEnum.UPDATE_THEME, payload: setThemeTo })
|
|
||||||
},
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Helmet>
|
<Helmet>
|
||||||
|
@ -87,7 +87,7 @@ export default function App() {
|
||||||
|
|
||||||
<GlobalStyle />
|
<GlobalStyle />
|
||||||
|
|
||||||
<Navbar />
|
<Header />
|
||||||
<StyledContentContainer>
|
<StyledContentContainer>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<Loading />
|
<Loading />
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
|
import dark from "@developomp-site/theme/dist/dark.json"
|
||||||
|
import light from "@developomp-site/theme/dist/light.json"
|
||||||
|
|
||||||
import { useEffect, useState } from "react"
|
import { useEffect, useState } from "react"
|
||||||
import styled from "styled-components"
|
import styled from "styled-components"
|
||||||
|
|
||||||
import theming from "../styles/theming"
|
|
||||||
|
|
||||||
const StyledBadge = styled.div<{ color: string; isDark: boolean }>`
|
const StyledBadge = styled.div<{ color: string; isDark: boolean }>`
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
@ -15,7 +16,7 @@ const StyledBadge = styled.div<{ color: string; isDark: boolean }>`
|
||||||
|
|
||||||
background-color: ${(props) => props.color};
|
background-color: ${(props) => props.color};
|
||||||
color: ${(props) =>
|
color: ${(props) =>
|
||||||
props.isDark ? theming.dark.color1 : theming.light.color1};
|
props.isDark ? dark.color.text.default : light.color.text.default};
|
||||||
`
|
`
|
||||||
|
|
||||||
const StyledSVG = styled.div<{ isDark: boolean }>`
|
const StyledSVG = styled.div<{ isDark: boolean }>`
|
||||||
|
@ -27,7 +28,9 @@ const StyledSVG = styled.div<{ isDark: boolean }>`
|
||||||
svg {
|
svg {
|
||||||
height: 16px;
|
height: 16px;
|
||||||
fill: ${(props) =>
|
fill: ${(props) =>
|
||||||
props.isDark ? theming.dark.color1 : theming.light.color1} !important;
|
props.isDark
|
||||||
|
? dark.color.text.default
|
||||||
|
: light.color.text.default} !important;
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
|
|
@ -1,29 +1,22 @@
|
||||||
import styled, { css } from "styled-components"
|
import styled, { css } from "styled-components"
|
||||||
|
|
||||||
import theming from "../styles/theming"
|
|
||||||
|
|
||||||
export const cardCSS = css`
|
export const cardCSS = css`
|
||||||
margin: auto;
|
margin: auto;
|
||||||
background-color: ${(props) =>
|
background-color: ${({ theme }) =>
|
||||||
theming.theme(props.theme.currentTheme, {
|
theme.currentTheme ? theme.theme.component.card.color.background : "white"};
|
||||||
light: "white",
|
|
||||||
dark: theming.dark.backgroundColor2,
|
|
||||||
})};
|
|
||||||
padding: 2rem;
|
padding: 2rem;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
box-shadow: ${(props) =>
|
box-shadow: ${({ theme }) =>
|
||||||
theming.theme(props.theme.currentTheme, {
|
theme.currentTheme === "dark"
|
||||||
light: "0 4px 10px rgb(0 0 0 / 5%), 0 0 1px rgb(0 0 0 / 10%);",
|
? "0 4px 10px rgb(0 0 0 / 30%), 0 0 1px rgb(0 0 0 / 30%)"
|
||||||
dark: "0 4px 10px rgb(0 0 0 / 30%), 0 0 1px rgb(0 0 0 / 30%);",
|
: "0 4px 10px rgb(0 0 0 / 5%), 0 0 1px rgb(0 0 0 / 10%)"};
|
||||||
})};
|
|
||||||
|
|
||||||
@media screen and (max-width: ${theming.size.screen_size1}) {
|
@media screen and (max-width: ${({ theme }) =>
|
||||||
|
theme.theme.maxDisplayWidth.mobile}) {
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
const Card = styled.div`
|
export default styled.div`
|
||||||
${cardCSS}
|
${cardCSS}
|
||||||
`
|
`
|
||||||
|
|
||||||
export default Card
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import styled from "styled-components"
|
import styled from "styled-components"
|
||||||
|
|
||||||
import theming from "../../styles/theming"
|
|
||||||
import GithubLinkIcon from "../GithubLinkIcon"
|
import GithubLinkIcon from "../GithubLinkIcon"
|
||||||
|
|
||||||
const StyledFooter = styled.footer`
|
const StyledFooter = styled.footer`
|
||||||
|
@ -13,17 +12,8 @@ const StyledFooter = styled.footer`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
color: ${(props) =>
|
background-color: ${({ theme }) =>
|
||||||
theming.theme(props.theme.currentTheme, {
|
theme.theme.component.footer.color.background};
|
||||||
light: "black",
|
|
||||||
dark: "white",
|
|
||||||
})};
|
|
||||||
|
|
||||||
background-color: ${(props) =>
|
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: "white",
|
|
||||||
dark: "black",
|
|
||||||
})};
|
|
||||||
`
|
`
|
||||||
|
|
||||||
const StyledFooterContainer = styled.div`
|
const StyledFooterContainer = styled.div`
|
||||||
|
@ -35,10 +25,10 @@ const StyledFooterContainer = styled.div`
|
||||||
color: gray;
|
color: gray;
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: ${theming.size.screen_size2};
|
max-width: ${({ theme }) => theme.theme.maxDisplayWidth.desktop};
|
||||||
`
|
`
|
||||||
|
|
||||||
const Footer = () => {
|
export default () => {
|
||||||
return (
|
return (
|
||||||
<StyledFooter>
|
<StyledFooter>
|
||||||
<StyledFooterContainer>
|
<StyledFooterContainer>
|
||||||
|
@ -51,5 +41,3 @@ const Footer = () => {
|
||||||
</StyledFooter>
|
</StyledFooter>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Footer
|
|
||||||
|
|
|
@ -4,39 +4,27 @@ import styled from "styled-components"
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
||||||
import { faGithub } from "@fortawesome/free-brands-svg-icons"
|
import { faGithub } from "@fortawesome/free-brands-svg-icons"
|
||||||
|
|
||||||
import theming from "../styles/theming"
|
|
||||||
|
|
||||||
const StyledGithubLink = styled.a<{ size?: string }>`
|
const StyledGithubLink = styled.a<{ size?: string }>`
|
||||||
font-size: ${(props) => props.size || "2.5rem"};
|
font-size: ${(props) => props.size || "2.5rem"};
|
||||||
|
color: ${({ theme }) =>
|
||||||
color: ${(props) =>
|
theme.currentTheme === "dark" ? "grey" : "lightgrey"};
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: "lightgrey",
|
|
||||||
dark: "grey",
|
|
||||||
})};
|
|
||||||
|
|
||||||
:hover {
|
:hover {
|
||||||
color: ${(props) =>
|
color: ${({ theme }) => theme.theme.color.text.highContrast};
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: theming.light.color0,
|
|
||||||
dark: theming.dark.color0,
|
|
||||||
})};
|
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
interface GithubLinkIconProps {
|
interface Props {
|
||||||
link: string
|
link: string
|
||||||
size?: string
|
size?: string
|
||||||
children?: ReactNode
|
children?: ReactNode
|
||||||
}
|
}
|
||||||
|
|
||||||
const GithubLinkIcon = (props: GithubLinkIconProps) => {
|
export default ({ link, size, children }: Props) => {
|
||||||
return (
|
return (
|
||||||
<StyledGithubLink size={props.size} href={props.link} target="_blank">
|
<StyledGithubLink size={size} href={link} target="_blank">
|
||||||
<FontAwesomeIcon icon={faGithub} />
|
<FontAwesomeIcon icon={faGithub} />
|
||||||
{props.children}
|
{children}
|
||||||
</StyledGithubLink>
|
</StyledGithubLink>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default GithubLinkIcon
|
|
||||||
|
|
21
apps/blog/src/components/Header/Buttons/Buttons.tsx
Normal file
21
apps/blog/src/components/Header/Buttons/Buttons.tsx
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import styled from "styled-components"
|
||||||
|
|
||||||
|
import LocaleToggleButton from "./LocaleToggleButton"
|
||||||
|
import ThemeToggleButton from "./ThemeToggleButton"
|
||||||
|
import SearchButton from "./SearchButton"
|
||||||
|
|
||||||
|
const RightButtons = styled.div`
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
margin-left: auto;
|
||||||
|
`
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
return (
|
||||||
|
<RightButtons>
|
||||||
|
<LocaleToggleButton />
|
||||||
|
<ThemeToggleButton />
|
||||||
|
<SearchButton />
|
||||||
|
</RightButtons>
|
||||||
|
)
|
||||||
|
}
|
|
@ -1,3 +1,5 @@
|
||||||
|
import type { SiteLocale } from "../../../globalContext"
|
||||||
|
|
||||||
import { useContext } from "react"
|
import { useContext } from "react"
|
||||||
import styled from "styled-components"
|
import styled from "styled-components"
|
||||||
import ReactTooltip from "react-tooltip"
|
import ReactTooltip from "react-tooltip"
|
||||||
|
@ -5,29 +7,28 @@ import ReactTooltip from "react-tooltip"
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
||||||
import { faLanguage } from "@fortawesome/free-solid-svg-icons"
|
import { faLanguage } from "@fortawesome/free-solid-svg-icons"
|
||||||
|
|
||||||
import { ActionsEnum, globalContext } from "../../globalContext"
|
import { ActionsEnum, globalContext } from "../../../globalContext"
|
||||||
import theming from "../../styles/theming"
|
import { HeaderButtonCSS } from "../HeaderButton"
|
||||||
|
|
||||||
import type { SiteLocale } from "../../globalContext"
|
interface Props {
|
||||||
|
|
||||||
interface StyledLocaleToggleButtonProps {
|
|
||||||
locale: SiteLocale
|
locale: SiteLocale
|
||||||
}
|
}
|
||||||
|
|
||||||
const StyledLocaleToggleButton = styled.button<StyledLocaleToggleButtonProps>`
|
const LocaleToggleButton = styled.button<Props>`
|
||||||
${theming.styles.navbarButtonStyle}
|
${HeaderButtonCSS}
|
||||||
|
|
||||||
border: none;
|
border: none;
|
||||||
width: 72px;
|
width: 72px;
|
||||||
|
|
||||||
${(props) => (props.locale == "en" ? "" : "transform: scaleX(-1);")};
|
${(props) => (props.locale == "en" ? "" : "transform: scaleX(-1);")};
|
||||||
`
|
`
|
||||||
|
|
||||||
function LocaleToggleButton() {
|
export default () => {
|
||||||
const { globalState, dispatch } = useContext(globalContext)
|
const { globalState, dispatch } = useContext(globalContext)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<StyledLocaleToggleButton
|
<LocaleToggleButton
|
||||||
data-tip
|
data-tip
|
||||||
data-for="locale"
|
data-for="locale"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
@ -39,12 +40,10 @@ function LocaleToggleButton() {
|
||||||
locale={globalState.locale}
|
locale={globalState.locale}
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon icon={faLanguage} />
|
<FontAwesomeIcon icon={faLanguage} />
|
||||||
</StyledLocaleToggleButton>
|
</LocaleToggleButton>
|
||||||
<ReactTooltip id="locale" type="dark" effect="solid">
|
<ReactTooltip id="locale" type="dark" effect="solid">
|
||||||
<span>{globalState.locale == "en" ? "English" : "한국어"} </span>
|
<span>{globalState.locale == "en" ? "English" : "한국어"} </span>
|
||||||
</ReactTooltip>
|
</ReactTooltip>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default LocaleToggleButton
|
|
|
@ -2,12 +2,11 @@ import { useContext } from "react"
|
||||||
import { Link } from "react-router-dom"
|
import { Link } from "react-router-dom"
|
||||||
import ReactTooltip from "react-tooltip"
|
import ReactTooltip from "react-tooltip"
|
||||||
|
|
||||||
|
import HeaderButton from "../HeaderButton"
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
||||||
import { faSearch } from "@fortawesome/free-solid-svg-icons"
|
import { faSearch } from "@fortawesome/free-solid-svg-icons"
|
||||||
|
|
||||||
import { StyledLink } from "./Navbar"
|
import { globalContext } from "../../../globalContext"
|
||||||
|
|
||||||
import { globalContext } from "../../globalContext"
|
|
||||||
|
|
||||||
const SearchButton = () => {
|
const SearchButton = () => {
|
||||||
const { globalState } = useContext(globalContext)
|
const { globalState } = useContext(globalContext)
|
||||||
|
@ -17,9 +16,9 @@ const SearchButton = () => {
|
||||||
<>
|
<>
|
||||||
<div>
|
<div>
|
||||||
<Link data-tip data-for="search" to={`/${locale}/search`}>
|
<Link data-tip data-for="search" to={`/${locale}/search`}>
|
||||||
<StyledLink>
|
<HeaderButton>
|
||||||
<FontAwesomeIcon icon={faSearch} />
|
<FontAwesomeIcon icon={faSearch} />
|
||||||
</StyledLink>
|
</HeaderButton>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<ReactTooltip id="search" type="dark" effect="solid">
|
<ReactTooltip id="search" type="dark" effect="solid">
|
|
@ -6,24 +6,21 @@ import ReactTooltip from "react-tooltip"
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
||||||
import { faMoon, faSun } from "@fortawesome/free-solid-svg-icons"
|
import { faMoon, faSun } from "@fortawesome/free-solid-svg-icons"
|
||||||
|
|
||||||
import theming from "../../styles/theming"
|
import { ActionsEnum, globalContext } from "../../../globalContext"
|
||||||
import { ActionsEnum, globalContext } from "../../globalContext"
|
import { HeaderButtonCSS } from "../HeaderButton"
|
||||||
|
|
||||||
const StyledThemeButton = styled.button`
|
const StyledThemeButton = styled.button`
|
||||||
${theming.styles.navbarButtonStyle}
|
${HeaderButtonCSS}
|
||||||
border: none;
|
border: none;
|
||||||
width: 72px;
|
width: 72px;
|
||||||
|
|
||||||
${(props) =>
|
${({ theme }) =>
|
||||||
theming.theme(props.theme.currentTheme, {
|
theme.currentTheme === "dark" ? "transform: scaleX(-1)" : ""};
|
||||||
light: "",
|
|
||||||
dark: "transform: scaleX(-1);",
|
|
||||||
})};
|
|
||||||
`
|
`
|
||||||
|
|
||||||
const ThemeToggleButton = () => {
|
const ThemeToggleButton = () => {
|
||||||
const { globalState, dispatch } = useContext(globalContext)
|
const { globalState, dispatch } = useContext(globalContext)
|
||||||
const theme = globalState.theme
|
const theme = globalState.currentTheme
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
3
apps/blog/src/components/Header/Buttons/index.ts
Normal file
3
apps/blog/src/components/Header/Buttons/index.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import Buttons from "./Buttons"
|
||||||
|
|
||||||
|
export default Buttons
|
63
apps/blog/src/components/Header/Header.tsx
Normal file
63
apps/blog/src/components/Header/Header.tsx
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
import { useContext } from "react"
|
||||||
|
import { Link } from "react-router-dom"
|
||||||
|
import styled from "styled-components"
|
||||||
|
import ReadProgress from "./ReadProgress"
|
||||||
|
|
||||||
|
import Nav from "./Nav"
|
||||||
|
|
||||||
|
import Sidebar from "../Sidebar"
|
||||||
|
|
||||||
|
import { globalContext } from "../../globalContext"
|
||||||
|
import Buttons from "./Buttons"
|
||||||
|
|
||||||
|
const Header = styled.header`
|
||||||
|
/* set z index to arbitrarily high value to prevent other components from drawing over it */
|
||||||
|
z-index: 9999;
|
||||||
|
|
||||||
|
position: fixed;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
background-color: ${({ theme }) =>
|
||||||
|
theme.theme.component.ui.color.background.default};
|
||||||
|
color: ${({ theme }) => theme.theme.color.text.default};
|
||||||
|
box-shadow: 0 4px 10px rgb(0 0 0 / 5%);
|
||||||
|
`
|
||||||
|
|
||||||
|
const Container = styled.div`
|
||||||
|
margin: 0 auto;
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
height: 4rem;
|
||||||
|
|
||||||
|
/* account for 20px scrollbar width */
|
||||||
|
@media only screen and (min-width: calc(${({ theme }) =>
|
||||||
|
theme.theme.maxDisplayWidth.desktop} + 20px)) {
|
||||||
|
width: calc(${({ theme }) => theme.theme.maxDisplayWidth.desktop} - 20px);
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const Icon = styled.img`
|
||||||
|
height: 2.5rem;
|
||||||
|
|
||||||
|
display: block;
|
||||||
|
margin: 1rem;
|
||||||
|
`
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
const { globalState } = useContext(globalContext)
|
||||||
|
const { locale } = globalState
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Header>
|
||||||
|
<Container>
|
||||||
|
<Link to={`/${locale}`}>
|
||||||
|
<Icon src="/icon/icon_circle.svg" />
|
||||||
|
</Link>
|
||||||
|
<Nav />
|
||||||
|
<Buttons />
|
||||||
|
<Sidebar />
|
||||||
|
</Container>
|
||||||
|
<ReadProgress />
|
||||||
|
</Header>
|
||||||
|
)
|
||||||
|
}
|
43
apps/blog/src/components/Header/HeaderButton.tsx
Normal file
43
apps/blog/src/components/Header/HeaderButton.tsx
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/**
|
||||||
|
* @file Manages the configuration settings for the widget.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import styled, { css } from "styled-components"
|
||||||
|
|
||||||
|
export const HeaderButtonCSS = css`
|
||||||
|
/* style */
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
cursor: pointer;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
/* size */
|
||||||
|
|
||||||
|
height: 100%;
|
||||||
|
min-width: 2.5rem;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 1rem 0 1rem;
|
||||||
|
|
||||||
|
/* text */
|
||||||
|
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
/* color */
|
||||||
|
|
||||||
|
color: ${({ theme }) => theme.theme.color.text.default};
|
||||||
|
background-color: ${({ theme }) =>
|
||||||
|
theme.theme.component.ui.color.background.default};
|
||||||
|
|
||||||
|
/* animation */
|
||||||
|
|
||||||
|
transition: transform 0.1s linear;
|
||||||
|
&:hover {
|
||||||
|
background-color: ${({ theme }) =>
|
||||||
|
theme.theme.component.ui.color.background.hover};
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
export default styled.div`
|
||||||
|
${HeaderButtonCSS}
|
||||||
|
`
|
|
@ -2,35 +2,33 @@ import { useContext } from "react"
|
||||||
import styled from "styled-components"
|
import styled from "styled-components"
|
||||||
import { Link } from "react-router-dom"
|
import { Link } from "react-router-dom"
|
||||||
|
|
||||||
import { StyledLink } from "./Navbar"
|
import HeaderButton from "./HeaderButton"
|
||||||
|
|
||||||
import NavbarData from "../../data/NavbarData"
|
import NavbarData from "../../data/NavbarData"
|
||||||
import theming from "../../styles/theming"
|
|
||||||
import { globalContext } from "../../globalContext"
|
import { globalContext } from "../../globalContext"
|
||||||
|
|
||||||
const StyledNavLinks = styled.div`
|
const Nav = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
@media only screen and (max-width: ${theming.size.screen_size1}) {
|
@media only screen and (max-width: ${({ theme }) =>
|
||||||
|
theme.theme.maxDisplayWidth.mobile}) {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
const NavLinks = () => {
|
export default () => {
|
||||||
const { globalState } = useContext(globalContext)
|
const { globalState } = useContext(globalContext)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledNavLinks>
|
<Nav>
|
||||||
{NavbarData.map((item, index) => (
|
{NavbarData.map((item, index) => (
|
||||||
<Link key={index} to={globalState.locale + item.path}>
|
<Link key={index} to={globalState.locale + item.path}>
|
||||||
<StyledLink>
|
<HeaderButton>
|
||||||
{globalState.locale == "en" ? item.title_en : item.title_kr}
|
{globalState.locale == "en" ? item.title_en : item.title_kr}
|
||||||
</StyledLink>
|
</HeaderButton>
|
||||||
</Link>
|
</Link>
|
||||||
))}
|
))}
|
||||||
</StyledNavLinks>
|
</Nav>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default NavLinks
|
|
|
@ -2,24 +2,16 @@ import { useCallback, useEffect, useState } from "react"
|
||||||
import { useLocation } from "react-router-dom"
|
import { useLocation } from "react-router-dom"
|
||||||
import styled from "styled-components"
|
import styled from "styled-components"
|
||||||
|
|
||||||
import theming from "../../styles/theming"
|
const Background = styled.div`
|
||||||
|
|
||||||
const StyledReadProgressBackground = styled.div`
|
|
||||||
height: 0.2rem;
|
height: 0.2rem;
|
||||||
background-color: ${(props) =>
|
background-color: ${({ theme }) =>
|
||||||
theming.theme(props.theme.currentTheme, {
|
theme.theme.component.scrollProgressBar.color.background};
|
||||||
light: "silver",
|
|
||||||
dark: "darkslategrey",
|
|
||||||
})};
|
|
||||||
`
|
`
|
||||||
|
|
||||||
const StyledReadProgress = styled.div`
|
const ProgressBar = styled.div`
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: ${(props) =>
|
background-color: ${({ theme }) =>
|
||||||
theming.theme(props.theme.currentTheme, {
|
theme.theme.component.scrollProgressBar.color.foreground};
|
||||||
light: theming.light.color0,
|
|
||||||
dark: theming.dark.color2,
|
|
||||||
})};
|
|
||||||
`
|
`
|
||||||
|
|
||||||
const st = "scrollTop"
|
const st = "scrollTop"
|
||||||
|
@ -58,9 +50,9 @@ const ReadProgress = () => {
|
||||||
}, [location])
|
}, [location])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledReadProgressBackground>
|
<Background>
|
||||||
<StyledReadProgress style={{ width: `${scroll}%` }} />
|
<ProgressBar style={{ width: `${scroll}%` }} />
|
||||||
</StyledReadProgressBackground>
|
</Background>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
3
apps/blog/src/components/Header/index.ts
Normal file
3
apps/blog/src/components/Header/index.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import Navbar from "./Header"
|
||||||
|
|
||||||
|
export default Navbar
|
|
@ -6,8 +6,6 @@ import styled from "styled-components"
|
||||||
|
|
||||||
import MainContent from "./MainContent"
|
import MainContent from "./MainContent"
|
||||||
|
|
||||||
import theming from "../styles/theming"
|
|
||||||
|
|
||||||
const StyledContainer = styled(MainContent)`
|
const StyledContainer = styled(MainContent)`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -30,11 +28,7 @@ const StyledContainer = styled(MainContent)`
|
||||||
`
|
`
|
||||||
|
|
||||||
const StyledSVG = styled.svg`
|
const StyledSVG = styled.svg`
|
||||||
--color: ${(props) =>
|
--color: ${({ theme }) => theme.theme.color.text.default};
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: theming.light.color1,
|
|
||||||
dark: theming.dark.color1,
|
|
||||||
})};
|
|
||||||
|
|
||||||
display: block;
|
display: block;
|
||||||
margin: 1rem;
|
margin: 1rem;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import styled, { css } from "styled-components"
|
import styled, { css } from "styled-components"
|
||||||
import theming from "../styles/theming"
|
|
||||||
|
|
||||||
import Card from "./Card"
|
import Card from "./Card"
|
||||||
|
|
||||||
|
@ -15,7 +14,8 @@ export const mainContentCSS = css`
|
||||||
max-width: fit-content;
|
max-width: fit-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: ${theming.size.screen_size1}) {
|
@media screen and (max-width: ${({ theme }) =>
|
||||||
|
theme.theme.maxDisplayWidth.mobile}) {
|
||||||
width: auto;
|
width: auto;
|
||||||
margin: 1rem;
|
margin: 1rem;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,95 +0,0 @@
|
||||||
import { useContext } from "react"
|
|
||||||
import styled from "styled-components"
|
|
||||||
import { Link } from "react-router-dom"
|
|
||||||
|
|
||||||
import NavLinks from "./NavLinks"
|
|
||||||
import LocaleToggleButton from "./LocaleToggleButton"
|
|
||||||
import ThemeToggleButton from "./ThemeToggleButton"
|
|
||||||
import SearchButton from "./SearchButton"
|
|
||||||
import ReadProgress from "./ReadProgress"
|
|
||||||
import Sidebar from "../Sidebar"
|
|
||||||
|
|
||||||
import theming from "../../styles/theming"
|
|
||||||
|
|
||||||
import { globalContext } from "../../globalContext"
|
|
||||||
|
|
||||||
const StyledNav = styled.nav`
|
|
||||||
/* set z index to arbitrarily high value to prevent other components from drawing over the navbar */
|
|
||||||
z-index: 9999;
|
|
||||||
position: fixed;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
background-color: ${(props) =>
|
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: theming.light.backgroundColor0,
|
|
||||||
dark: theming.dark.backgroundColor0,
|
|
||||||
})};
|
|
||||||
color: ${(props) =>
|
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: theming.light.color0,
|
|
||||||
dark: theming.dark.color0,
|
|
||||||
})};
|
|
||||||
box-shadow: 0 4px 10px rgb(0 0 0 / 5%);
|
|
||||||
`
|
|
||||||
|
|
||||||
const StyledContainer = styled.div`
|
|
||||||
margin: 0 auto;
|
|
||||||
align-items: center;
|
|
||||||
display: flex;
|
|
||||||
height: 4rem;
|
|
||||||
|
|
||||||
/* account for 20px scrollbar width */
|
|
||||||
@media only screen and (min-width: calc(${theming.size
|
|
||||||
.screen_size2} + 20px)) {
|
|
||||||
width: calc(${theming.size.screen_size2} - 20px);
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
const RightButtons = styled.div`
|
|
||||||
display: flex;
|
|
||||||
height: 100%;
|
|
||||||
margin-left: auto;
|
|
||||||
`
|
|
||||||
|
|
||||||
const StyledImg = styled.img`
|
|
||||||
height: 2.5rem;
|
|
||||||
|
|
||||||
display: block;
|
|
||||||
margin: 1rem;
|
|
||||||
`
|
|
||||||
|
|
||||||
export const StyledLink = styled.div`
|
|
||||||
${theming.styles.navbarButtonStyle}
|
|
||||||
`
|
|
||||||
|
|
||||||
const Navbar = () => {
|
|
||||||
const { globalState } = useContext(globalContext)
|
|
||||||
const { locale } = globalState
|
|
||||||
|
|
||||||
return (
|
|
||||||
<StyledNav>
|
|
||||||
<StyledContainer>
|
|
||||||
{/* icon */}
|
|
||||||
<Link to={`/${locale}`}>
|
|
||||||
<StyledImg src="/icon/icon_circle.svg" />
|
|
||||||
</Link>
|
|
||||||
|
|
||||||
{/* nav links */}
|
|
||||||
<NavLinks />
|
|
||||||
|
|
||||||
{/* right buttons */}
|
|
||||||
<RightButtons>
|
|
||||||
<LocaleToggleButton />
|
|
||||||
<ThemeToggleButton />
|
|
||||||
<SearchButton />
|
|
||||||
</RightButtons>
|
|
||||||
|
|
||||||
{/* etc */}
|
|
||||||
<Sidebar />
|
|
||||||
</StyledContainer>
|
|
||||||
<ReadProgress />
|
|
||||||
</StyledNav>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Navbar
|
|
|
@ -1,3 +0,0 @@
|
||||||
import Navbar from "./Navbar"
|
|
||||||
|
|
||||||
export default Navbar
|
|
|
@ -15,57 +15,41 @@ import Tag from "./Tag"
|
||||||
import TagList from "./TagList"
|
import TagList from "./TagList"
|
||||||
import MainContent from "./MainContent"
|
import MainContent from "./MainContent"
|
||||||
|
|
||||||
import theming from "../styles/theming"
|
|
||||||
import { globalContext } from "../globalContext"
|
import { globalContext } from "../globalContext"
|
||||||
|
|
||||||
|
const PostCard = styled(MainContent)`
|
||||||
|
box-shadow: 0 4px 10px rgb(0 0 0 / 10%);
|
||||||
|
text-align: left;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
|
||||||
|
:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
box-shadow: 0 4px 10px
|
||||||
|
${({ theme }) => theme.theme.component.card.color.hoverGlow};
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
const PostCardContainer = styled(Link)`
|
const PostCardContainer = styled(Link)`
|
||||||
display: block;
|
display: block;
|
||||||
padding: 2rem;
|
padding: 2rem;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
color: ${(props) =>
|
/* override link color */
|
||||||
theming.theme(props.theme.currentTheme, {
|
color: ${({ theme }) => theme.theme.color.text.gray};
|
||||||
light: theming.light.color2,
|
|
||||||
dark: theming.dark.color2,
|
|
||||||
})};
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: ${(props) =>
|
color: ${({ theme }) => theme.theme.color.text.gray};
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: theming.light.color2,
|
|
||||||
dark: theming.dark.color2,
|
|
||||||
})};
|
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
const StyledPostCard = styled(MainContent)`
|
const Title = styled.h1`
|
||||||
box-shadow: 0 4px 10px rgb(0 0 0 / 10%);
|
|
||||||
text-align: left;
|
|
||||||
margin-bottom: 2rem;
|
|
||||||
|
|
||||||
color: ${(props) =>
|
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: theming.light.color1,
|
|
||||||
dark: theming.dark.color1,
|
|
||||||
})};
|
|
||||||
|
|
||||||
${theming.styles.hoverCard}
|
|
||||||
`
|
|
||||||
|
|
||||||
const StyledTitle = styled.h1`
|
|
||||||
font-size: 2rem;
|
font-size: 2rem;
|
||||||
font-style: bold;
|
font-style: bold;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
color: ${(props) =>
|
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: theming.light.color2,
|
|
||||||
dark: theming.dark.color2,
|
|
||||||
})};
|
|
||||||
`
|
`
|
||||||
|
|
||||||
const StyledMetaContainer = styled.small``
|
const MetaContainer = styled.small``
|
||||||
|
|
||||||
interface PostCardData extends PostData {
|
interface PostCardData extends PostData {
|
||||||
content_id: string
|
content_id: string
|
||||||
|
@ -75,26 +59,26 @@ interface Props {
|
||||||
postData: PostCardData
|
postData: PostCardData
|
||||||
}
|
}
|
||||||
|
|
||||||
const PostCard = (props: Props) => {
|
export default (props: Props) => {
|
||||||
const { postData } = props
|
const { postData } = props
|
||||||
const { content_id, wordCount, date, readTime, title, tags } = postData
|
const { content_id, wordCount, date, readTime, title, tags } = postData
|
||||||
|
|
||||||
const { globalState } = useContext(globalContext)
|
const { globalState } = useContext(globalContext)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledPostCard>
|
<PostCard>
|
||||||
<PostCardContainer
|
<PostCardContainer
|
||||||
to={`/${globalState.locale}${content_id.replace(/(.kr)$/g, "")}`}
|
to={`/${globalState.locale}${content_id.replace(/(.kr)$/g, "")}`}
|
||||||
>
|
>
|
||||||
<StyledTitle>
|
<Title>
|
||||||
{title || "No title"}
|
{title || "No title"}
|
||||||
{/* show "(series)" for urls that matches regex "/series/<series-title>" */}
|
{/* show "(series)" for urls that matches regex "/series/<series-title>" */}
|
||||||
{/\/series\/[^/]*$/.test(content_id) && " (series)"}
|
{/\/series\/[^/]*$/.test(content_id) && " (series)"}
|
||||||
</StyledTitle>
|
</Title>
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<StyledMetaContainer>
|
<MetaContainer>
|
||||||
<TagList direction="left">
|
<TagList direction="left">
|
||||||
{tags &&
|
{tags &&
|
||||||
tags.map((tag) => {
|
tags.map((tag) => {
|
||||||
|
@ -115,10 +99,8 @@ const PostCard = (props: Props) => {
|
||||||
{typeof wordCount === "number"
|
{typeof wordCount === "number"
|
||||||
? wordCount + " words"
|
? wordCount + " words"
|
||||||
: "unknown length"}
|
: "unknown length"}
|
||||||
</StyledMetaContainer>
|
</MetaContainer>
|
||||||
</PostCardContainer>
|
</PostCardContainer>
|
||||||
</StyledPostCard>
|
</PostCard>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default PostCard
|
|
||||||
|
|
|
@ -9,14 +9,15 @@ import { faEllipsisV, faTimes } from "@fortawesome/free-solid-svg-icons"
|
||||||
import SubMenu from "./SubMenu"
|
import SubMenu from "./SubMenu"
|
||||||
|
|
||||||
import NavbarData from "../../data/NavbarData"
|
import NavbarData from "../../data/NavbarData"
|
||||||
import theming from "../../styles/theming"
|
import HeaderButton from "../Header/HeaderButton"
|
||||||
|
|
||||||
const CommonSidebarToggleButtonStyle = css`
|
const CommonSidebarToggleButtonStyle = css`
|
||||||
${theming.styles.navbarButtonStyle}
|
${HeaderButton}
|
||||||
width: 1.5rem;
|
width: 1.5rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
cursor: pointer;
|
|
||||||
@media only screen and (min-width: ${theming.size.screen_size1}) {
|
@media only screen and (min-width: ${({ theme }) =>
|
||||||
|
theme.theme.maxDisplayWidth.mobile}) {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
@ -65,16 +66,9 @@ const SidebarNav = styled.nav<{ isSidebarOpen: boolean }>`
|
||||||
z-index: 30;
|
z-index: 30;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
background-color: ${(props) =>
|
background-color: ${({ theme }) =>
|
||||||
theming.theme(props.theme.currentTheme, {
|
theme.theme.component.header.color.background};
|
||||||
light: theming.light.backgroundColor0,
|
color: ${({ theme }) => theme.theme.component.header.color.text};
|
||||||
dark: theming.dark.backgroundColor0,
|
|
||||||
})};
|
|
||||||
color: ${(props) =>
|
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: theming.light.color0,
|
|
||||||
dark: theming.dark.color0,
|
|
||||||
})};
|
|
||||||
`
|
`
|
||||||
|
|
||||||
const SidebarWrap = styled.div`
|
const SidebarWrap = styled.div`
|
||||||
|
|
|
@ -2,17 +2,17 @@
|
||||||
* @file Submenu item for sidebar
|
* @file Submenu item for sidebar
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import type { Item } from "../../data/NavbarData"
|
||||||
|
|
||||||
import { useCallback, useContext, useState } from "react"
|
import { useCallback, useContext, useState } from "react"
|
||||||
import { Link } from "react-router-dom"
|
import { Link } from "react-router-dom"
|
||||||
import styled from "styled-components"
|
import styled from "styled-components"
|
||||||
|
|
||||||
import theming from "../../styles/theming"
|
|
||||||
import { globalContext } from "../../globalContext"
|
import { globalContext } from "../../globalContext"
|
||||||
|
import button from "../../styles/button"
|
||||||
import type { Item } from "../../data/NavbarData"
|
|
||||||
|
|
||||||
const SidebarLink = styled(Link)`
|
const SidebarLink = styled(Link)`
|
||||||
${theming.styles.navbarButtonStyle};
|
${button};
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|
|
@ -4,19 +4,13 @@ import styled from "styled-components"
|
||||||
import { faHashtag } from "@fortawesome/free-solid-svg-icons"
|
import { faHashtag } from "@fortawesome/free-solid-svg-icons"
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
||||||
|
|
||||||
import theming from "../styles/theming"
|
const Tag = styled.div`
|
||||||
|
|
||||||
const StyledTag = styled.div`
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
margin-right: 0.8rem;
|
margin-right: 0.8rem;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
|
|
||||||
color: ${(props) =>
|
color: ${({ theme }) => theme.theme.color.text.gray};
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: theming.light.color2,
|
|
||||||
dark: theming.dark.color2,
|
|
||||||
})};
|
|
||||||
`
|
`
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
@ -24,12 +18,10 @@ interface Props {
|
||||||
onClick?: (event: MouseEvent<never>) => void
|
onClick?: (event: MouseEvent<never>) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const Tag = (props: Props) => {
|
export default (props: Props) => {
|
||||||
return (
|
return (
|
||||||
<StyledTag onClick={props.onClick || undefined}>
|
<Tag onClick={props.onClick || undefined}>
|
||||||
<FontAwesomeIcon icon={faHashtag} /> {props.text}
|
<FontAwesomeIcon icon={faHashtag} /> {props.text}
|
||||||
</StyledTag>
|
</Tag>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Tag
|
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
|
import type { Dispatch, ReactNode, ReactElement } from "react"
|
||||||
|
import type { Theme } from "@developomp-site/theme"
|
||||||
|
|
||||||
|
import darkTheme from "@developomp-site/theme/dist/dark.json"
|
||||||
|
import lightTheme from "@developomp-site/theme/dist/light.json"
|
||||||
import { createContext, useEffect, useReducer } from "react"
|
import { createContext, useEffect, useReducer } from "react"
|
||||||
import storage from "local-storage-fallback"
|
import storage from "local-storage-fallback"
|
||||||
|
|
||||||
import type { Dispatch, ReactNode, ReactElement } from "react"
|
|
||||||
|
|
||||||
export type SiteLocale = "en" | "kr"
|
export type SiteLocale = "en" | "kr"
|
||||||
export type SiteTheme = "dark" | "light"
|
export type SiteTheme = "dark" | "light"
|
||||||
|
|
||||||
|
@ -11,11 +14,6 @@ export enum ActionsEnum {
|
||||||
UPDATE_LOCALE,
|
UPDATE_LOCALE,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IGlobalState {
|
|
||||||
locale: SiteLocale
|
|
||||||
theme: SiteTheme
|
|
||||||
}
|
|
||||||
|
|
||||||
export type GlobalAction =
|
export type GlobalAction =
|
||||||
| {
|
| {
|
||||||
type: ActionsEnum.UPDATE_THEME
|
type: ActionsEnum.UPDATE_THEME
|
||||||
|
@ -26,6 +24,12 @@ export type GlobalAction =
|
||||||
payload: SiteLocale
|
payload: SiteLocale
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IGlobalState {
|
||||||
|
locale: SiteLocale
|
||||||
|
currentTheme: SiteTheme
|
||||||
|
theme: Theme
|
||||||
|
}
|
||||||
|
|
||||||
export interface IGlobalContext {
|
export interface IGlobalContext {
|
||||||
globalState: IGlobalState
|
globalState: IGlobalState
|
||||||
dispatch: Dispatch<GlobalAction>
|
dispatch: Dispatch<GlobalAction>
|
||||||
|
@ -40,7 +44,11 @@ function getDefaultLocale(): SiteLocale {
|
||||||
|
|
||||||
const defaultState: IGlobalState = {
|
const defaultState: IGlobalState = {
|
||||||
locale: getDefaultLocale(),
|
locale: getDefaultLocale(),
|
||||||
theme: (storage.getItem("theme") || "dark") as SiteTheme,
|
currentTheme: (storage.getItem("theme") || "dark") as SiteTheme,
|
||||||
|
theme:
|
||||||
|
((storage.getItem("theme") || "dark") as SiteTheme) === "dark"
|
||||||
|
? darkTheme
|
||||||
|
: lightTheme,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const globalContext = createContext({} as IGlobalContext)
|
export const globalContext = createContext({} as IGlobalContext)
|
||||||
|
@ -48,7 +56,8 @@ export const globalContext = createContext({} as IGlobalContext)
|
||||||
function reducer(state = defaultState, action: GlobalAction): IGlobalState {
|
function reducer(state = defaultState, action: GlobalAction): IGlobalState {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case ActionsEnum.UPDATE_THEME:
|
case ActionsEnum.UPDATE_THEME:
|
||||||
state.theme = action.payload
|
state.currentTheme = action.payload
|
||||||
|
state.theme = state.currentTheme === "dark" ? darkTheme : lightTheme
|
||||||
break
|
break
|
||||||
|
|
||||||
case ActionsEnum.UPDATE_LOCALE:
|
case ActionsEnum.UPDATE_LOCALE:
|
||||||
|
@ -67,8 +76,8 @@ export function GlobalStore(props: { children: ReactNode }): ReactElement {
|
||||||
|
|
||||||
// save theme when it is changed
|
// save theme when it is changed
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
storage.setItem("theme", globalState.theme)
|
storage.setItem("theme", globalState.currentTheme)
|
||||||
}, [globalState.theme])
|
}, [globalState.currentTheme])
|
||||||
|
|
||||||
// save locale when it is changed
|
// save locale when it is changed
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
@ -2,8 +2,9 @@
|
||||||
* PostList.tsx
|
* PostList.tsx
|
||||||
* show posts in recent order
|
* show posts in recent order
|
||||||
*/
|
*/
|
||||||
|
import type { Map } from "../../../types/types"
|
||||||
|
|
||||||
import { useContext, useEffect, useState } from "react"
|
import { useCallback, useContext, useEffect, useState } from "react"
|
||||||
import { Helmet } from "react-helmet-async"
|
import { Helmet } from "react-helmet-async"
|
||||||
import styled from "styled-components"
|
import styled from "styled-components"
|
||||||
|
|
||||||
|
@ -11,25 +12,20 @@ import PostCard from "../../components/PostCard"
|
||||||
import ShowMoreButton from "./ShowMoreButton"
|
import ShowMoreButton from "./ShowMoreButton"
|
||||||
|
|
||||||
import _map from "../../data/map.json"
|
import _map from "../../data/map.json"
|
||||||
import theming from "../../styles/theming"
|
|
||||||
|
|
||||||
import { globalContext } from "../../globalContext"
|
import { globalContext } from "../../globalContext"
|
||||||
|
|
||||||
import type { Map } from "../../../types/types"
|
|
||||||
|
|
||||||
const map: Map = _map
|
const map: Map = _map
|
||||||
|
|
||||||
const StyledPostList = styled.div`
|
const PostList = styled.div`
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
color: ${(props) =>
|
color: ${({ theme }) => theme.theme.color.text.default};
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: "#111111",
|
|
||||||
dark: "#EEEEEE",
|
|
||||||
})};
|
|
||||||
`
|
`
|
||||||
|
|
||||||
const Home = () => {
|
export default () => {
|
||||||
const { globalState } = useContext(globalContext)
|
const { globalState } = useContext(globalContext)
|
||||||
const { locale } = globalState
|
const { locale } = globalState
|
||||||
|
|
||||||
|
@ -37,7 +33,7 @@ const Home = () => {
|
||||||
const [postsLength, setPostsLength] = useState(0)
|
const [postsLength, setPostsLength] = useState(0)
|
||||||
const [postCards, setPostCards] = useState<JSX.Element[]>([])
|
const [postCards, setPostCards] = useState<JSX.Element[]>([])
|
||||||
|
|
||||||
function loadPostCards() {
|
const loadPostCards = useCallback(() => {
|
||||||
let postCount = 0
|
let postCount = 0
|
||||||
const postCards = [] as JSX.Element[]
|
const postCards = [] as JSX.Element[]
|
||||||
|
|
||||||
|
@ -65,7 +61,7 @@ const Home = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
setPostCards(postCards)
|
setPostCards(postCards)
|
||||||
}
|
}, [howMany, postCards])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
loadPostCards()
|
loadPostCards()
|
||||||
|
@ -81,9 +77,11 @@ const Home = () => {
|
||||||
<meta property="og:image" content="/icon/icon.svg" />
|
<meta property="og:image" content="/icon/icon.svg" />
|
||||||
</Helmet>
|
</Helmet>
|
||||||
|
|
||||||
<StyledPostList>
|
<PostList>
|
||||||
<h1>{locale == "en" ? "Recent Posts" : "최근 포스트"}</h1>
|
<h1>{locale == "en" ? "Recent Posts" : "최근 포스트"}</h1>
|
||||||
|
|
||||||
{postCards}
|
{postCards}
|
||||||
|
|
||||||
{postsLength > howMany && (
|
{postsLength > howMany && (
|
||||||
<ShowMoreButton
|
<ShowMoreButton
|
||||||
action={() => {
|
action={() => {
|
||||||
|
@ -91,9 +89,7 @@ const Home = () => {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</StyledPostList>
|
</PostList>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Home
|
|
||||||
|
|
|
@ -1,54 +1,21 @@
|
||||||
import { useContext } from "react"
|
import { useContext } from "react"
|
||||||
import styled from "styled-components"
|
import styled from "styled-components"
|
||||||
|
|
||||||
import theming from "../../styles/theming"
|
|
||||||
import { globalContext } from "../../globalContext"
|
import { globalContext } from "../../globalContext"
|
||||||
|
import buttonStyle from "../../styles/button"
|
||||||
|
|
||||||
const Button = styled.button`
|
const Button = styled.button`
|
||||||
/* size */
|
${buttonStyle}
|
||||||
|
|
||||||
padding: 1rem;
|
/* center div */
|
||||||
|
margin: 0 auto;
|
||||||
/* styling */
|
|
||||||
|
|
||||||
display: inline-block;
|
|
||||||
border: none;
|
|
||||||
cursor: pointer;
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
|
|
||||||
/* text */
|
|
||||||
|
|
||||||
text-align: center;
|
|
||||||
text-decoration: none;
|
|
||||||
font-size: 1rem;
|
|
||||||
|
|
||||||
/* colors */
|
|
||||||
|
|
||||||
color: ${(props) =>
|
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: "black",
|
|
||||||
dark: "#CFD0D0",
|
|
||||||
})};
|
|
||||||
background-color: ${(props) =>
|
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: theming.light.backgroundColor2,
|
|
||||||
dark: theming.dark.backgroundColor2,
|
|
||||||
})};
|
|
||||||
|
|
||||||
:hover {
|
|
||||||
background-color: ${(props) =>
|
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: theming.light.backgroundColor0,
|
|
||||||
dark: theming.dark.backgroundColor0,
|
|
||||||
})};
|
|
||||||
}
|
|
||||||
`
|
`
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
action(): void
|
action(): void
|
||||||
}
|
}
|
||||||
|
|
||||||
const ShowMoreButton = (props: Props) => {
|
export default (props: Props) => {
|
||||||
const { globalState } = useContext(globalContext)
|
const { globalState } = useContext(globalContext)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -57,5 +24,3 @@ const ShowMoreButton = (props: Props) => {
|
||||||
</Button>
|
</Button>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ShowMoreButton
|
|
||||||
|
|
|
@ -8,14 +8,9 @@ import {
|
||||||
} from "@fortawesome/free-solid-svg-icons"
|
} from "@fortawesome/free-solid-svg-icons"
|
||||||
|
|
||||||
import { PageData } from "../../../types/types"
|
import { PageData } from "../../../types/types"
|
||||||
import theming from "../../styles/theming"
|
|
||||||
|
|
||||||
const StyledMetaContainer = styled.div`
|
const StyledMetaContainer = styled.div`
|
||||||
color: ${(props) =>
|
color: ${({ theme }) => theme.theme.color.text.gray};
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: "#555",
|
|
||||||
dark: "#CCC",
|
|
||||||
})};
|
|
||||||
`
|
`
|
||||||
|
|
||||||
const Meta = (props: { fetchedPage: PageData }) => {
|
const Meta = (props: { fetchedPage: PageData }) => {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { useContext } from "react"
|
import { useContext } from "react"
|
||||||
import styled, { css } from "styled-components"
|
import styled from "styled-components"
|
||||||
import { Link } from "react-router-dom"
|
import { Link } from "react-router-dom"
|
||||||
|
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
||||||
|
@ -9,8 +9,7 @@ import {
|
||||||
faListUl,
|
faListUl,
|
||||||
} from "@fortawesome/free-solid-svg-icons"
|
} from "@fortawesome/free-solid-svg-icons"
|
||||||
|
|
||||||
import theming from "../../styles/theming"
|
import buttonStyle from "../../styles/button"
|
||||||
|
|
||||||
import { globalContext } from "../../globalContext"
|
import { globalContext } from "../../globalContext"
|
||||||
|
|
||||||
const Container = styled.div`
|
const Container = styled.div`
|
||||||
|
@ -18,26 +17,6 @@ const Container = styled.div`
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
`
|
`
|
||||||
|
|
||||||
const buttonStyle = css`
|
|
||||||
${theming.styles.navbarButtonStyle}
|
|
||||||
|
|
||||||
background-color: ${(props) =>
|
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
dark: "#202225",
|
|
||||||
light: "#EEEEEE",
|
|
||||||
})};
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
height: 3rem;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: ${(props) =>
|
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
dark: theming.dark.backgroundColor1,
|
|
||||||
light: theming.light.backgroundColor2,
|
|
||||||
})};
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
const Button = styled.div`
|
const Button = styled.div`
|
||||||
${buttonStyle}
|
${buttonStyle}
|
||||||
`
|
`
|
||||||
|
@ -47,14 +26,6 @@ const DisabledButton = styled.div`
|
||||||
|
|
||||||
color: grey;
|
color: grey;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: ${(props) =>
|
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
dark: "#202225",
|
|
||||||
light: "#EEEEEE",
|
|
||||||
})};
|
|
||||||
}
|
|
||||||
`
|
`
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|
|
@ -6,7 +6,6 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
||||||
import { faCaretDown, faCaretUp } from "@fortawesome/free-solid-svg-icons"
|
import { faCaretDown, faCaretUp } from "@fortawesome/free-solid-svg-icons"
|
||||||
import styled from "styled-components"
|
import styled from "styled-components"
|
||||||
|
|
||||||
import theming from "../../styles/theming"
|
|
||||||
import { globalContext } from "../../globalContext"
|
import { globalContext } from "../../globalContext"
|
||||||
|
|
||||||
const StyledTocToggleButton = styled.button`
|
const StyledTocToggleButton = styled.button`
|
||||||
|
@ -16,11 +15,7 @@ const StyledTocToggleButton = styled.button`
|
||||||
background-color: rgba(0, 0, 0, 0);
|
background-color: rgba(0, 0, 0, 0);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
color: ${(props) =>
|
color: ${({ theme }) => theme.theme.color.text.highContrast};
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: "black",
|
|
||||||
dark: "white",
|
|
||||||
})};
|
|
||||||
`
|
`
|
||||||
|
|
||||||
const StyledCollapseContainer = styled.div`
|
const StyledCollapseContainer = styled.div`
|
||||||
|
|
|
@ -6,21 +6,21 @@ import Badge from "../../components/Badge"
|
||||||
import { cardCSS } from "../../components/Card"
|
import { cardCSS } from "../../components/Card"
|
||||||
|
|
||||||
import { PortfolioProject } from "../../../types/types"
|
import { PortfolioProject } from "../../../types/types"
|
||||||
import theming from "../../styles/theming"
|
|
||||||
import { globalContext } from "../../globalContext"
|
import { globalContext } from "../../globalContext"
|
||||||
|
|
||||||
const StyledProjectCard = styled.div`
|
const StyledProjectCard = styled.div`
|
||||||
${cardCSS}
|
${cardCSS}
|
||||||
${theming.styles.hoverCard}
|
|
||||||
|
|
||||||
|
color: ${(props) => props.theme.theme.color.text.default};
|
||||||
margin-bottom: 2rem;
|
margin-bottom: 2rem;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
|
|
||||||
color: ${(props) =>
|
:hover {
|
||||||
theming.theme(props.theme.currentTheme, {
|
cursor: pointer;
|
||||||
light: theming.light.color1,
|
|
||||||
dark: theming.dark.color1,
|
box-shadow: 0 4px 10px
|
||||||
})};
|
${(props) => props.theme.theme.component.card.color.hoverGlow};
|
||||||
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
const StyledImg = styled.img`
|
const StyledImg = styled.img`
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
import { DateRange } from "react-date-range"
|
import { DateRange } from "react-date-range"
|
||||||
import styled from "styled-components"
|
import styled from "styled-components"
|
||||||
|
|
||||||
import theming from "../../styles/theming"
|
|
||||||
|
|
||||||
export const DateRangeControl = styled.div`
|
export const DateRangeControl = styled.div`
|
||||||
width: 350px;
|
width: 350px;
|
||||||
|
|
||||||
@media screen and (max-width: ${theming.size.screen_size2}) {
|
@media screen and (max-width: ${(props) =>
|
||||||
|
props.theme.theme.maxDisplayWidth.mobile}) {
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
/* eslint-disable react/prop-types */
|
import { useCallback, useContext, useEffect, useState } from "react"
|
||||||
|
|
||||||
import { useContext, useEffect, useState } from "react"
|
|
||||||
import styled from "styled-components"
|
import styled from "styled-components"
|
||||||
import { useSearchParams } from "react-router-dom"
|
import { useSearchParams } from "react-router-dom"
|
||||||
import { Helmet } from "react-helmet-async"
|
import { Helmet } from "react-helmet-async"
|
||||||
|
@ -10,7 +8,6 @@ import elasticlunr from "elasticlunr" // search engine
|
||||||
|
|
||||||
import _map from "../../data/map.json"
|
import _map from "../../data/map.json"
|
||||||
import searchData from "../../data/search.json"
|
import searchData from "../../data/search.json"
|
||||||
import theming from "../../styles/theming"
|
|
||||||
|
|
||||||
import Loading from "../../components/Loading"
|
import Loading from "../../components/Loading"
|
||||||
import PostCard from "../../components/PostCard"
|
import PostCard from "../../components/PostCard"
|
||||||
|
@ -54,7 +51,8 @@ const StyledSearchContainer = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
|
|
||||||
@media screen and (max-width: ${theming.size.screen_size2}) {
|
@media screen and (max-width: ${(props) =>
|
||||||
|
props.theme.theme.maxDisplayWidth.mobile}) {
|
||||||
flex-direction: column-reverse;
|
flex-direction: column-reverse;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
@ -64,7 +62,8 @@ const StyledSearchControlContainer = styled.div`
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-left: 1rem;
|
margin-left: 1rem;
|
||||||
|
|
||||||
@media screen and (max-width: ${theming.size.screen_size2}) {
|
@media screen and (max-width: ${(props) =>
|
||||||
|
props.theme.theme.maxDisplayWidth.mobile}) {
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
|
@ -113,6 +112,38 @@ const Search = () => {
|
||||||
|
|
||||||
const [postCards, setPostCards] = useState<JSX.Element[]>([])
|
const [postCards, setPostCards] = useState<JSX.Element[]>([])
|
||||||
|
|
||||||
|
const doSearch = useCallback(() => {
|
||||||
|
try {
|
||||||
|
const _postCards: JSX.Element[] = []
|
||||||
|
for (const res of searchIndex.search(searchInput)) {
|
||||||
|
const postData = map.posts[res.ref]
|
||||||
|
|
||||||
|
if (
|
||||||
|
postData && // if post data exists
|
||||||
|
isDateInRange(postData.date, dateRange[0]) && // date is within range
|
||||||
|
isSelectedTagsInPost(selectedTags, postData.tags) // if post include tags
|
||||||
|
) {
|
||||||
|
_postCards.push(
|
||||||
|
<PostCard
|
||||||
|
key={res.ref}
|
||||||
|
postData={{
|
||||||
|
content_id: res.ref,
|
||||||
|
...postData,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// apply search result
|
||||||
|
setPostCards(_postCards)
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-empty
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
}
|
||||||
|
}, [dateRange, selectedTags, searchInput])
|
||||||
|
|
||||||
// parse search parameters
|
// parse search parameters
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
for (const [key, value] of URLSearchParams.entries()) {
|
for (const [key, value] of URLSearchParams.entries()) {
|
||||||
|
@ -186,38 +217,6 @@ const Search = () => {
|
||||||
return () => clearTimeout(delayDebounceFn)
|
return () => clearTimeout(delayDebounceFn)
|
||||||
}, [searchInput])
|
}, [searchInput])
|
||||||
|
|
||||||
function doSearch() {
|
|
||||||
try {
|
|
||||||
const _postCards: JSX.Element[] = []
|
|
||||||
for (const res of searchIndex.search(searchInput)) {
|
|
||||||
const postData = map.posts[res.ref]
|
|
||||||
|
|
||||||
if (
|
|
||||||
postData && // if post data exists
|
|
||||||
isDateInRange(postData.date, dateRange[0]) && // date is within range
|
|
||||||
isSelectedTagsInPost(selectedTags, postData.tags) // if post include tags
|
|
||||||
) {
|
|
||||||
_postCards.push(
|
|
||||||
<PostCard
|
|
||||||
key={res.ref}
|
|
||||||
postData={{
|
|
||||||
content_id: res.ref,
|
|
||||||
...postData,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// apply search result
|
|
||||||
setPostCards(_postCards)
|
|
||||||
|
|
||||||
// eslint-disable-next-line no-empty
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!initialized) return <Loading />
|
if (!initialized) return <Loading />
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -1,32 +1,30 @@
|
||||||
import styled from "styled-components"
|
import styled from "styled-components"
|
||||||
|
|
||||||
import theming from "../../styles/theming"
|
export default styled.input`
|
||||||
|
|
||||||
const StyledSearchBar = styled.input`
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-radius: 100px; /* arbitrarily large value */
|
border-radius: 100px; /* arbitrarily large value */
|
||||||
height: 2.5rem;
|
height: 2.5rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
outline: none;
|
outline: none;
|
||||||
|
color: ${({ theme }) => theme.theme.color.text.default};
|
||||||
border: ${(props) =>
|
border: 1px solid
|
||||||
theming.theme(props.theme.currentTheme, {
|
${(props) => props.theme.theme.component.input.color.border.default};
|
||||||
light: "1px solid #ccc",
|
|
||||||
dark: "1px solid #555",
|
|
||||||
})};
|
|
||||||
|
|
||||||
background-color: ${(props) =>
|
background-color: ${(props) =>
|
||||||
theming.theme(props.theme.currentTheme, {
|
props.theme.theme.component.input.color.background.default};
|
||||||
light: theming.dark.color1,
|
|
||||||
dark: theming.dark.backgroundColor1,
|
|
||||||
})};
|
|
||||||
|
|
||||||
color: ${(props) =>
|
::placeholder {
|
||||||
theming.theme(props.theme.currentTheme, {
|
color: ${(props) => props.theme.theme.component.input.color.placeHolder};
|
||||||
light: theming.light.color1,
|
opacity: 1;
|
||||||
dark: theming.dark.color1,
|
}
|
||||||
})};
|
|
||||||
|
&:hover {
|
||||||
|
border: 1px solid
|
||||||
|
${({ theme }) => theme.theme.component.input.color.border.hover};
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
border: 1px solid
|
||||||
|
${({ theme }) => theme.theme.component.input.color.border.focus};
|
||||||
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
export default StyledSearchBar
|
|
||||||
|
|
|
@ -2,8 +2,6 @@ import { useContext } from "react"
|
||||||
import styled from "styled-components"
|
import styled from "styled-components"
|
||||||
import Select from "react-select"
|
import Select from "react-select"
|
||||||
|
|
||||||
import theming from "../../styles/theming"
|
|
||||||
|
|
||||||
import _map from "../../data/map.json"
|
import _map from "../../data/map.json"
|
||||||
import { globalContext } from "../../globalContext"
|
import { globalContext } from "../../globalContext"
|
||||||
|
|
||||||
|
@ -33,24 +31,19 @@ interface TagSelectProps {
|
||||||
|
|
||||||
const TagSelect = (props: TagSelectProps) => {
|
const TagSelect = (props: TagSelectProps) => {
|
||||||
const { globalState } = useContext(globalContext)
|
const { globalState } = useContext(globalContext)
|
||||||
|
const { theme } = globalState
|
||||||
const locale = globalState.locale
|
const locale = globalState.locale
|
||||||
const currentTheme = globalState.theme
|
|
||||||
const { onChange, defaultValue: selectedTags } = props
|
const { onChange, defaultValue: selectedTags } = props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledReactTagsContainer>
|
<StyledReactTagsContainer>
|
||||||
<Select
|
<Select
|
||||||
placeholder={locale == "en" ? "Select tags..." : "태그를 선택하세요"}
|
placeholder={locale == "en" ? "Select tags..." : "태그를 선택하세요"}
|
||||||
theme={(theme) => ({
|
theme={(reactSelectTheme) => ({
|
||||||
...theme,
|
...reactSelectTheme,
|
||||||
colors: {
|
colors: {
|
||||||
...theme.colors,
|
...reactSelectTheme.colors,
|
||||||
neutral0: theming
|
neutral0: theme.component.input.color.background.default,
|
||||||
.theme(currentTheme, {
|
|
||||||
light: theming.light.backgroundColor1,
|
|
||||||
dark: theming.dark.backgroundColor1,
|
|
||||||
})
|
|
||||||
.toString(),
|
|
||||||
neutral5: "hsl(0, 0%, 20%)",
|
neutral5: "hsl(0, 0%, 20%)",
|
||||||
neutral10: "hsl(0, 0%, 30%)",
|
neutral10: "hsl(0, 0%, 30%)",
|
||||||
neutral20: "hsl(0, 0%, 40%)",
|
neutral20: "hsl(0, 0%, 40%)",
|
||||||
|
@ -68,59 +61,42 @@ const TagSelect = (props: TagSelectProps) => {
|
||||||
styles={{
|
styles={{
|
||||||
option: (styles) => ({
|
option: (styles) => ({
|
||||||
...styles,
|
...styles,
|
||||||
backgroundColor: theming
|
backgroundColor: theme.component.input.color.background.default,
|
||||||
.theme(currentTheme, {
|
color: theme.color.text.default,
|
||||||
light: theming.light.backgroundColor1,
|
|
||||||
dark: theming.dark.backgroundColor1,
|
|
||||||
})
|
|
||||||
.toString(),
|
|
||||||
color: theming
|
|
||||||
.theme(currentTheme, {
|
|
||||||
light: theming.light.color1,
|
|
||||||
dark: theming.dark.color1,
|
|
||||||
})
|
|
||||||
.toString(),
|
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
padding: 10,
|
|
||||||
":hover": {
|
":hover": {
|
||||||
backgroundColor: theming
|
backgroundColor: theme.component.input.color.background.itemHover,
|
||||||
.theme(currentTheme, {
|
|
||||||
light: theming.light.backgroundColor0,
|
|
||||||
dark: theming.dark.backgroundColor0,
|
|
||||||
})
|
|
||||||
.toString(),
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
control: (styles) => ({
|
control: (styles) => ({
|
||||||
...styles,
|
...styles,
|
||||||
backgroundColor: theming
|
backgroundColor: theme.component.input.color.background.default,
|
||||||
.theme(currentTheme, {
|
border: `1px solid ${theme.component.input.color.border.default}`,
|
||||||
light: theming.light.backgroundColor1,
|
":hover": {
|
||||||
dark: theming.dark.backgroundColor1,
|
border: `1px solid ${theme.component.input.color.border.hover}`,
|
||||||
})
|
},
|
||||||
.toString(),
|
":focus": {
|
||||||
border: theming.theme(currentTheme, {
|
border: `1px solid ${theme.component.input.color.border.focus}`,
|
||||||
light: "1px solid #ccc",
|
},
|
||||||
dark: "1px solid #555",
|
|
||||||
}),
|
|
||||||
}),
|
}),
|
||||||
multiValue: (styles) => ({
|
multiValue: (styles) => ({
|
||||||
...styles,
|
...styles,
|
||||||
color: "white",
|
color: theme.color.text.default,
|
||||||
backgroundColor: theming.light.linkColor,
|
backgroundColor: theme.component.ui.color.background.default,
|
||||||
borderRadius: "5px",
|
borderRadius: "10px",
|
||||||
}),
|
}),
|
||||||
multiValueLabel: (styles) => ({
|
multiValueLabel: (styles) => ({
|
||||||
...styles,
|
...styles,
|
||||||
|
color: theme.color.text.default,
|
||||||
marginLeft: "0.2rem",
|
marginLeft: "0.2rem",
|
||||||
marginRight: "0.2rem",
|
|
||||||
}),
|
}),
|
||||||
multiValueRemove: (styles) => ({
|
multiValueRemove: (styles) => ({
|
||||||
...styles,
|
...styles,
|
||||||
marginLeft: "0.2rem",
|
marginRight: "0.3rem",
|
||||||
|
cursor: "pointer",
|
||||||
|
color: theme.component.input.color.placeHolder,
|
||||||
":hover": {
|
":hover": {
|
||||||
backgroundColor: "white",
|
color: theme.color.text.default,
|
||||||
color: theming.light.linkColor,
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
}}
|
}}
|
||||||
|
|
32
apps/blog/src/styles/anchor.ts
Normal file
32
apps/blog/src/styles/anchor.ts
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
import { css } from "styled-components"
|
||||||
|
|
||||||
|
export default css`
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
color: ${(props) => props.theme.theme.component.anchor.color.default};
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: ${(props) => props.theme.theme.component.anchor.color.hover};
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
color: ${(props) => props.theme.theme.component.anchor.color.active};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The "#" thingy used beside headers */
|
||||||
|
a.header-anchor {
|
||||||
|
/* compensate for navbar height*/
|
||||||
|
display: inline-block;
|
||||||
|
margin-top: 4.5rem;
|
||||||
|
|
||||||
|
color: ${(props) => props.theme.theme.component.anchor.color.header};
|
||||||
|
}
|
||||||
|
|
||||||
|
/* footnote anchors */
|
||||||
|
a[id^="fnref"] {
|
||||||
|
display: inline;
|
||||||
|
padding-top: 4.5rem;
|
||||||
|
}
|
||||||
|
`
|
19
apps/blog/src/styles/blockQuote.ts
Normal file
19
apps/blog/src/styles/blockQuote.ts
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import { css } from "styled-components"
|
||||||
|
|
||||||
|
export default css`
|
||||||
|
blockquote {
|
||||||
|
background-color: ${({ theme }) =>
|
||||||
|
theme.theme.component.blockQuote.color.background};
|
||||||
|
border-left: 0.4rem solid
|
||||||
|
${({ theme }) => theme.theme.component.blockQuote.color.borderLeft};
|
||||||
|
padding-top: 0.1rem;
|
||||||
|
padding-right: 1rem;
|
||||||
|
padding-bottom: 0.1rem;
|
||||||
|
padding-left: 1.5rem;
|
||||||
|
|
||||||
|
@media screen and (max-width: ${({ theme }) =>
|
||||||
|
theme.theme.maxDisplayWidth.mobile}) {
|
||||||
|
margin: 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
37
apps/blog/src/styles/button.tsx
Normal file
37
apps/blog/src/styles/button.tsx
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import { css } from "styled-components"
|
||||||
|
|
||||||
|
export default css`
|
||||||
|
/* style */
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
cursor: pointer;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border: none;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
|
||||||
|
/* size */
|
||||||
|
|
||||||
|
height: 3rem;
|
||||||
|
min-width: 2.5rem;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 1rem 0 1rem;
|
||||||
|
|
||||||
|
/* text */
|
||||||
|
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
/* color */
|
||||||
|
|
||||||
|
color: ${({ theme }) => theme.theme.color.text.default};
|
||||||
|
background-color: ${({ theme }) =>
|
||||||
|
theme.theme.component.ui.color.background.default};
|
||||||
|
&:hover {
|
||||||
|
background-color: ${({ theme }) =>
|
||||||
|
theme.theme.component.ui.color.background.hover};
|
||||||
|
}
|
||||||
|
|
||||||
|
/* animation */
|
||||||
|
|
||||||
|
transition: transform 0.1s linear;
|
||||||
|
`
|
37
apps/blog/src/styles/code.ts
Normal file
37
apps/blog/src/styles/code.ts
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import { css } from "styled-components"
|
||||||
|
|
||||||
|
export default css`
|
||||||
|
/* highlight.js code style */
|
||||||
|
${({ theme }) => theme.theme.component.code.block.style}
|
||||||
|
|
||||||
|
/* inline code */
|
||||||
|
:not(pre) > code {
|
||||||
|
font-family: ${({ theme }) => theme.theme.font.monospace};
|
||||||
|
word-wrap: break-word;
|
||||||
|
color: ${({ theme }) => theme.theme.component.code.inline.color.text};
|
||||||
|
background-color: ${({ theme }) =>
|
||||||
|
theme.theme.component.code.inline.color.background};
|
||||||
|
border: 1px solid
|
||||||
|
${({ theme }) => theme.theme.component.code.inline.color.border};
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 0 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* code block */
|
||||||
|
pre > code {
|
||||||
|
font-family: ${(props) => props.theme.theme.font.monospace};
|
||||||
|
border: 1px solid
|
||||||
|
${({ theme }) => theme.theme.component.code.block.color.border};
|
||||||
|
}
|
||||||
|
|
||||||
|
/* // todo: fix highlight not working properly when scrolled horizontally // */
|
||||||
|
.highlighted-line {
|
||||||
|
background-color: ${({ theme }) =>
|
||||||
|
theme.theme.component.code.block.color.highlight};
|
||||||
|
|
||||||
|
display: block;
|
||||||
|
min-width: min-content;
|
||||||
|
margin: 0 -1rem;
|
||||||
|
padding: 0 1rem;
|
||||||
|
}
|
||||||
|
`
|
|
@ -1,102 +0,0 @@
|
||||||
/**
|
|
||||||
* from node_modules/highlight.js/styles/atom-one-dark-reasonable.css
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { css } from "styled-components"
|
|
||||||
|
|
||||||
export default css`
|
|
||||||
pre code.hljs {
|
|
||||||
display: block;
|
|
||||||
overflow-x: auto;
|
|
||||||
padding: 1em;
|
|
||||||
}
|
|
||||||
code.hljs {
|
|
||||||
padding: 3px 5px;
|
|
||||||
}
|
|
||||||
.hljs {
|
|
||||||
color: #abb2bf;
|
|
||||||
background: #282c34;
|
|
||||||
}
|
|
||||||
.hljs-keyword,
|
|
||||||
.hljs-operator,
|
|
||||||
.hljs-pattern-match {
|
|
||||||
color: #f92672;
|
|
||||||
}
|
|
||||||
.hljs-function,
|
|
||||||
.hljs-pattern-match .hljs-constructor {
|
|
||||||
color: #61aeee;
|
|
||||||
}
|
|
||||||
.hljs-function .hljs-params {
|
|
||||||
color: #a6e22e;
|
|
||||||
}
|
|
||||||
.hljs-function .hljs-params .hljs-typing {
|
|
||||||
color: #fd971f;
|
|
||||||
}
|
|
||||||
.hljs-module-access .hljs-module {
|
|
||||||
color: #7e57c2;
|
|
||||||
}
|
|
||||||
.hljs-constructor {
|
|
||||||
color: #e2b93d;
|
|
||||||
}
|
|
||||||
.hljs-constructor .hljs-string {
|
|
||||||
color: #9ccc65;
|
|
||||||
}
|
|
||||||
.hljs-comment,
|
|
||||||
.hljs-quote {
|
|
||||||
color: #b18eb1;
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
.hljs-doctag,
|
|
||||||
.hljs-formula {
|
|
||||||
color: #c678dd;
|
|
||||||
}
|
|
||||||
.hljs-deletion,
|
|
||||||
.hljs-name,
|
|
||||||
.hljs-section,
|
|
||||||
.hljs-selector-tag,
|
|
||||||
.hljs-subst {
|
|
||||||
color: #e06c75;
|
|
||||||
}
|
|
||||||
.hljs-literal {
|
|
||||||
color: #56b6c2;
|
|
||||||
}
|
|
||||||
.hljs-addition,
|
|
||||||
.hljs-attribute,
|
|
||||||
.hljs-meta .hljs-string,
|
|
||||||
.hljs-regexp,
|
|
||||||
.hljs-string {
|
|
||||||
color: #98c379;
|
|
||||||
}
|
|
||||||
.hljs-built_in,
|
|
||||||
.hljs-class .hljs-title,
|
|
||||||
.hljs-title.class_ {
|
|
||||||
color: #e6c07b;
|
|
||||||
}
|
|
||||||
.hljs-attr,
|
|
||||||
.hljs-number,
|
|
||||||
.hljs-selector-attr,
|
|
||||||
.hljs-selector-class,
|
|
||||||
.hljs-selector-pseudo,
|
|
||||||
.hljs-template-variable,
|
|
||||||
.hljs-type,
|
|
||||||
.hljs-variable {
|
|
||||||
color: #d19a66;
|
|
||||||
}
|
|
||||||
.hljs-bullet,
|
|
||||||
.hljs-link,
|
|
||||||
.hljs-meta,
|
|
||||||
.hljs-selector-id,
|
|
||||||
.hljs-symbol,
|
|
||||||
.hljs-title {
|
|
||||||
color: #61aeee;
|
|
||||||
}
|
|
||||||
.hljs-emphasis {
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
.hljs-strong {
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
.hljs-link {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
`
|
|
|
@ -1,85 +0,0 @@
|
||||||
/**
|
|
||||||
* from node_modules/highlight.js/styles/default.css
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { css } from "styled-components"
|
|
||||||
|
|
||||||
export default css`
|
|
||||||
pre code.hljs {
|
|
||||||
display: block;
|
|
||||||
overflow-x: auto;
|
|
||||||
padding: 1em;
|
|
||||||
}
|
|
||||||
code.hljs {
|
|
||||||
padding: 3px 5px;
|
|
||||||
}
|
|
||||||
.hljs {
|
|
||||||
background: #f0f0f0;
|
|
||||||
color: #444;
|
|
||||||
}
|
|
||||||
.hljs-comment {
|
|
||||||
color: #888;
|
|
||||||
}
|
|
||||||
.hljs-punctuation,
|
|
||||||
.hljs-tag {
|
|
||||||
color: #444a;
|
|
||||||
}
|
|
||||||
.hljs-tag .hljs-attr,
|
|
||||||
.hljs-tag .hljs-name {
|
|
||||||
color: #444;
|
|
||||||
}
|
|
||||||
.hljs-attribute,
|
|
||||||
.hljs-doctag,
|
|
||||||
.hljs-keyword,
|
|
||||||
.hljs-meta .hljs-keyword,
|
|
||||||
.hljs-name,
|
|
||||||
.hljs-selector-tag {
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
.hljs-deletion,
|
|
||||||
.hljs-number,
|
|
||||||
.hljs-quote,
|
|
||||||
.hljs-selector-class,
|
|
||||||
.hljs-selector-id,
|
|
||||||
.hljs-string,
|
|
||||||
.hljs-template-tag,
|
|
||||||
.hljs-type {
|
|
||||||
color: #800;
|
|
||||||
}
|
|
||||||
.hljs-section,
|
|
||||||
.hljs-title {
|
|
||||||
color: #800;
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
.hljs-link,
|
|
||||||
.hljs-operator,
|
|
||||||
.hljs-regexp,
|
|
||||||
.hljs-selector-attr,
|
|
||||||
.hljs-selector-pseudo,
|
|
||||||
.hljs-symbol,
|
|
||||||
.hljs-template-variable,
|
|
||||||
.hljs-variable {
|
|
||||||
color: #bc6060;
|
|
||||||
}
|
|
||||||
.hljs-literal {
|
|
||||||
color: #78a960;
|
|
||||||
}
|
|
||||||
.hljs-addition,
|
|
||||||
.hljs-built_in,
|
|
||||||
.hljs-bullet,
|
|
||||||
.hljs-code {
|
|
||||||
color: #397300;
|
|
||||||
}
|
|
||||||
.hljs-meta {
|
|
||||||
color: #1f7199;
|
|
||||||
}
|
|
||||||
.hljs-meta .hljs-string {
|
|
||||||
color: #4d99bf;
|
|
||||||
}
|
|
||||||
.hljs-emphasis {
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
.hljs-strong {
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
`
|
|
|
@ -1,285 +1,16 @@
|
||||||
import { createGlobalStyle, css } from "styled-components"
|
import { createGlobalStyle, css } from "styled-components"
|
||||||
|
|
||||||
import codeblockLightCSS from "./codeblock-light"
|
|
||||||
import codeblockDarkCSS from "./codeblock-dark"
|
|
||||||
|
|
||||||
import "katex/dist/katex.min.css"
|
import "katex/dist/katex.min.css"
|
||||||
|
|
||||||
import theming from "./theming"
|
import anchorCSS from "./anchor"
|
||||||
|
import scrollbarCSS from "./scrollbar"
|
||||||
const anchorCSS = css`
|
import codeCSS from "./code"
|
||||||
a {
|
import kbdCSS from "./kbd"
|
||||||
text-decoration: none;
|
import tableCSS from "./table"
|
||||||
|
import blockquoteCSS from "./blockQuote"
|
||||||
color: ${(props) =>
|
import hrCSS from "./hr"
|
||||||
theming.theme(props.theme.currentTheme, {
|
import headerCSS from "./header"
|
||||||
light: theming.light.linkColor,
|
import markCSS from "./mark"
|
||||||
dark: theming.dark.linkColor,
|
import katexCSS from "./katex"
|
||||||
})};
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: ${(props) =>
|
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: theming.dark.linkColor,
|
|
||||||
dark: theming.light.linkColor,
|
|
||||||
})};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The "#" thingy used beside headers */
|
|
||||||
a.header-anchor {
|
|
||||||
/* compensate for navbar height*/
|
|
||||||
display: inline-block;
|
|
||||||
margin-top: 4.5rem;
|
|
||||||
|
|
||||||
color: ${(props) =>
|
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: "lightgray",
|
|
||||||
dark: "lightslategray",
|
|
||||||
})};
|
|
||||||
}
|
|
||||||
|
|
||||||
/* footnote anchors */
|
|
||||||
a[id^="fnref"] {
|
|
||||||
display: inline;
|
|
||||||
padding-top: 4.5rem;
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
const scrollbarCSS = css`
|
|
||||||
body::-webkit-scrollbar {
|
|
||||||
width: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body::-webkit-scrollbar-track {
|
|
||||||
border-radius: ${theming.size.x2_small};
|
|
||||||
|
|
||||||
background: ${(props) =>
|
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: theming.light.backgroundColor0,
|
|
||||||
dark: theming.dark.backgroundColor0,
|
|
||||||
})};
|
|
||||||
box-shadow: inset 0 0 5px rgb(0 0 0 / 10%);
|
|
||||||
}
|
|
||||||
|
|
||||||
body::-webkit-scrollbar-thumb {
|
|
||||||
border-radius: ${theming.size.x2_small};
|
|
||||||
background: ${(props) =>
|
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: theming.light.backgroundColor2,
|
|
||||||
dark: "#888888",
|
|
||||||
})};
|
|
||||||
box-shadow: inset 0 0 10px rgb(0 0 0 / 20%);
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
const codeCSS = css`
|
|
||||||
${(props) => {
|
|
||||||
switch (props.theme.currentTheme) {
|
|
||||||
case "dark":
|
|
||||||
return codeblockDarkCSS
|
|
||||||
case "light":
|
|
||||||
return codeblockLightCSS
|
|
||||||
default:
|
|
||||||
return codeblockDarkCSS
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
|
|
||||||
/* line code */
|
|
||||||
:not(pre) > code {
|
|
||||||
font-family: ${theming.font.code};
|
|
||||||
word-wrap: break-word;
|
|
||||||
color: ${(props) =>
|
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: theming.light.color1,
|
|
||||||
dark: theming.dark.color1,
|
|
||||||
})};
|
|
||||||
background-color: ${(props) =>
|
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: "#eee",
|
|
||||||
dark: "#444", // I hope no hardcore christian finds this code
|
|
||||||
})};
|
|
||||||
border: ${(props) =>
|
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: "1px solid #BBB",
|
|
||||||
dark: "1px solid #666", // especially this
|
|
||||||
})};
|
|
||||||
border-radius: 3px;
|
|
||||||
padding: 0 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* code block */
|
|
||||||
pre > code {
|
|
||||||
font-family: ${theming.font.code};
|
|
||||||
border: ${(props) =>
|
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: "1px solid #BBB",
|
|
||||||
dark: "1px solid #555",
|
|
||||||
})};
|
|
||||||
}
|
|
||||||
|
|
||||||
/* // todo: fix highlight not working properly when scrolled horizontally // */
|
|
||||||
.highlighted-line {
|
|
||||||
background-color: ${(props) =>
|
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: "#dddddd",
|
|
||||||
dark: "#14161a",
|
|
||||||
})};
|
|
||||||
|
|
||||||
display: block;
|
|
||||||
min-width: min-content;
|
|
||||||
margin: 0 -1rem;
|
|
||||||
padding: 0 1rem;
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
const kbdCSS = css`
|
|
||||||
/* https://www.rgagnon.com/jsdetails/js-nice-effect-the-KBD-tag.html */
|
|
||||||
kbd {
|
|
||||||
margin: 0px 0.1em;
|
|
||||||
padding: 0.1em 0.6em;
|
|
||||||
border-radius: 3px;
|
|
||||||
border: ${(props) =>
|
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: "1px solid #CCCCCC",
|
|
||||||
dark: "1px solid #555555",
|
|
||||||
})};
|
|
||||||
color: ${(props) =>
|
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: "#333333",
|
|
||||||
dark: "white",
|
|
||||||
})};
|
|
||||||
line-height: 1.4;
|
|
||||||
font-size: 13.5px;
|
|
||||||
display: inline-block;
|
|
||||||
box-shadow: ${(props) =>
|
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: "0px 1px 0px rgba(0,0,0,0.2), inset 0px 0px 0px 2px white",
|
|
||||||
dark: "0px 1px 0px rgba(255,255,255,0.3), inset 0px 0px 0px 2px black",
|
|
||||||
})};
|
|
||||||
background-color: ${(props) =>
|
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: "#F7F7F7",
|
|
||||||
dark: "black",
|
|
||||||
})};
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
const tableCSS = css`
|
|
||||||
table {
|
|
||||||
border-collapse: collapse;
|
|
||||||
border-spacing: 0;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
td,
|
|
||||||
th {
|
|
||||||
padding: 8px;
|
|
||||||
border: ${(props) =>
|
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: "1px solid #ddd",
|
|
||||||
dark: "1px solid #777777",
|
|
||||||
})};
|
|
||||||
}
|
|
||||||
|
|
||||||
/* table alternating color */
|
|
||||||
tr:nth-child(even) {
|
|
||||||
background-color: ${(props) =>
|
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: "#f2f2f2",
|
|
||||||
dark: "#21272E",
|
|
||||||
})};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
const blockquoteCSS = css`
|
|
||||||
blockquote {
|
|
||||||
background-color: ${(props) =>
|
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: "rgba(0, 0, 0, 5%)",
|
|
||||||
dark: "rgba(255, 255, 255, 7%)",
|
|
||||||
})};
|
|
||||||
border-left: ${(props) =>
|
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: "0.4rem solid rgba(0, 0, 0, 10%)",
|
|
||||||
dark: "0.4rem solid rgba(255, 255, 255, 30%)",
|
|
||||||
})};
|
|
||||||
padding-top: 0.1rem;
|
|
||||||
padding-right: 1rem;
|
|
||||||
padding-bottom: 0.1rem;
|
|
||||||
padding-left: 1.5rem;
|
|
||||||
|
|
||||||
@media screen and (max-width: ${theming.size.screen_size1}) {
|
|
||||||
margin: 0.5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
const hrCSS = css`
|
|
||||||
hr {
|
|
||||||
border: 0;
|
|
||||||
border-bottom: 1px solid;
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
const headerCSS = css`
|
|
||||||
/* intentionally left out h1 */
|
|
||||||
h2,
|
|
||||||
h3,
|
|
||||||
h4,
|
|
||||||
h5,
|
|
||||||
h6 {
|
|
||||||
margin-top: -2rem;
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 2.5rem;
|
|
||||||
}
|
|
||||||
h2 {
|
|
||||||
font-size: 1.5rem;
|
|
||||||
}
|
|
||||||
h3 {
|
|
||||||
font-size: 1rem;
|
|
||||||
text-indent: 0.5rem;
|
|
||||||
}
|
|
||||||
h4 {
|
|
||||||
font-size: 1rem;
|
|
||||||
text-indent: 1rem;
|
|
||||||
}
|
|
||||||
h5 {
|
|
||||||
font-size: 1rem;
|
|
||||||
text-indent: 1.5rem;
|
|
||||||
}
|
|
||||||
h6 {
|
|
||||||
font-size: 1rem;
|
|
||||||
text-indent: 2rem;
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
const markCSS = css`
|
|
||||||
mark {
|
|
||||||
background-color: ${(props) =>
|
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: "rgba(255, 255, 0, 75%)",
|
|
||||||
dark: "rgba(255, 255, 0, 50%)",
|
|
||||||
})};
|
|
||||||
color: ${(props) =>
|
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: "black",
|
|
||||||
dark: "white",
|
|
||||||
})};
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
const katexCSS = css`
|
|
||||||
// prevent overflowing on small displays
|
|
||||||
.katex-html {
|
|
||||||
overflow: auto;
|
|
||||||
padding: 0.5rem;
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
const globalCSS = css`
|
const globalCSS = css`
|
||||||
body {
|
body {
|
||||||
|
@ -303,24 +34,16 @@ const globalCSS = css`
|
||||||
/* text */
|
/* text */
|
||||||
|
|
||||||
line-height: 2rem;
|
line-height: 2rem;
|
||||||
font-size: ${theming.size.medium};
|
font-size: 1rem;
|
||||||
font-family: ${theming.font.regular};
|
font-family: ${({ theme }) => theme.theme.font.sansSerif};
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
text-rendering: optimizeLegibility;
|
text-rendering: optimizeLegibility;
|
||||||
|
|
||||||
/* color */
|
/* color */
|
||||||
|
|
||||||
background-color: ${(props) =>
|
background-color: ${({ theme }) => theme.theme.color.background};
|
||||||
theming.theme(props.theme.currentTheme, {
|
color: ${({ theme }) => theme.theme.color.text.default};
|
||||||
light: theming.light.backgroundColor1,
|
|
||||||
dark: theming.dark.backgroundColor1,
|
|
||||||
})};
|
|
||||||
color: ${(props) =>
|
|
||||||
theming.theme(props.theme.currentTheme, {
|
|
||||||
light: theming.light.color1,
|
|
||||||
dark: theming.dark.color1,
|
|
||||||
})};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
|
|
37
apps/blog/src/styles/header.ts
Normal file
37
apps/blog/src/styles/header.ts
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import { css } from "styled-components"
|
||||||
|
|
||||||
|
export default css`
|
||||||
|
/* intentionally left out h1 */
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
margin-top: -2rem;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 2.5rem;
|
||||||
|
}
|
||||||
|
h2 {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
h3 {
|
||||||
|
font-size: 1rem;
|
||||||
|
text-indent: 0.5rem;
|
||||||
|
}
|
||||||
|
h4 {
|
||||||
|
font-size: 1rem;
|
||||||
|
text-indent: 1rem;
|
||||||
|
}
|
||||||
|
h5 {
|
||||||
|
font-size: 1rem;
|
||||||
|
text-indent: 1.5rem;
|
||||||
|
}
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
text-indent: 2rem;
|
||||||
|
}
|
||||||
|
`
|
8
apps/blog/src/styles/hr.ts
Normal file
8
apps/blog/src/styles/hr.ts
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import { css } from "styled-components"
|
||||||
|
|
||||||
|
export default css`
|
||||||
|
hr {
|
||||||
|
border: 0;
|
||||||
|
border-bottom: 1px solid;
|
||||||
|
}
|
||||||
|
`
|
9
apps/blog/src/styles/katex.ts
Normal file
9
apps/blog/src/styles/katex.ts
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import { css } from "styled-components"
|
||||||
|
|
||||||
|
export default css`
|
||||||
|
// prevent overflowing on small displays
|
||||||
|
.katex-html {
|
||||||
|
overflow: auto;
|
||||||
|
padding: 0.5rem;
|
||||||
|
}
|
||||||
|
`
|
21
apps/blog/src/styles/kbd.ts
Normal file
21
apps/blog/src/styles/kbd.ts
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import { css } from "styled-components"
|
||||||
|
|
||||||
|
export default css`
|
||||||
|
/* https://www.rgagnon.com/jsdetails/js-nice-effect-the-KBD-tag.html */
|
||||||
|
kbd {
|
||||||
|
margin: 0px 0.1em;
|
||||||
|
padding: 0.1em 0.6em;
|
||||||
|
border-radius: 3px;
|
||||||
|
border: 1px solid ${({ theme }) => theme.theme.component.kbd.color.border};
|
||||||
|
color: ${({ theme }) => theme.theme.component.kbd.color.text};
|
||||||
|
line-height: 1.4;
|
||||||
|
font-size: 13.5px;
|
||||||
|
display: inline-block;
|
||||||
|
box-shadow: 0px 1px 0px
|
||||||
|
${({ theme }) => theme.theme.component.kbd.color.outerShadow},
|
||||||
|
inset 0px 0px 0px 2px
|
||||||
|
${({ theme }) => theme.theme.component.kbd.color.innerShadow};
|
||||||
|
background-color: ${({ theme }) =>
|
||||||
|
theme.theme.component.kbd.color.background};
|
||||||
|
}
|
||||||
|
`
|
9
apps/blog/src/styles/mark.ts
Normal file
9
apps/blog/src/styles/mark.ts
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import { css } from "styled-components"
|
||||||
|
|
||||||
|
export default css`
|
||||||
|
mark {
|
||||||
|
background-color: ${({ theme }) =>
|
||||||
|
theme.theme.component.mark.color.background};
|
||||||
|
color: ${({ theme }) => theme.theme.component.mark.color.text};
|
||||||
|
}
|
||||||
|
`
|
21
apps/blog/src/styles/scrollbar.ts
Normal file
21
apps/blog/src/styles/scrollbar.ts
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import { css } from "styled-components"
|
||||||
|
|
||||||
|
export default css`
|
||||||
|
body::-webkit-scrollbar {
|
||||||
|
width: ${(props) => props.theme.theme.component.scrollbar.width};
|
||||||
|
}
|
||||||
|
|
||||||
|
body::-webkit-scrollbar-track {
|
||||||
|
border-radius: ${(props) =>
|
||||||
|
props.theme.theme.component.scrollbar.borderRadius};
|
||||||
|
background: ${(props) => props.theme.theme.component.scrollbar.color.track};
|
||||||
|
box-shadow: inset 0 0 5px rgb(0 0 0 / 10%);
|
||||||
|
}
|
||||||
|
|
||||||
|
body::-webkit-scrollbar-thumb {
|
||||||
|
border-radius: ${(props) =>
|
||||||
|
props.theme.theme.component.scrollbar.borderRadius};
|
||||||
|
background: ${(props) => props.theme.theme.component.scrollbar.color.thumb};
|
||||||
|
box-shadow: inset 0 0 10px rgb(0 0 0 / 20%);
|
||||||
|
}
|
||||||
|
`
|
22
apps/blog/src/styles/table.ts
Normal file
22
apps/blog/src/styles/table.ts
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import { css } from "styled-components"
|
||||||
|
|
||||||
|
export default css`
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-spacing: 0;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
td,
|
||||||
|
th {
|
||||||
|
padding: 8px;
|
||||||
|
border: 1px solid
|
||||||
|
${({ theme }) => theme.theme.component.table.color.border};
|
||||||
|
}
|
||||||
|
|
||||||
|
/* table alternating color */
|
||||||
|
tr:nth-child(even) {
|
||||||
|
background-color: ${({ theme }) =>
|
||||||
|
theme.theme.component.table.color.even};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
|
@ -1,107 +0,0 @@
|
||||||
/** theming.ts
|
|
||||||
* stores values that are used across
|
|
||||||
* It makes changing values easier
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { css } from "styled-components"
|
|
||||||
|
|
||||||
// not declared in the export object so the export object can refer to it
|
|
||||||
function theme(
|
|
||||||
currentTheme: string,
|
|
||||||
values: { [key: string]: string | number }
|
|
||||||
) {
|
|
||||||
return values[currentTheme]
|
|
||||||
}
|
|
||||||
|
|
||||||
const theming = {
|
|
||||||
theme: theme,
|
|
||||||
font: {
|
|
||||||
regular: "'Noto Sans KR', sans-serif",
|
|
||||||
code: "'Source Code Pro', monospace",
|
|
||||||
},
|
|
||||||
size: {
|
|
||||||
x2_small: "3px",
|
|
||||||
small: 0,
|
|
||||||
medium: "1rem",
|
|
||||||
large: 0,
|
|
||||||
x_large: 0,
|
|
||||||
screen_size1: "1000px",
|
|
||||||
screen_size2: "1500px",
|
|
||||||
},
|
|
||||||
dark: {
|
|
||||||
backgroundColor0: "#202225",
|
|
||||||
backgroundColor1: "#36393F",
|
|
||||||
backgroundColor2: "#2F3136",
|
|
||||||
color0: "#FFFFFF",
|
|
||||||
color1: "#EEEEEE",
|
|
||||||
color2: "#CCC",
|
|
||||||
linkColor: "#66AAFF",
|
|
||||||
},
|
|
||||||
light: {
|
|
||||||
backgroundColor0: "#FFFFFF",
|
|
||||||
backgroundColor1: "#F7F7F7",
|
|
||||||
backgroundColor2: "#DDDDDD",
|
|
||||||
color0: "#000000",
|
|
||||||
color1: "#111111",
|
|
||||||
color2: "#555",
|
|
||||||
linkColor: "#4592F7",
|
|
||||||
},
|
|
||||||
styles: {
|
|
||||||
hoverCard: css`
|
|
||||||
:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
box-shadow: ${(props) =>
|
|
||||||
theme(props.theme.currentTheme, {
|
|
||||||
light: "0 4px 10px rgb(0 0 0 / 25%)",
|
|
||||||
dark: "0 4px 10px rgb(255 255 255 / 20%)",
|
|
||||||
})};
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
navbarButtonStyle: css`
|
|
||||||
/* style */
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
cursor: pointer;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
/* size */
|
|
||||||
|
|
||||||
height: 100%;
|
|
||||||
min-width: 2.5rem;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0 1rem 0 1rem;
|
|
||||||
|
|
||||||
/* text */
|
|
||||||
|
|
||||||
text-decoration: none;
|
|
||||||
|
|
||||||
/* color */
|
|
||||||
|
|
||||||
color: ${(props) =>
|
|
||||||
theme(props.theme.currentTheme, {
|
|
||||||
light: "black",
|
|
||||||
dark: "#CFD0D0",
|
|
||||||
})};
|
|
||||||
background-color: ${(props) =>
|
|
||||||
theme(props.theme.currentTheme, {
|
|
||||||
light: "white",
|
|
||||||
dark: "#202225",
|
|
||||||
})};
|
|
||||||
|
|
||||||
/* animation */
|
|
||||||
|
|
||||||
transition: transform 0.1s linear;
|
|
||||||
&:hover {
|
|
||||||
background-color: ${(props) =>
|
|
||||||
theme(props.theme.currentTheme, {
|
|
||||||
light: "#EEEEEE",
|
|
||||||
dark: "#36393F",
|
|
||||||
})};
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
export default theming
|
|
55
apps/blog/src/theme.tsx
Normal file
55
apps/blog/src/theme.tsx
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
// import "./DarkMode.css"
|
||||||
|
import { ChangeEventHandler } from "react"
|
||||||
|
|
||||||
|
/* NEW (START) */
|
||||||
|
const setDark = () => {
|
||||||
|
localStorage.setItem("theme", "dark")
|
||||||
|
document.documentElement.setAttribute("data-theme", "dark")
|
||||||
|
}
|
||||||
|
|
||||||
|
const setLight = () => {
|
||||||
|
localStorage.setItem("theme", "light")
|
||||||
|
document.documentElement.setAttribute("data-theme", "light")
|
||||||
|
}
|
||||||
|
|
||||||
|
const storedTheme = localStorage.getItem("theme")
|
||||||
|
|
||||||
|
const prefersDark =
|
||||||
|
window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches
|
||||||
|
|
||||||
|
const defaultDark =
|
||||||
|
storedTheme === "dark" || (storedTheme === null && prefersDark)
|
||||||
|
|
||||||
|
if (defaultDark) {
|
||||||
|
setDark()
|
||||||
|
}
|
||||||
|
|
||||||
|
const toggleTheme: ChangeEventHandler<HTMLInputElement> = (e) => {
|
||||||
|
if (e.target.checked) {
|
||||||
|
setDark()
|
||||||
|
} else {
|
||||||
|
setLight()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* NEW (END) */
|
||||||
|
|
||||||
|
const DarkMode = () => {
|
||||||
|
return (
|
||||||
|
<div className="toggle-theme-wrapper">
|
||||||
|
<span>☀️</span>
|
||||||
|
<label className="toggle-theme" htmlFor="checkbox">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id="checkbox"
|
||||||
|
// NEW
|
||||||
|
onChange={toggleTheme}
|
||||||
|
defaultChecked={defaultDark}
|
||||||
|
/>
|
||||||
|
<div className="slider round"></div>
|
||||||
|
</label>
|
||||||
|
<span>🌒</span>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DarkMode
|
|
@ -1,5 +1,11 @@
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"name": "typescript-styled-plugin",
|
||||||
|
"validate": false
|
||||||
|
}
|
||||||
|
],
|
||||||
"target": "es5",
|
"target": "es5",
|
||||||
"module": "esnext",
|
"module": "esnext",
|
||||||
"lib": ["dom", "dom.iterable", "esnext"],
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import "styled-components"
|
import "styled-components"
|
||||||
import type { SiteTheme } from "../src/globalContext"
|
import type { Theme } from "@developomp-site/theme"
|
||||||
|
import { SiteTheme } from "../src/globalContext"
|
||||||
|
|
||||||
declare module "styled-components" {
|
declare module "styled-components" {
|
||||||
export interface DefaultTheme {
|
export interface DefaultTheme {
|
||||||
currentTheme: SiteTheme
|
currentTheme: SiteTheme
|
||||||
setTheme(setThemeTo: SiteTheme): void
|
theme: Theme
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Meta, ColorPalette, ColorItem } from "@storybook/addon-docs"
|
import { Meta, ColorPalette, ColorItem } from "@storybook/addon-docs"
|
||||||
import darkTheme from "@developomp-site/theme/dark"
|
import darkTheme from "@developomp-site/theme/dist/dark.json"
|
||||||
|
|
||||||
<Meta title="Colors" />
|
<Meta title="Colors" />
|
||||||
|
|
||||||
|
|
5
packages/theme/.eslintrc
Normal file
5
packages/theme/.eslintrc
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"node": true
|
||||||
|
}
|
||||||
|
}
|
9
packages/theme/build.ts
Normal file
9
packages/theme/build.ts
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import { writeFileSync, mkdirSync, existsSync } from "fs"
|
||||||
|
|
||||||
|
import dark from "./src/dark"
|
||||||
|
import light from "./src/light"
|
||||||
|
|
||||||
|
if (!existsSync("dist")) mkdirSync("dist")
|
||||||
|
|
||||||
|
writeFileSync("dist/dark.json", JSON.stringify(dark))
|
||||||
|
writeFileSync("dist/light.json", JSON.stringify(light))
|
|
@ -1,62 +0,0 @@
|
||||||
const theme: Theme = {
|
|
||||||
font: {
|
|
||||||
sansSerif: "'Noto Sans KR', sans-serif", // https://fonts.google.com/noto/specimen/Noto+Sans+KR
|
|
||||||
monospace: "'Source Code Pro', monospace",
|
|
||||||
},
|
|
||||||
|
|
||||||
maxDisplayWidth: {
|
|
||||||
mobile: "1024px", // max-w-screen-lg
|
|
||||||
desktop: "1536px", // max-w-screen-2xl
|
|
||||||
},
|
|
||||||
|
|
||||||
component: {
|
|
||||||
scrollbar: {
|
|
||||||
width: "8px", // w-2
|
|
||||||
borderRadius: "4px", // rounded
|
|
||||||
},
|
|
||||||
|
|
||||||
header: {
|
|
||||||
color: {
|
|
||||||
background: "#202225", // custom
|
|
||||||
hover: "#3f3f46", // zinc-700
|
|
||||||
text: "#d4d4d8", // zinc-300
|
|
||||||
},
|
|
||||||
height: "16px", // h-4
|
|
||||||
},
|
|
||||||
|
|
||||||
scrollProgressBar: {
|
|
||||||
color: {
|
|
||||||
background: "#52525b", // zinc 600
|
|
||||||
foreground: "#d4d4d8", // zinc-300
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
card: {
|
|
||||||
color: {
|
|
||||||
background: "#2f3136",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
footer: {
|
|
||||||
color: {
|
|
||||||
background: "",
|
|
||||||
text: "",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
ui: {
|
|
||||||
color: {
|
|
||||||
background: {
|
|
||||||
interactive: "",
|
|
||||||
},
|
|
||||||
text: {
|
|
||||||
on1: "",
|
|
||||||
link: "#66AAFF",
|
|
||||||
linkActive: "#4592F7",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
export default theme
|
|
143
packages/theme/index.d.ts
vendored
Normal file
143
packages/theme/index.d.ts
vendored
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
export interface Theme {
|
||||||
|
font: {
|
||||||
|
sansSerif: string
|
||||||
|
monospace: string
|
||||||
|
}
|
||||||
|
|
||||||
|
color: {
|
||||||
|
text: {
|
||||||
|
highContrast: string
|
||||||
|
default: string
|
||||||
|
gray: string
|
||||||
|
}
|
||||||
|
background: string
|
||||||
|
}
|
||||||
|
|
||||||
|
maxDisplayWidth: {
|
||||||
|
mobile: string
|
||||||
|
desktop: string
|
||||||
|
}
|
||||||
|
|
||||||
|
component: {
|
||||||
|
anchor: {
|
||||||
|
color: {
|
||||||
|
default: string
|
||||||
|
hover: string
|
||||||
|
active: string
|
||||||
|
header: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blockQuote: {
|
||||||
|
color: {
|
||||||
|
background: string
|
||||||
|
borderLeft: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
card: {
|
||||||
|
color: {
|
||||||
|
background: string
|
||||||
|
hoverGlow: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
code: {
|
||||||
|
inline: {
|
||||||
|
color: {
|
||||||
|
text: string
|
||||||
|
background: string
|
||||||
|
border: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
block: {
|
||||||
|
color: {
|
||||||
|
border: string
|
||||||
|
highlight: string
|
||||||
|
}
|
||||||
|
style: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
footer: {
|
||||||
|
color: {
|
||||||
|
background: string
|
||||||
|
text: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
header: {
|
||||||
|
color: {
|
||||||
|
background: string
|
||||||
|
hover: string
|
||||||
|
text: string
|
||||||
|
}
|
||||||
|
height: string
|
||||||
|
}
|
||||||
|
|
||||||
|
input: {
|
||||||
|
color: {
|
||||||
|
background: {
|
||||||
|
default: string
|
||||||
|
itemHover: string
|
||||||
|
}
|
||||||
|
border: {
|
||||||
|
default: string
|
||||||
|
hover: string
|
||||||
|
focus: string
|
||||||
|
}
|
||||||
|
placeHolder: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
kbd: {
|
||||||
|
color: {
|
||||||
|
text: string
|
||||||
|
border: string
|
||||||
|
outerShadow: string
|
||||||
|
innerShadow: string
|
||||||
|
background: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mark: {
|
||||||
|
color: {
|
||||||
|
text: string
|
||||||
|
background: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scrollbar: {
|
||||||
|
color: {
|
||||||
|
track: string
|
||||||
|
thumb: string
|
||||||
|
}
|
||||||
|
width: string
|
||||||
|
borderRadius: string
|
||||||
|
}
|
||||||
|
|
||||||
|
scrollProgressBar: {
|
||||||
|
color: {
|
||||||
|
background: string
|
||||||
|
foreground: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
table: {
|
||||||
|
color: {
|
||||||
|
border: string
|
||||||
|
even: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ui: {
|
||||||
|
color: {
|
||||||
|
background: {
|
||||||
|
default: string
|
||||||
|
hover: string
|
||||||
|
}
|
||||||
|
border: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +0,0 @@
|
||||||
import BaseTheme from "../dark"
|
|
||||||
|
|
||||||
const theme: Theme = { ...BaseTheme }
|
|
||||||
|
|
||||||
export default theme
|
|
|
@ -1,9 +1,22 @@
|
||||||
{
|
{
|
||||||
"name": "@developomp-site/theme",
|
"name": "@developomp-site/theme",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
|
"types": "./index.d.ts",
|
||||||
"private": true,
|
"private": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "nodemon --ignore dist/ --exec pnpm build",
|
||||||
|
"build": "npx ts-node ./build.ts",
|
||||||
|
"clean": "rm -rf dist && rm -rf node_modules"
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"tailwindcss": "^3.1.4"
|
"@types/merge-deep": "^3.0.0",
|
||||||
|
"@types/node": "^18.11.10",
|
||||||
|
"merge-deep": "^3.0.3",
|
||||||
|
"nodemon": "^2.0.20",
|
||||||
|
"tailwindcss": "^3.1.4",
|
||||||
|
"ts-node": "^10.9.1",
|
||||||
|
"tsup": "^5.10.1",
|
||||||
|
"utility-types": "^3.10.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
167
packages/theme/src/dark/index.ts
Normal file
167
packages/theme/src/dark/index.ts
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
import type { Theme } from "../.."
|
||||||
|
|
||||||
|
import { readFileSync } from "fs"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
font: {
|
||||||
|
sansSerif: "'Noto Sans KR', sans-serif", // https://fonts.google.com/noto/specimen/Noto+Sans+KR
|
||||||
|
monospace: "'Source Code Pro', monospace",
|
||||||
|
},
|
||||||
|
|
||||||
|
color: {
|
||||||
|
text: {
|
||||||
|
highContrast: "#FFFFFF",
|
||||||
|
default: "#EEEEEE",
|
||||||
|
gray: "#CCC",
|
||||||
|
},
|
||||||
|
background: "#36393F",
|
||||||
|
},
|
||||||
|
|
||||||
|
maxDisplayWidth: {
|
||||||
|
mobile: "1024px", // max-w-screen-lg
|
||||||
|
desktop: "1536px", // max-w-screen-2xl
|
||||||
|
},
|
||||||
|
|
||||||
|
component: {
|
||||||
|
anchor: {
|
||||||
|
color: {
|
||||||
|
default: "#66AAFF",
|
||||||
|
hover: "#4592F7",
|
||||||
|
active: "#4592F7",
|
||||||
|
header: "#778899",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
blockQuote: {
|
||||||
|
color: {
|
||||||
|
background: "#FFFFFF12",
|
||||||
|
borderLeft: "#FFFFFF4D",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
card: {
|
||||||
|
color: {
|
||||||
|
background: "#2F3136",
|
||||||
|
hoverGlow: "#FFFFFF33",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
code: {
|
||||||
|
inline: {
|
||||||
|
color: {
|
||||||
|
text: "#FFFFFF",
|
||||||
|
background: "#444",
|
||||||
|
border: "#666",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
block: {
|
||||||
|
color: {
|
||||||
|
border: "#555",
|
||||||
|
highlight: "#14161A",
|
||||||
|
},
|
||||||
|
style: readFileSync(__dirname + "/codeblock.css", "utf-8"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
footer: {
|
||||||
|
color: {
|
||||||
|
background: "#000000",
|
||||||
|
text: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
header: {
|
||||||
|
color: {
|
||||||
|
background: "#202225", // custom
|
||||||
|
hover: "#3F3F46", // zinc-700
|
||||||
|
text: "#D4D4D8", // zinc-300
|
||||||
|
},
|
||||||
|
height: "16px", // h-4
|
||||||
|
},
|
||||||
|
|
||||||
|
input: {
|
||||||
|
color: {
|
||||||
|
background: {
|
||||||
|
default: "#36393f",
|
||||||
|
itemHover: "#202225",
|
||||||
|
},
|
||||||
|
border: {
|
||||||
|
default: "#555555",
|
||||||
|
hover: "#808080",
|
||||||
|
focus: "#a3a3a3", // neutral-400
|
||||||
|
},
|
||||||
|
placeHolder: "#A9A9A9",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
kbd: {
|
||||||
|
color: {
|
||||||
|
text: "#FFFFFF",
|
||||||
|
border: "#555555",
|
||||||
|
outerShadow: "#FFFFFF4D",
|
||||||
|
innerShadow: "#000000",
|
||||||
|
background: "#000000",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
mark: {
|
||||||
|
color: {
|
||||||
|
text: "#FFFFFF",
|
||||||
|
background: "#FFFF0080",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
scrollbar: {
|
||||||
|
color: {
|
||||||
|
track: "#18181B",
|
||||||
|
thumb: "#888888",
|
||||||
|
},
|
||||||
|
width: "8px", // w-2
|
||||||
|
borderRadius: "4px", // rounded
|
||||||
|
},
|
||||||
|
|
||||||
|
scrollProgressBar: {
|
||||||
|
color: {
|
||||||
|
background: "#52525B", // zinc 600
|
||||||
|
foreground: "#D4D4D8", // zinc-300
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
table: {
|
||||||
|
color: {
|
||||||
|
border: "#777777",
|
||||||
|
even: "#21272E",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
ui: {
|
||||||
|
color: {
|
||||||
|
background: {
|
||||||
|
default: "#202225",
|
||||||
|
hover: "#3F3F46", // zinc-700
|
||||||
|
},
|
||||||
|
border: "#555",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as Theme
|
||||||
|
|
||||||
|
/*
|
||||||
|
dark: {
|
||||||
|
backgroundColor0: "#18181b",
|
||||||
|
backgroundColor1: "#36393F",
|
||||||
|
backgroundColor2: "#2F3136",
|
||||||
|
color0: "#FFFFFF",
|
||||||
|
color1: "#EEEEEE",
|
||||||
|
color2: "#CCC",
|
||||||
|
}
|
||||||
|
|
||||||
|
light: {
|
||||||
|
backgroundColor0: "#FFFFFF",
|
||||||
|
backgroundColor1: "#F7F7F7",
|
||||||
|
backgroundColor2: "#DDDDDD",
|
||||||
|
color0: "#000000",
|
||||||
|
color1: "#111111",
|
||||||
|
color2: "#555",
|
||||||
|
}
|
||||||
|
*/
|
126
packages/theme/src/light/index.ts
Normal file
126
packages/theme/src/light/index.ts
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
import type { Theme } from "../.."
|
||||||
|
|
||||||
|
import { readFileSync } from "fs"
|
||||||
|
import merge from "merge-deep"
|
||||||
|
import { DeepPartial } from "utility-types"
|
||||||
|
|
||||||
|
import BaseTheme from "../dark"
|
||||||
|
|
||||||
|
export default merge<Theme, DeepPartial<Theme>>(BaseTheme, {
|
||||||
|
color: {
|
||||||
|
text: {
|
||||||
|
highContrast: "#000000",
|
||||||
|
default: "#111111",
|
||||||
|
gray: "#555",
|
||||||
|
},
|
||||||
|
background: "#F7F7F7",
|
||||||
|
},
|
||||||
|
component: {
|
||||||
|
anchor: {
|
||||||
|
color: {
|
||||||
|
header: "#D3D3D3",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
blockQuote: {
|
||||||
|
color: {
|
||||||
|
background: "#0000000D",
|
||||||
|
borderLeft: "#0000001A",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
card: {
|
||||||
|
color: {
|
||||||
|
background: "#FFFFFF",
|
||||||
|
hoverGlow: "#00000040",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
code: {
|
||||||
|
inline: {
|
||||||
|
color: {
|
||||||
|
text: "#000000",
|
||||||
|
background: "#EEE",
|
||||||
|
border: "#BBB",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
block: {
|
||||||
|
color: {
|
||||||
|
border: "#BBB",
|
||||||
|
highlight: "#DDDDDD",
|
||||||
|
},
|
||||||
|
style: readFileSync(__dirname + "/codeblock.css", "utf-8"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
footer: {
|
||||||
|
color: {
|
||||||
|
background: "#FFFFFF",
|
||||||
|
text: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
input: {
|
||||||
|
color: {
|
||||||
|
background: {
|
||||||
|
default: "#EEEEEE",
|
||||||
|
itemHover: "#FFFFFF",
|
||||||
|
},
|
||||||
|
border: {
|
||||||
|
default: "#CCCCCC",
|
||||||
|
hover: "#808080",
|
||||||
|
focus: "#000000",
|
||||||
|
},
|
||||||
|
placeHolder: "#777777",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
kbd: {
|
||||||
|
color: {
|
||||||
|
text: "#333333",
|
||||||
|
border: "#CCCCCC",
|
||||||
|
outerShadow: "#00000033",
|
||||||
|
innerShadow: "#FFFFFF",
|
||||||
|
background: "#F7F7F7",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
mark: {
|
||||||
|
color: {
|
||||||
|
text: "#000000",
|
||||||
|
background: "#FFFF00BF",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
scrollbar: {
|
||||||
|
color: {
|
||||||
|
track: "#FFFFFF",
|
||||||
|
thumb: "#DDDDDD",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
scrollProgressBar: {
|
||||||
|
color: {
|
||||||
|
background: "#d4d4d8", // zinc-300
|
||||||
|
foreground: "#52525b", // zinc-600
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
table: {
|
||||||
|
color: {
|
||||||
|
border: "#DDD",
|
||||||
|
even: "#F2F2F2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
ui: {
|
||||||
|
color: {
|
||||||
|
background: {
|
||||||
|
default: "#FFFFFF",
|
||||||
|
hover: "#EEEEEE",
|
||||||
|
},
|
||||||
|
border: "#CCC",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}) as Theme
|
9
packages/theme/tsconfig.json
Normal file
9
packages/theme/tsconfig.json
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"types": ["node"],
|
||||||
|
"moduleResolution": "Node",
|
||||||
|
"esModuleInterop": true
|
||||||
|
},
|
||||||
|
"include": ["src"],
|
||||||
|
"exclude": ["dist", "node_modules"]
|
||||||
|
}
|
60
packages/theme/types/index.d.ts
vendored
60
packages/theme/types/index.d.ts
vendored
|
@ -1,60 +0,0 @@
|
||||||
interface Theme extends Object {
|
|
||||||
font: {
|
|
||||||
sansSerif: string
|
|
||||||
monospace: string
|
|
||||||
}
|
|
||||||
|
|
||||||
maxDisplayWidth: {
|
|
||||||
mobile: string
|
|
||||||
desktop: string
|
|
||||||
}
|
|
||||||
|
|
||||||
component: {
|
|
||||||
scrollbar: {
|
|
||||||
width: string
|
|
||||||
borderRadius: string
|
|
||||||
}
|
|
||||||
|
|
||||||
header: {
|
|
||||||
color: {
|
|
||||||
background: string
|
|
||||||
hover: string
|
|
||||||
text: string
|
|
||||||
}
|
|
||||||
height: string
|
|
||||||
}
|
|
||||||
|
|
||||||
scrollProgressBar: {
|
|
||||||
color: {
|
|
||||||
background: string
|
|
||||||
foreground: string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
card: {
|
|
||||||
color: {
|
|
||||||
background: string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
footer: {
|
|
||||||
color: {
|
|
||||||
background: string
|
|
||||||
text: string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ui: {
|
|
||||||
color: {
|
|
||||||
background: {
|
|
||||||
interactive: string
|
|
||||||
}
|
|
||||||
text: {
|
|
||||||
on1: string
|
|
||||||
link: string
|
|
||||||
linkActive: string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
207
pnpm-lock.yaml
generated
207
pnpm-lock.yaml
generated
|
@ -18,8 +18,9 @@ importers:
|
||||||
|
|
||||||
apps/blog:
|
apps/blog:
|
||||||
specifiers:
|
specifiers:
|
||||||
'@developomp-site/eslint-config': workspace:0.0.0
|
'@developomp-site/eslint-config': workspace:*
|
||||||
'@developomp-site/tsconfig': workspace:0.0.0
|
'@developomp-site/theme': workspace:*
|
||||||
|
'@developomp-site/tsconfig': workspace:*
|
||||||
'@fortawesome/fontawesome-svg-core': ^6.2.1
|
'@fortawesome/fontawesome-svg-core': ^6.2.1
|
||||||
'@fortawesome/free-brands-svg-icons': ^6.2.1
|
'@fortawesome/free-brands-svg-icons': ^6.2.1
|
||||||
'@fortawesome/free-regular-svg-icons': ^6.2.1
|
'@fortawesome/free-regular-svg-icons': ^6.2.1
|
||||||
|
@ -81,6 +82,7 @@ importers:
|
||||||
tslint-config-prettier: ^1.18.0
|
tslint-config-prettier: ^1.18.0
|
||||||
typescript: ^4.9.3
|
typescript: ^4.9.3
|
||||||
dependencies:
|
dependencies:
|
||||||
|
'@developomp-site/theme': link:../../packages/theme
|
||||||
'@fortawesome/fontawesome-svg-core': 6.2.1
|
'@fortawesome/fontawesome-svg-core': 6.2.1
|
||||||
'@fortawesome/free-brands-svg-icons': 6.2.1
|
'@fortawesome/free-brands-svg-icons': 6.2.1
|
||||||
'@fortawesome/free-regular-svg-icons': 6.2.1
|
'@fortawesome/free-regular-svg-icons': 6.2.1
|
||||||
|
@ -234,9 +236,23 @@ importers:
|
||||||
|
|
||||||
packages/theme:
|
packages/theme:
|
||||||
specifiers:
|
specifiers:
|
||||||
|
'@types/merge-deep': ^3.0.0
|
||||||
|
'@types/node': ^18.11.10
|
||||||
|
merge-deep: ^3.0.3
|
||||||
|
nodemon: ^2.0.20
|
||||||
tailwindcss: ^3.1.4
|
tailwindcss: ^3.1.4
|
||||||
|
ts-node: ^10.9.1
|
||||||
|
tsup: ^5.10.1
|
||||||
|
utility-types: ^3.10.0
|
||||||
devDependencies:
|
devDependencies:
|
||||||
tailwindcss: 3.2.4_postcss@8.4.19
|
'@types/merge-deep': 3.0.0
|
||||||
|
'@types/node': 18.11.11
|
||||||
|
merge-deep: 3.0.3
|
||||||
|
nodemon: 2.0.20
|
||||||
|
tailwindcss: 3.2.4_v776zzvn44o7tpgzieipaairwm
|
||||||
|
ts-node: 10.9.1_bspv7bpieoza2i5ctiw2ofswem
|
||||||
|
tsup: 5.12.9_h63whvv5d2b4avkcl4ixnozygi
|
||||||
|
utility-types: 3.10.0
|
||||||
|
|
||||||
packages/tsconfig:
|
packages/tsconfig:
|
||||||
specifiers: {}
|
specifiers: {}
|
||||||
|
@ -4372,6 +4388,10 @@ packages:
|
||||||
resolution: {integrity: sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==}
|
resolution: {integrity: sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@types/merge-deep/3.0.0:
|
||||||
|
resolution: {integrity: sha512-t5B5UfacpaP8opUvFGUwT0uQetFrD+qm1/I2ksxokJFLT0Tb4B2NI2G2LYz3ugMDKOE7adkNBZ6coK7RW6MAqA==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@types/mime/3.0.1:
|
/@types/mime/3.0.1:
|
||||||
resolution: {integrity: sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==}
|
resolution: {integrity: sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==}
|
||||||
dev: false
|
dev: false
|
||||||
|
@ -5003,6 +5023,10 @@ packages:
|
||||||
/abab/2.0.6:
|
/abab/2.0.6:
|
||||||
resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==}
|
resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==}
|
||||||
|
|
||||||
|
/abbrev/1.1.1:
|
||||||
|
resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/accepts/1.3.8:
|
/accepts/1.3.8:
|
||||||
resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
|
resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
|
@ -6451,6 +6475,17 @@ packages:
|
||||||
wrap-ansi: 7.0.0
|
wrap-ansi: 7.0.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/clone-deep/0.2.4:
|
||||||
|
resolution: {integrity: sha512-we+NuQo2DHhSl+DP6jlUiAhyAjBQrYnpOk15rN6c6JSPScjiCLh8IbSU+VTcph6YS3o7mASE8a0+gbZ7ChLpgg==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
dependencies:
|
||||||
|
for-own: 0.1.5
|
||||||
|
is-plain-object: 2.0.4
|
||||||
|
kind-of: 3.2.2
|
||||||
|
lazy-cache: 1.0.4
|
||||||
|
shallow-clone: 0.1.2
|
||||||
|
dev: true
|
||||||
|
|
||||||
/clone-deep/4.0.1:
|
/clone-deep/4.0.1:
|
||||||
resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==}
|
resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
@ -7206,6 +7241,18 @@ packages:
|
||||||
dependencies:
|
dependencies:
|
||||||
ms: 2.1.3
|
ms: 2.1.3
|
||||||
|
|
||||||
|
/debug/3.2.7_supports-color@5.5.0:
|
||||||
|
resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
|
||||||
|
peerDependencies:
|
||||||
|
supports-color: '*'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
supports-color:
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
ms: 2.1.3
|
||||||
|
supports-color: 5.5.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
/debug/4.3.4:
|
/debug/4.3.4:
|
||||||
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
|
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
|
||||||
engines: {node: '>=6.0'}
|
engines: {node: '>=6.0'}
|
||||||
|
@ -8953,11 +9000,23 @@ packages:
|
||||||
optional: true
|
optional: true
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/for-in/0.1.8:
|
||||||
|
resolution: {integrity: sha512-F0to7vbBSHP8E3l6dCjxNOLuSFAACIxFy3UehTUlG7svlXi37HHsDkyVcHo0Pq8QwrE+pXvWSVX3ZT1T9wAZ9g==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/for-in/1.0.2:
|
/for-in/1.0.2:
|
||||||
resolution: {integrity: sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==}
|
resolution: {integrity: sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/for-own/0.1.5:
|
||||||
|
resolution: {integrity: sha512-SKmowqGTJoPzLO1T0BBJpkfp3EMacCMOuH40hOUbrbzElVktk4DioXVM99QkLCyKoiuOmyjgcWMpVz2xjE7LZw==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
dependencies:
|
||||||
|
for-in: 1.0.2
|
||||||
|
dev: true
|
||||||
|
|
||||||
/foreground-child/2.0.0:
|
/foreground-child/2.0.0:
|
||||||
resolution: {integrity: sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==}
|
resolution: {integrity: sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==}
|
||||||
engines: {node: '>=8.0.0'}
|
engines: {node: '>=8.0.0'}
|
||||||
|
@ -9914,6 +9973,10 @@ packages:
|
||||||
resolution: {integrity: sha512-DUNFN5j7Tln0D+TxzloUjKB+CtVu6myn0JEFak6dG18mNt9YkQ6lzGCdafwofISZ1lLF3xRHJ98VKy9ynkcFaA==}
|
resolution: {integrity: sha512-DUNFN5j7Tln0D+TxzloUjKB+CtVu6myn0JEFak6dG18mNt9YkQ6lzGCdafwofISZ1lLF3xRHJ98VKy9ynkcFaA==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/ignore-by-default/1.0.1:
|
||||||
|
resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/ignore/4.0.6:
|
/ignore/4.0.6:
|
||||||
resolution: {integrity: sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==}
|
resolution: {integrity: sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==}
|
||||||
engines: {node: '>= 4'}
|
engines: {node: '>= 4'}
|
||||||
|
@ -11279,6 +11342,13 @@ packages:
|
||||||
commander: 8.3.0
|
commander: 8.3.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/kind-of/2.0.1:
|
||||||
|
resolution: {integrity: sha512-0u8i1NZ/mg0b+W3MGGw5I7+6Eib2nx72S/QvXa0hYjEkjTknYmEYQJwGu3mLC0BrhtJjtQafTkyRUQ75Kx0LVg==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
dependencies:
|
||||||
|
is-buffer: 1.1.6
|
||||||
|
dev: true
|
||||||
|
|
||||||
/kind-of/3.2.2:
|
/kind-of/3.2.2:
|
||||||
resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==}
|
resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
@ -11320,6 +11390,16 @@ packages:
|
||||||
language-subtag-registry: 0.3.22
|
language-subtag-registry: 0.3.22
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/lazy-cache/0.2.7:
|
||||||
|
resolution: {integrity: sha512-gkX52wvU/R8DVMMt78ATVPFMJqfW8FPz1GZ1sVHBVQHmu/WvhIWE4cE1GBzhJNFicDeYhnwp6Rl35BcAIM3YOQ==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/lazy-cache/1.0.4:
|
||||||
|
resolution: {integrity: sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/lazy-cache/2.0.2:
|
/lazy-cache/2.0.2:
|
||||||
resolution: {integrity: sha512-7vp2Acd2+Kz4XkzxGxaB1FWOi8KjWIWsgdfD5MCb86DWvlLqhRPM+d6Pro3iNEL5VT9mstz5hKAlcd+QR6H3aA==}
|
resolution: {integrity: sha512-7vp2Acd2+Kz4XkzxGxaB1FWOi8KjWIWsgdfD5MCb86DWvlLqhRPM+d6Pro3iNEL5VT9mstz5hKAlcd+QR6H3aA==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
@ -11776,6 +11856,15 @@ packages:
|
||||||
dev: true
|
dev: true
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
/merge-deep/3.0.3:
|
||||||
|
resolution: {integrity: sha512-qtmzAS6t6grwEkNrunqTBdn0qKwFgNWvlxUbAV8es9M7Ot1EbyApytCnvE0jALPa46ZpKDUo527kKiaWplmlFA==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
dependencies:
|
||||||
|
arr-union: 3.1.0
|
||||||
|
clone-deep: 0.2.4
|
||||||
|
kind-of: 3.2.2
|
||||||
|
dev: true
|
||||||
|
|
||||||
/merge-descriptors/1.0.1:
|
/merge-descriptors/1.0.1:
|
||||||
resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==}
|
resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==}
|
||||||
|
|
||||||
|
@ -11982,6 +12071,14 @@ packages:
|
||||||
is-extendable: 1.0.1
|
is-extendable: 1.0.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/mixin-object/2.0.1:
|
||||||
|
resolution: {integrity: sha512-ALGF1Jt9ouehcaXaHhn6t1yGWRqGaHkPFndtFVHfZXOvkIZ/yoGaSi0AHVTafb3ZBGg4dr/bDwnaEKqCXzchMA==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
dependencies:
|
||||||
|
for-in: 0.1.8
|
||||||
|
is-extendable: 0.1.1
|
||||||
|
dev: true
|
||||||
|
|
||||||
/mkdirp/0.5.6:
|
/mkdirp/0.5.6:
|
||||||
resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
|
resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
@ -12150,6 +12247,30 @@ packages:
|
||||||
/node-releases/2.0.6:
|
/node-releases/2.0.6:
|
||||||
resolution: {integrity: sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==}
|
resolution: {integrity: sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==}
|
||||||
|
|
||||||
|
/nodemon/2.0.20:
|
||||||
|
resolution: {integrity: sha512-Km2mWHKKY5GzRg6i1j5OxOHQtuvVsgskLfigG25yTtbyfRGn/GNvIbRyOf1PSCKJ2aT/58TiuUsuOU5UToVViw==}
|
||||||
|
engines: {node: '>=8.10.0'}
|
||||||
|
hasBin: true
|
||||||
|
dependencies:
|
||||||
|
chokidar: 3.5.3
|
||||||
|
debug: 3.2.7_supports-color@5.5.0
|
||||||
|
ignore-by-default: 1.0.1
|
||||||
|
minimatch: 3.1.2
|
||||||
|
pstree.remy: 1.1.8
|
||||||
|
semver: 5.7.1
|
||||||
|
simple-update-notifier: 1.1.0
|
||||||
|
supports-color: 5.5.0
|
||||||
|
touch: 3.1.0
|
||||||
|
undefsafe: 2.0.5
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/nopt/1.0.10:
|
||||||
|
resolution: {integrity: sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==}
|
||||||
|
hasBin: true
|
||||||
|
dependencies:
|
||||||
|
abbrev: 1.1.1
|
||||||
|
dev: true
|
||||||
|
|
||||||
/normalize-package-data/2.5.0:
|
/normalize-package-data/2.5.0:
|
||||||
resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==}
|
resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -13080,7 +13201,6 @@ packages:
|
||||||
postcss: 8.4.19
|
postcss: 8.4.19
|
||||||
ts-node: 10.9.1_bspv7bpieoza2i5ctiw2ofswem
|
ts-node: 10.9.1_bspv7bpieoza2i5ctiw2ofswem
|
||||||
yaml: 1.10.2
|
yaml: 1.10.2
|
||||||
dev: false
|
|
||||||
|
|
||||||
/postcss-loader/4.3.0_gzaxsinx64nntyd3vmdqwl7coe:
|
/postcss-loader/4.3.0_gzaxsinx64nntyd3vmdqwl7coe:
|
||||||
resolution: {integrity: sha512-M/dSoIiNDOo8Rk0mUqoj4kpGq91gcxCfb9PoyZVdZ76/AuhxylHDYZblNE8o+EQ9AMSASeMFEKxZf5aU6wlx1Q==}
|
resolution: {integrity: sha512-M/dSoIiNDOo8Rk0mUqoj4kpGq91gcxCfb9PoyZVdZ76/AuhxylHDYZblNE8o+EQ9AMSASeMFEKxZf5aU6wlx1Q==}
|
||||||
|
@ -13748,6 +13868,10 @@ packages:
|
||||||
/psl/1.9.0:
|
/psl/1.9.0:
|
||||||
resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==}
|
resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==}
|
||||||
|
|
||||||
|
/pstree.remy/1.1.8:
|
||||||
|
resolution: {integrity: sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/public-encrypt/4.0.3:
|
/public-encrypt/4.0.3:
|
||||||
resolution: {integrity: sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==}
|
resolution: {integrity: sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -14944,6 +15068,11 @@ packages:
|
||||||
resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==}
|
resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
/semver/7.0.0:
|
||||||
|
resolution: {integrity: sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==}
|
||||||
|
hasBin: true
|
||||||
|
dev: true
|
||||||
|
|
||||||
/semver/7.3.8:
|
/semver/7.3.8:
|
||||||
resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==}
|
resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
@ -15094,6 +15223,16 @@ packages:
|
||||||
safe-buffer: 5.2.1
|
safe-buffer: 5.2.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/shallow-clone/0.1.2:
|
||||||
|
resolution: {integrity: sha512-J1zdXCky5GmNnuauESROVu31MQSnLoYvlyEn6j2Ztk6Q5EHFIhxkMhYcv6vuDzl2XEzoRr856QwzMgWM/TmZgw==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
dependencies:
|
||||||
|
is-extendable: 0.1.1
|
||||||
|
kind-of: 2.0.1
|
||||||
|
lazy-cache: 0.2.7
|
||||||
|
mixin-object: 2.0.1
|
||||||
|
dev: true
|
||||||
|
|
||||||
/shallow-clone/3.0.1:
|
/shallow-clone/3.0.1:
|
||||||
resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==}
|
resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
@ -15149,6 +15288,13 @@ packages:
|
||||||
engines: {node: '>=0.12.18'}
|
engines: {node: '>=0.12.18'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/simple-update-notifier/1.1.0:
|
||||||
|
resolution: {integrity: sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==}
|
||||||
|
engines: {node: '>=8.10.0'}
|
||||||
|
dependencies:
|
||||||
|
semver: 7.0.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
/sisteransi/1.0.5:
|
/sisteransi/1.0.5:
|
||||||
resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
|
resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
|
||||||
|
|
||||||
|
@ -15858,7 +16004,6 @@ packages:
|
||||||
resolve: 1.22.1
|
resolve: 1.22.1
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- ts-node
|
- ts-node
|
||||||
dev: false
|
|
||||||
|
|
||||||
/tapable/1.1.3:
|
/tapable/1.1.3:
|
||||||
resolution: {integrity: sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==}
|
resolution: {integrity: sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==}
|
||||||
|
@ -16105,6 +16250,13 @@ packages:
|
||||||
resolution: {integrity: sha512-gVweAectJU3ebq//Ferr2JUY4WKSDe5N+z0FvjDncLGyHmIDoxgY/2Ie4qfEIDm4IS7OA6Rmdm7pdEEdMcV/xQ==}
|
resolution: {integrity: sha512-gVweAectJU3ebq//Ferr2JUY4WKSDe5N+z0FvjDncLGyHmIDoxgY/2Ie4qfEIDm4IS7OA6Rmdm7pdEEdMcV/xQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/touch/3.1.0:
|
||||||
|
resolution: {integrity: sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==}
|
||||||
|
hasBin: true
|
||||||
|
dependencies:
|
||||||
|
nopt: 1.0.10
|
||||||
|
dev: true
|
||||||
|
|
||||||
/tough-cookie/4.1.2:
|
/tough-cookie/4.1.2:
|
||||||
resolution: {integrity: sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==}
|
resolution: {integrity: sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
@ -16237,6 +16389,42 @@ packages:
|
||||||
hasBin: true
|
hasBin: true
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/tsup/5.12.9_h63whvv5d2b4avkcl4ixnozygi:
|
||||||
|
resolution: {integrity: sha512-dUpuouWZYe40lLufo64qEhDpIDsWhRbr2expv5dHEMjwqeKJS2aXA/FPqs1dxO4T6mBojo7rvo3jP9NNzaKyDg==}
|
||||||
|
hasBin: true
|
||||||
|
peerDependencies:
|
||||||
|
'@swc/core': ^1
|
||||||
|
postcss: ^8.4.12
|
||||||
|
typescript: ^4.1.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@swc/core':
|
||||||
|
optional: true
|
||||||
|
postcss:
|
||||||
|
optional: true
|
||||||
|
typescript:
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
bundle-require: 3.1.2_esbuild@0.14.54
|
||||||
|
cac: 6.7.14
|
||||||
|
chokidar: 3.5.3
|
||||||
|
debug: 4.3.4
|
||||||
|
esbuild: 0.14.54
|
||||||
|
execa: 5.1.1
|
||||||
|
globby: 11.1.0
|
||||||
|
joycon: 3.1.1
|
||||||
|
postcss: 8.4.19
|
||||||
|
postcss-load-config: 3.1.4_v776zzvn44o7tpgzieipaairwm
|
||||||
|
resolve-from: 5.0.0
|
||||||
|
rollup: 2.79.1
|
||||||
|
source-map: 0.8.0-beta.0
|
||||||
|
sucrase: 3.29.0
|
||||||
|
tree-kill: 1.2.2
|
||||||
|
typescript: 4.9.4
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
- ts-node
|
||||||
|
dev: true
|
||||||
|
|
||||||
/tsup/5.12.9_o6pf6py3ttho7dpy7mshkpxque:
|
/tsup/5.12.9_o6pf6py3ttho7dpy7mshkpxque:
|
||||||
resolution: {integrity: sha512-dUpuouWZYe40lLufo64qEhDpIDsWhRbr2expv5dHEMjwqeKJS2aXA/FPqs1dxO4T6mBojo7rvo3jP9NNzaKyDg==}
|
resolution: {integrity: sha512-dUpuouWZYe40lLufo64qEhDpIDsWhRbr2expv5dHEMjwqeKJS2aXA/FPqs1dxO4T6mBojo7rvo3jP9NNzaKyDg==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
@ -16469,6 +16657,10 @@ packages:
|
||||||
has-symbols: 1.0.3
|
has-symbols: 1.0.3
|
||||||
which-boxed-primitive: 1.0.2
|
which-boxed-primitive: 1.0.2
|
||||||
|
|
||||||
|
/undefsafe/2.0.5:
|
||||||
|
resolution: {integrity: sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/unfetch/4.2.0:
|
/unfetch/4.2.0:
|
||||||
resolution: {integrity: sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==}
|
resolution: {integrity: sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==}
|
||||||
dev: true
|
dev: true
|
||||||
|
@ -16733,6 +16925,11 @@ packages:
|
||||||
/utila/0.4.0:
|
/utila/0.4.0:
|
||||||
resolution: {integrity: sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==}
|
resolution: {integrity: sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==}
|
||||||
|
|
||||||
|
/utility-types/3.10.0:
|
||||||
|
resolution: {integrity: sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==}
|
||||||
|
engines: {node: '>= 4'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/utils-merge/1.0.1:
|
/utils-merge/1.0.1:
|
||||||
resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==}
|
resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==}
|
||||||
engines: {node: '>= 0.4.0'}
|
engines: {node: '>= 0.4.0'}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue