Next.js app with a browser-side buttplug/buttplug-wasm control layer (server never touches real-time device commands), SQLite storage via Drizzle, single-secret auth, recordings/replay with device remapping, a usage stats dashboard, Docker deployment, and Gitea CI. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W8WkFF5ppURBAB918593Eb
32 lines
906 B
TypeScript
32 lines
906 B
TypeScript
"use client";
|
|
|
|
import { Slider } from "@/components/ui/slider";
|
|
import type { ActuatorInfo } from "@/lib/buttplug/types";
|
|
|
|
interface ActuatorSliderProps {
|
|
actuator: ActuatorInfo;
|
|
value: number;
|
|
transmitting: boolean;
|
|
onChange: (value: number) => void;
|
|
}
|
|
|
|
export function ActuatorSlider({ actuator, value, transmitting, onChange }: ActuatorSliderProps) {
|
|
return (
|
|
<div className="flex flex-col gap-1.5">
|
|
<div className="flex items-center justify-between text-xs">
|
|
<span className="font-medium text-foreground">{actuator.descriptor}</span>
|
|
<span className={transmitting ? "bp-gradient-text font-semibold" : "text-muted-foreground"}>
|
|
{Math.round(value * 100)}%
|
|
</span>
|
|
</div>
|
|
<Slider
|
|
value={[value * 100]}
|
|
min={0}
|
|
max={100}
|
|
step={1}
|
|
onValueChange={([v]) => onChange(v / 100)}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|