This commit is contained in:
2026-05-23 17:17:56 -07:00
commit 448f2e33ef
135 changed files with 11817 additions and 0 deletions
@@ -0,0 +1,58 @@
import { type ReactNode, useEffect, useState } from 'react'
import { ScrollContext } from '../../functions/Context'
import HeaderMessage from '../layout/HeaderMessage'
import HeaderError from '../layout/HeaderError'
import ViewAnimation from '../views/Animation'
import ViewHomepage from '../views/Homepage'
import ViewPersonal from '../views/Personal'
import ViewSearch from '../views/Search'
import ViewSettings from '../views/Settings'
import ViewText from '../views/Text'
import ViewUpload from '../views/Upload'
export default function PaneContent() {
const [mainElem, setMainElem] = useState<HTMLElement | null>(null)
const [path, setPath] = useState(window.location.pathname)
const [key, setKey] = useState(window.location.href)
// Track Path
useEffect(() => {
const onPop = () => {
setPath(window.location.pathname)
setKey(window.location.href)
}
window.addEventListener('popstate', onPop)
return () => window.removeEventListener('popstate', onPop)
}, [])
// Match Component
const views = new Array<{ route: RegExp; scroll: boolean; component: (m: RegExpMatchArray) => ReactNode }>(
{ route: /^\/art\/([0-9]+)$/, scroll: false, component: (m) => <ViewAnimation key={key} id={m[1]} /> },
{ route: /^\/text\/([a-z-]+)$/, scroll: true, component: (m) => <ViewText key={key} id={m[1]} /> },
{ route: /^\/personal$/, scroll: true, component: (_) => <ViewPersonal /> },
{ route: /^\/upload$/, scroll: false, component: (_) => <ViewUpload key={key} /> },
{ route: /^\/settings$/, scroll: true, component: (_) => <ViewSettings key={key} /> },
{ route: /^\/search$/, scroll: true, component: (_) => <ViewSearch key={key} /> },
{ route: /^\/$/, scroll: true, component: (_) => <ViewHomepage key={key} /> },
)
const match = views.map((v) => ({ v, m: path.match(v.route) })).find(({ m }) => m !== null)
const relevant = match ? { ...match.v, component: match.v.component(match.m!) } : null
// Render Content
return (
<ScrollContext.Provider value={mainElem}>
<main ref={setMainElem} className={`layout-content ${relevant?.scroll ? 'layout-scrolling' : ''}`}>
{relevant ? (
relevant.component
) : (
<>
<HeaderMessage label="System Message" />
<HeaderError reason="The page you requested was not found." />
</>
)}
</main>
</ScrollContext.Provider>
)
}
@@ -0,0 +1,18 @@
import { type ReactNode } from 'react'
import './styles/PaneGlass.css'
interface PropsForPaneGlass {
children?: ReactNode
}
export default function PaneGlass({ children }: PropsForPaneGlass) {
return (
<div className="layout-glass-container">
<div className="layout-glass-corner" />
<div className="layout-glass-corner" />
<div className="layout-glass-corner" />
<div className="layout-glass-corner" />
{children}
</div>
)
}
@@ -0,0 +1,73 @@
import { useEffect, useState } from 'react'
import type { BackendTag } from '../../functions/BackendTypes'
import { BackendFetch } from '../../functions/Backend'
import { routeTo } from '../../functions/Route'
import VectorIconStar from '../../vectors/star.svg'
import VectorIconFeed from '../../vectors/feed.svg'
import SidebarCategory from '../layout/SidebarCategory'
import SidebarItemLogo from '../layout/SidebarItemLogo'
import SidebarItemText from '../layout/SidebarItemText'
import SidebarItemIcon from '../layout/SidebarItemIcon'
import SidebarItemTag from '../layout/SidebarItemTag'
import InputTags from '../inputs/Tags'
export default function PaneSidebar() {
const [childrenTags, setChildrenTags] = useState([<a className="item-tag dummy">... LOADING ...</a>])
useEffect(() => {
BackendFetch<BackendTag[]>('/tags/popular?limit=5').then((resp) => {
if (!resp.success) {
console.error('Tags Unavailable:', resp)
setChildrenTags([
<a className="item-tag dummy">... ERROR ...</a>,
<a className="item-tag dummy">VIEW CONSOLE FOR DETAILS</a>,
])
return
}
setChildrenTags(
resp.json.map((i) => <SidebarItemTag key={i.id} id={i.id} usage={i.usage} label={i.label} />),
)
})
}, [])
function onTagChange(tags: BackendTag[]) {
const query = tags.map((t) => `tag=${t.id}`).join('&')
routeTo(`/search?${query}`)
}
return (
<nav className="layout-sidebar layout-scrolling">
<SidebarCategory label="Main">
<SidebarItemLogo />
<InputTags label="" allowCustom={false} onChange={onTagChange} />
</SidebarCategory>
<SidebarCategory label="Sections">
<SidebarItemIcon
icon={VectorIconFeed}
label="Upload"
description="Submit new animation"
location="/upload"
/>
<SidebarItemIcon
icon={VectorIconStar}
label="Personal"
description="From this device"
location="/personal"
/>
</SidebarCategory>
<SidebarCategory label="Popular" header={true}>
{childrenTags}
</SidebarCategory>
<SidebarCategory label="Links" header={true}>
<SidebarItemText label="Terms of Service" location="/text/terms-of-service" />
<SidebarItemText label="Privacy Policy" location="/text/privacy-policy" />
<SidebarItemText label="API Guide" location="/text/api-guide" />
<SidebarItemText label="Settings" location="/settings" />
</SidebarCategory>
</nav>
)
}
@@ -0,0 +1,45 @@
div.layout-glass-container {
backdrop-filter: blur(var(--effect-glass-blur));
margin: var(--effect-glass-corner-margin);
background: var(--effect-glass-tint);
height: fit-content;
}
div.layout-glass-corner {
position: absolute;
width: 24px;
height: 24px;
pointer-events: none;
}
div.layout-glass-corner:nth-child(1) {
/* Top-left */
top: var(--effect-glass-corner-offset);
left: var(--effect-glass-corner-offset);
border-top: var(--effect-glass-corner-thickness) solid var(--effect-glass-corner-color);
border-left: var(--effect-glass-corner-thickness) solid var(--effect-glass-corner-color);
}
div.layout-glass-corner:nth-child(2) {
/* Top-right */
top: var(--effect-glass-corner-offset);
right: var(--effect-glass-corner-offset);
border-top: var(--effect-glass-corner-thickness) solid var(--effect-glass-corner-color);
border-right: var(--effect-glass-corner-thickness) solid var(--effect-glass-corner-color);
}
div.layout-glass-corner:nth-child(3) {
/* Bottom-left */
bottom: var(--effect-glass-corner-offset);
left: var(--effect-glass-corner-offset);
border-bottom: var(--effect-glass-corner-thickness) solid var(--effect-glass-corner-color);
border-left: var(--effect-glass-corner-thickness) solid var(--effect-glass-corner-color);
}
div.layout-glass-corner:nth-child(4) {
right: var(--effect-glass-corner-offset);
/* Bottom-right */
bottom: var(--effect-glass-corner-offset);
border-right: var(--effect-glass-corner-thickness) solid var(--effect-glass-corner-color);
border-bottom: var(--effect-glass-corner-thickness) solid var(--effect-glass-corner-color);
}