Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
5db6904
extrapolate color palette types from styled system
officialMECH Jan 21, 2026
7754a7b
make list collection compositions more flexible
officialMECH Jan 21, 2026
c131396
break up common atomic ui patterns into hooks
officialMECH Jan 22, 2026
3b71e63
clean up configs for styled system
officialMECH Jan 27, 2026
ecaaa12
move data attributes to aria labels
officialMECH Jan 27, 2026
15dd9fc
add new patterns for styled wrapper components
officialMECH Jan 27, 2026
ae12e0a
move recipes to styled system preset
officialMECH Jan 28, 2026
ceb32de
add escape hatch for polymorphic components
officialMECH Jan 31, 2026
fed2392
improve atomic components for new rendering patterns
officialMECH Feb 2, 2026
6453fd5
new prompt api for better portability
officialMECH Feb 3, 2026
faaea39
refactor mdx components
officialMECH Feb 5, 2026
b59c867
fix render logic for polymorphic components
officialMECH Feb 6, 2026
b103aad
upgrade compositions for atomic ui components
officialMECH Feb 8, 2026
7e40711
better apis for local file compositions
officialMECH Feb 9, 2026
cd1d228
relocate shortcut components to more intuitive scopes
officialMECH Feb 9, 2026
31a1e4a
make app layout exports more consistent
officialMECH Feb 9, 2026
f052e6d
simplify composition for editor action panel
officialMECH Feb 9, 2026
3a47961
compose new layouts for editor ui templates
officialMECH Feb 10, 2026
a084a45
small fixes for atomic ui components
officialMECH Feb 10, 2026
318341b
refactors for shared component hooks
officialMECH Feb 10, 2026
201500d
organize event grid template into composable layout
officialMECH Feb 11, 2026
a42a12b
organize app forms and fix related components
officialMECH Feb 12, 2026
5a07589
fix bindings for field components
officialMECH Feb 12, 2026
8f8fa54
small fixes for icon components
officialMECH Feb 14, 2026
a8b6d34
organize (and fix) docs components
officialMECH Feb 14, 2026
c1f6dec
clean up atomic scene components
officialMECH Feb 15, 2026
09a42c6
move logic for track mover to dedicated hook
officialMECH Feb 15, 2026
3b528d0
break off light spring into a standalone hook
officialMECH Feb 15, 2026
13f4c25
new composable layout for beat markers
officialMECH Feb 15, 2026
5e45f48
new composable layout for beatmap visualization
officialMECH Feb 16, 2026
c546038
improve prop forwarding for note components
officialMECH Feb 16, 2026
df523f4
refactor compositions for environment templates
officialMECH Feb 16, 2026
ec10f8c
more clean up for app/scene components
officialMECH Feb 16, 2026
09fb045
update context and meta tags for nested routes
officialMECH Feb 19, 2026
330efd8
various fixes for style consistency
officialMECH Feb 19, 2026
3b9edb2
update ui dependencies
officialMECH Feb 19, 2026
2865793
add tanstack devtools suite
officialMECH Feb 19, 2026
8402182
fixes for regressions with deps updates
officialMECH Feb 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
"[typescript]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[typescriptreact]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[mdx]": {
"editor.defaultFormatter": "unifiedjs.vscode-mdx"
},
Expand Down
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="en" class="dark">
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="description" content="A web-based level editor for Beat Saber™."/>
Expand Down
71 changes: 38 additions & 33 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@
"test": "vitest"
},
"dependencies": {
"@ark-ui/react": "^5.23.0",
"@fontsource-variable/inconsolata": "^5.2.7",
"@fontsource-variable/oswald": "^5.2.6",
"@fontsource-variable/raleway": "^5.2.6",
"@react-spring/three": "^10.0.2",
"@react-spring/web": "^10.0.2",
"@react-three/drei": "^10.7.5",
"@react-three/fiber": "^9.3.0",
"@ark-ui/react": "^5.31.0",
"@fontsource-variable/inconsolata": "^5.2.8",
"@fontsource-variable/oswald": "^5.2.8",
"@fontsource-variable/raleway": "^5.2.8",
"@mdx-js/mdx": "^3.1.1",
"@react-spring/three": "^10.0.3",
"@react-spring/web": "^10.0.3",
"@react-three/drei": "^10.7.7",
"@react-three/fiber": "^9.5.0",
"@react-three/postprocessing": "^3.0.4",
"@reduxjs/toolkit": "^2.9.0",
"@standard-schema/spec": "^1.0.0",
Expand All @@ -30,52 +31,57 @@
"@std/path": "jsr:^1.1.2",
"@std/random": "jsr:^0.1.2",
"@std/text": "jsr:^1.0.16",
"@tanstack/react-form": "^1.19.5",
"@tanstack/react-pacer": "^0.16.2",
"@tanstack/react-query": "^5.87.4",
"@tanstack/react-router": "^1.131.36",
"@tanstack/react-router-devtools": "^1.131.36",
"@tanstack/react-form": "^1.28.3",
"@tanstack/react-pacer": "^0.20.0",
"@tanstack/react-query": "^5.90.21",
"@tanstack/react-router": "^1.161.1",
"@tanstack/react-table": "^8.21.3",
"@zag-js/color-utils": "^1.22.1",
"@zag-js/file-utils": "^1.22.1",
"@zag-js/color-utils": "^1.33.1",
"@zag-js/file-utils": "^1.33.1",
"bsmap": "^2.2.9",
"date-fns": "^4.1.0",
"fflate": "^0.8.2",
"file-saver": "^2.0.5",
"idb": "^8.0.3",
"lucide-react": "^0.543.0",
"react": "^19.1.1",
"react-dom": "^19.1.1",
"lucide-react": "^0.574.0",
"postprocessing": "^6.38.2",
"react": "^19.2.4",
"react-dom": "^19.2.4",
"react-redux": "^9.2.0",
"redux-state-sync": "^3.1.4",
"redux-undo": "^1.1.0",
"three": "^0.174.0",
"three-stdlib": "^2.36.0",
"three": "^0.183.0",
"unstorage": "^1.17.1",
"valibot": "^1.1.0",
"waveform-data": "^4.5.2"
},
"devDependencies": {
"@biomejs/biome": "2.2.4",
"@pandacss/dev": "^1.3.0",
"@pandacss/preset-base": "^1.3.0",
"@tanstack/router-cli": "^1.131.36",
"@tanstack/router-plugin": "^1.131.36",
"@tanstack/virtual-file-routes": "^1.131.2",
"@pandacss/dev": "^1.8.2",
"@pandacss/types": "^1.8.2",
"@tanstack/devtools-vite": "^0.5.1",
"@tanstack/react-devtools": "^0.9.6",
"@tanstack/react-form-devtools": "^0.2.16",
"@tanstack/react-pacer-devtools": "^0.5.2",
"@tanstack/react-query-devtools": "^5.91.3",
"@tanstack/react-router-devtools": "^1.161.1",
"@tanstack/router-cli": "^1.161.1",
"@tanstack/router-plugin": "^1.161.1",
"@tanstack/virtual-file-routes": "^1.154.7",
"@types/file-saver": "^2.0.7",
"@types/node": "^22.18.1",
"@types/react": "^19.1.12",
"@types/react-dom": "^19.1.9",
"@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
"@types/redux-state-sync": "^3.1.10",
"@types/three": "^0.174.0",
"@types/three": "^0.183.0",
"@velite/plugin-vite": "^0.0.1",
"@vite-pwa/assets-generator": "^1.0.1",
"@vitejs/plugin-react": "^5.0.2",
"@vitejs/plugin-react": "^5.1.4",
"concurrently": "^9.2.1",
"lefthook": "^1.12.4",
"mdx": "^0.3.1",
"rehype-expressive-code": "^0.41.3",
"rehype-github-alerts": "^4.1.1",
"rehype-expressive-code": "^0.41.6",
"rehype-github-alerts": "^4.2.0",
"rehype-slug": "^6.0.0",
"remark-gfm": "^4.0.1",
"typescript": "^5.9.2",
Expand All @@ -85,7 +91,6 @@
"vitest": "^3.2.4"
},
"resolutions": {
"@types/react": "^18",
"redux": "^5"
"three-stdlib": "^2.36.1"
}
}
18 changes: 14 additions & 4 deletions panda.config.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
import { defineConfig } from "@pandacss/dev";
import { default as base } from "@pandacss/preset-base";
import { defineConfig, definePlugin } from "@pandacss/dev";

