Skip to content

Commit

Permalink
Add Slider
Browse files Browse the repository at this point in the history
  • Loading branch information
gabe-serna committed Nov 7, 2024
1 parent 587bd8f commit 0e9d454
Show file tree
Hide file tree
Showing 7 changed files with 219 additions and 24 deletions.
64 changes: 40 additions & 24 deletions app/audio/MidiEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,33 +19,33 @@ import {
AccordionTrigger,
} from "@/components/ui/accordion";
import { Slider } from "@/components/ui/slider";
import { runInContext } from "vm";
import { Label } from "@/components/ui/label";
import AudioMixer from "@/components/AudioMixer";
import { Arc, Knob, Pointer, Value } from "rc-knob";

export default function MidiEditor() {
const { audioStorage } = useContext(AudioContext);
const midiAdjustments = useRef<HTMLButtonElement>(null);
const audioControls = useRef<HTMLButtonElement>(null);
const [controlsOpen, setControlsOpen] = useState(false);
const [midiOpen, setMidiOpen] = useState(false);
// const [controlsOpen, setControlsOpen] = useState(false);

const handleOpen: MouseEventHandler<HTMLButtonElement> = (event) => {
setTimeout(() => {
if (!midiAdjustments.current || !audioControls.current) return;
console.log(
midiAdjustments.current.dataset.state,
audioControls.current.dataset.state,
);
if (
midiAdjustments.current.dataset.state === "open" ||
audioControls.current.dataset.state === "open"
) {
setControlsOpen(true);
} else setControlsOpen(false);
// if (
// midiAdjustments.current.dataset.state === "open" ||
// audioControls.current.dataset.state === "open"
// ) {
// setControlsOpen(true);
// } else setControlsOpen(false);

if (midiAdjustments.current.dataset.state === "open") setMidiOpen(true);
else setMidiOpen(false);
}, 50);
};

useEffect(() => {
console.log("controlsOpen", controlsOpen);
}, [controlsOpen]);

return Object.entries(audioStorage as Record<keyof AudioStorage, Stem>).map(
([key, stem]) => {
if (!stem.midiBlob) return;
Expand All @@ -63,7 +63,9 @@ export default function MidiEditor() {
className="flex h-[565.6px] flex-col justify-between"
collapsible
>
<div className="flex flex-col space-y-4">
<div
className={`flex flex-col justify-between space-y-4 ${midiOpen ? "h-[565.6px]" : ""}`}
>
<AccordionItem value="midi-adjustments">
<AccordionTrigger
ref={midiAdjustments}
Expand All @@ -84,18 +86,32 @@ export default function MidiEditor() {
>
Audio Controls
</AccordionTrigger>
<AccordionContent className="flex h-32 flex-col gap-4 rounded-3xl border-2 border-border bg-card px-6 dark:bg-stone-900">
<Slider
orientation="vertical"
max={100}
<AccordionContent className="flex h-72 flex-col gap-4 rounded-3xl border-2 border-border bg-card px-6 dark:bg-stone-900">
{/* <AudioMixer name="Midi Audio" /> */}
{/* knob inside of the accordion content does not work because of the -translate-y-10 class */}
<Knob
size={100}
angleOffset={220}
angleRange={280}
steps={10}
snap={true}
min={0}
defaultValue={[50]}
className=""
/>
max={100}
// onChange={(value) => console.log(value)}
>
<Arc arcWidth={5} color="#FC5A96" radius={47.5} />
<Pointer
width={5}
radius={40}
type="circle"
color="#FC5A96"
/>
<Value marginBottom={40} className="value" />
</Knob>
</AccordionContent>
</AccordionItem>
</div>
{!controlsOpen && (
{!midiOpen && (
<div className="flex flex-col space-y-4">
<AccordionItem
value="next"
Expand Down
17 changes: 17 additions & 0 deletions app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,26 @@
"use client";
import { Arc, Knob, Pointer, Value } from "rc-knob";

export default async function Index() {
return (
<>
<main className="flex flex-1 flex-col gap-6 px-4">
<h1 className="mb-4 text-xl font-semibold">Songscribe</h1>
<p>The fastest way to turn any song into sheet music</p>
<Knob
size={100}
angleOffset={220}
angleRange={280}
steps={10}
snap={true}
min={0}
max={100}
// onChange={(value) => console.log(value)}
>
<Arc arcWidth={5} color="#FC5A96" radius={47.5} />
<Pointer width={5} radius={40} type="circle" color="#FC5A96" />
<Value marginBottom={40} className="value" />
</Knob>
</main>
</>
);
Expand Down
42 changes: 42 additions & 0 deletions components/AudioMixer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { Label } from "@/components/ui/label";
import { Slider } from "@/components/ui/slider";
import { Knob, Pointer, Scale, Arc, Value } from "rc-knob";
import { useState } from "react";

export default function AudioMixer({ name }: { name: string }) {
const defaultValue = [50];
const [value, setValue] = useState(defaultValue);
const htmlName = name.toLowerCase().replace(" ", "_");

return (
<div className="flex h-full w-max flex-col-reverse items-center justify-center">
<Label htmlFor={htmlName} className="mt-4">
{name}
</Label>
{/* <Knob
size={100}
angleOffset={220}
angleRange={280}
steps={10}
snap={true}
min={0}
max={100}
// onChange={(value) => console.log(value)}
>
<Arc arcWidth={5} color="#FC5A96" radius={47.5} />
<Pointer width={5} radius={40} type="circle" color="#FC5A96" />
<Value marginBottom={40} className="value" />
</Knob> */}
<p className="w-14 text-center text-card-foreground">{value}</p>
<Slider
name={htmlName}
min={0}
max={100}
value={value}
defaultValue={defaultValue}
onValueChange={(val) => setValue(val)}
orientation="vertical"
/>
</div>
);
}
34 changes: 34 additions & 0 deletions components/KnobPortal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"use client";
import React from "react";
import { createPortal } from "react-dom";
import { Knob, Pointer, Scale, Arc, Value } from "rc-knob";

interface KnobPortalProps {
value: number;
onChange: (value: number) => void;
}

const KnobPortal: React.FC<KnobPortalProps> = ({ value, onChange }) => {
return createPortal(
<Knob
size={100}
angleOffset={220}
angleRange={280}
steps={10}
snap={true}
min={0}
max={100}
value={value}
onChange={onChange}
ariaLabelledBy="knob-label"
ariaValueText={`Value: ${value}`}
>
<Arc arcWidth={5} color="#FC5A96" radius={47.5} />
<Pointer width={5} radius={40} type="circle" color="#FC5A96" />
<Value marginBottom={40} className="value" />
</Knob>,
document.body, // Render the Knob at the end of the body
);
};

export default KnobPortal;
10 changes: 10 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"midi-file": "^1.2.4",
"next": "^14.2.15",
"next-themes": "^0.3.0",
"rc-knob": "^1.0.1",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-hook-form": "^7.53.1",
Expand Down
75 changes: 75 additions & 0 deletions rc-knob.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// rc-knob.d.ts
declare module "rc-knob" {
import { ReactNode, FC } from "react";

interface KnobProps {
min?: number;
max?: number;
value?: number;
angleOffset?: number;
angleRange?: number;
size?: number;
steps?: number;
snap?: boolean;
ariaValueText?: string;
ariaLabelledBy?: string;
onChange?: (value: number) => void;
className?: string;
children?: ReactNode;
}

interface PointerProps {
width?: number;
height?: number;
angleOffset?: number;
angleRange?: number;
percentage?: number;
radius?: number;
center?: number;
type?: "rect" | "circle";
color?: string;
className?: string;
}

interface ScaleProps {
angleRange?: number;
steps?: number;
type?: "rect" | "circle";
radius?: number;
tickWidth?: number;
tickHeight?: number;
angleOffset?: number;
center?: number;
color?: string;
activeColor?: string;
className?: string;
activeClassName?: string;
fn?: (props: any) => ReactNode;
percentage?: number;
}

interface ArcProps {
color?: string;
background?: string;
percentage?: number;
angleOffset?: number;
angleRange?: number;
radius?: number;
arcWidth?: number;
center?: number;
}

interface ValueProps {
value?: number;
size?: number;
decimalPlace?: number;
className?: string;
marginBottom?: number;
}

export const Knob: FC<KnobProps>;
export const Pointer: FC<PointerProps>;
export const Scale: FC<ScaleProps>;
export const Arc: FC<ArcProps>;
export const Value: FC<ValueProps>;
}

0 comments on commit 0e9d454

Please sign in to comment.