DreamKnob/packages/dreamknob/src/skins/NeonKnob.tsx
Dreamodus 60a02cb1db Initial release: dreamknob library + showcase
React + TypeScript knob/fader library with a headless interaction core
(rotary, relative-drag and track modes, wheel, keyboard, a11y), SVG
primitives, nine prebuilt skins, seven-segment display engine, and a
Vite showcase with gallery, live playground and API docs.
2026-07-12 14:26:52 -07:00

86 lines
2.3 KiB
TypeScript

import * as React from 'react';
import { Knob } from '../components/Knob';
import { Arc } from '../primitives/Arc';
import { Pointer } from '../primitives/Pointer';
import { KnobLabel, KnobValue } from '../primitives/Text';
import { MONO_FONT, UI_FONT, type SkinProps } from './shared';
export interface NeonKnobProps extends SkinProps {
color?: string;
trackColor?: string;
textColor?: string;
labelColor?: string;
arcFrom?: 'min' | 'center';
}
/** Minimal glowing arc knob — futuristic / dark-mode DAW style. */
export const NeonKnob: React.FC<NeonKnobProps> = ({
size = 84,
color = '#e44cff',
trackColor = 'rgba(255,255,255,0.06)',
textColor,
labelColor = 'rgba(255,255,255,0.4)',
arcFrom = 'min',
label,
showValue = true,
unit,
format,
className,
style,
...core
}) => {
const id = React.useId();
const glowId = `${id}-glow`;
return (
<Knob size={size} className={className} style={style} {...core}>
<defs>
<filter
id={glowId}
filterUnits="userSpaceOnUse"
x={-size * 0.3}
y={-size * 0.3}
width={size * 1.6}
height={size * 1.6}
>
<feGaussianBlur stdDeviation={size * 0.035} result="b1" />
<feGaussianBlur in="SourceGraphic" stdDeviation={size * 0.012} result="b2" />
<feMerge>
<feMergeNode in="b1" />
<feMergeNode in="b2" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>
<Arc
radius={size / 2 - size * 0.09}
thickness={Math.max(2.5, size * 0.035)}
color={color}
trackColor={trackColor}
from={arcFrom}
arcProps={{ filter: `url(#${glowId})` }}
/>
<Pointer
type="circle"
radius={size / 2 - size * 0.09}
width={Math.max(2.5, size * 0.035)}
color="#ffffff"
shapeProps={{ filter: `url(#${glowId})` }}
/>
{showValue && (
<KnobValue
color={textColor ?? color}
unit={unit}
format={format}
fontSize={size * 0.17}
fontFamily={MONO_FONT}
textProps={{ filter: `url(#${glowId})` }}
/>
)}
{label && (
<KnobLabel color={labelColor} fontFamily={UI_FONT} dy={size * 0.45} fontSize={size * 0.1}>
{label}
</KnobLabel>
)}
</Knob>
);
};