import { default as beatmapper } from "./src/styles/preset";

const removePandaTokens = definePlugin({
name: "remove-colors",
hooks: {
"preset:resolved": ({ utils, preset, name }) => {
if (name === "@pandacss/preset-panda") return utils.omit(preset, ["theme.tokens.colors", "theme.semanticTokens.colors"]);
return preset;
},
},
});

export default defineConfig({
preflight: true,
include: ["./src/**/*.{js,jsx,ts,tsx}", "./pages/**/*.{js,jsx,ts,tsx}"],
include: ["./src/**/*.{js,jsx,ts,tsx}"],
importMap: "$:styled-system",
outdir: "styled-system",
presets: [base, beatmapper({})],
presets: ["@pandacss/preset-base", "@pandacss/preset-panda", beatmapper({})],
plugins: [removePandaTokens],
jsxFramework: "react",
jsxStyleProps: "none",
shorthands: false,
Expand Down
18 changes: 0 additions & 18 deletions src/components/app/atoms/file.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion src/components/app/atoms/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { LocalFilePreview, type LocalFileProps } from "./file";
export { LocalFile } from "./local-file";
20 changes: 20 additions & 0 deletions src/components/app/atoms/local-file.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { ReactNode } from "react";

import { useLocalFileQuery } from "$/components/app/hooks/local-file.hooks";
import { convertFileToDataUrl } from "$/helpers/file.helpers";

export interface LocalFileProps {
filename: string;
fallback?: ReactNode;
children: (src: string | undefined, isLoading: boolean) => ReactNode;
}
export function LocalFile({ filename, fallback, children }: LocalFileProps) {
const { data: url, isLoading } = useLocalFileQuery<string>(filename, {
queryKey: ["supplier"],
transformFile: async (file) => await convertFileToDataUrl(file),
});

if (!url) return fallback;

return children(url, isLoading);
}
50 changes: 0 additions & 50 deletions src/components/app/compositions/file-upload.tsx

This file was deleted.

35 changes: 0 additions & 35 deletions src/components/app/compositions/file.tsx

This file was deleted.

5 changes: 1 addition & 4 deletions src/components/app/compositions/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,2 @@
export { CoverArtFilePreview } from "./file";
export { LocalFileUpload, MapArchiveFileUpload } from "./file-upload";
export { CoverArtFile } from "./local-file";
export { default as Logo } from "./logo";
export { AppPrompter, useAppPrompterContext } from "./prompter";
export { Shortcut } from "./shortcut";
29 changes: 29 additions & 0 deletions src/components/app/compositions/local-file.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type { Assign } from "@ark-ui/react";
import { type ComponentProps, useMemo } from "react";

import { LocalFile } from "$/components/app/atoms";
import { Spinner } from "$/components/ui/compositions";
import { Center, styled } from "$:styled-system/jsx";

export interface CoverArtProps {
boxSize?: number;
}
export function CoverArtFile({ filename, boxSize, ...rest }: Assign<ComponentProps<typeof CoverArt>, CoverArtProps & { filename: string }>) {
const style = useMemo(() => ({ width: boxSize, height: boxSize }), [boxSize]);

return (
<Center style={style}>
<LocalFile filename={filename} fallback={<Spinner />}>
{(src) => <CoverArt {...rest} src={src} style={style} />}
</LocalFile>
</Center>
);
}

const CoverArt = styled("img", {
base: {
objectFit: "cover",
borderRadius: "sm",
aspectRatio: "square",
},
});
33 changes: 18 additions & 15 deletions src/components/app/compositions/logo.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { animated as a, useSpring } from "@react-spring/three";
import { Canvas } from "@react-three/fiber";
import { Link } from "@tanstack/react-router";
import { Link, useRouteContext } from "@tanstack/react-router";
import { createColorNote, NoteDirection } from "bsmap";
import type { EnvironmentAllName } from "bsmap/types";
import { type DateArg, endOfMonth, endOfWeek, isWithinInterval, startOfMonth, startOfWeek } from "date-fns";
import { getYear, isThisMonth, isThisWeek, setYear } from "date-fns";
import { useMemo, useRef, useState } from "react";

import { ColorNote } from "$/components/scene/compositions";
Expand All @@ -12,26 +12,29 @@ import { HStack, Stack, styled } from "$:styled-system/jsx";

const MOCK_NOTE = createColorNote({ direction: NoteDirection.DOWN });

function checkDate(date: `${number}/${number}`, start: (date: DateArg<Date>) => Date, end: (date: DateArg<Date>) => Date) {
const today = new Date();
return isWithinInterval(today, { start: start(`${date}/${today.getFullYear()}`), end: end(`${date}/${today.getFullYear()}`) });
}

function deriveNoteColor() {
function deriveNoteColor(now: number) {
let environment: EnvironmentAllName = "DefaultEnvironment" as const;
if (checkDate("06/01", startOfMonth, endOfMonth)) environment = "GagaEnvironment";
if (checkDate("10/31", startOfWeek, endOfWeek)) environment = "HalloweenEnvironment";

if (isThisMonth(setYear("06/01", getYear(now)))) {
environment = "GagaEnvironment";
}
if (isThisWeek(setYear("10/31", getYear(now)))) {
environment = "HalloweenEnvironment";
}

const { colorLeft, colorRight } = deriveColorSchemeFromEnvironment(environment);
if (import.meta.env.DEV) return colorRight;
return colorLeft;
return import.meta.env.DEV ? colorRight : colorLeft;
}

interface Props {
size?: "full" | "mini";
}
function Logo({ size = "full" }: Props) {
const { now } = useRouteContext({ from: "__root__" });

const [isHovering, setIsHovering] = useState(false);
const color = useRef(deriveNoteColor());

const color = useRef(deriveNoteColor(now));

const [spring] = useSpring(() => ({ rotation: isHovering ? 0 : -0.35 }), [isHovering]);

Expand All @@ -47,7 +50,7 @@ function Logo({ size = "full" }: Props) {
<HStack gap={1}>
<Canvas style={styles}>
<a.group rotation-y={spring.rotation}>
<ColorNote position={[0, 0, 2]} data={MOCK_NOTE} color={color.current} size={3} />
<ColorNote position={[0, 0, 2]} scale={3} data={MOCK_NOTE} color={color.current} />
</a.group>
<ambientLight intensity={1.5} />
<directionalLight intensity={0.5} position={[0, 30, 8]} />
Expand Down Expand Up @@ -81,7 +84,7 @@ const Subtitle = styled("span", {
base: {
color: "fg.muted",
fontFamily: "body",
fontWeight: "medium",
fontWeight: "normal",
},
variants: {
size: {
Expand Down
Loading