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.
73 lines
2 KiB
TypeScript
73 lines
2 KiB
TypeScript
import * as React from 'react';
|
|
import { useKnobContext } from '../core/context';
|
|
|
|
export interface PointerProps {
|
|
/** Built-in shapes. Provide children instead for a custom pointer. */
|
|
type?: 'line' | 'circle' | 'triangle';
|
|
/** Distance from center to the pointer's outer end. Defaults to size/2 - 4. */
|
|
radius?: number;
|
|
/** Length of the pointer along the radial axis. */
|
|
length?: number;
|
|
width?: number;
|
|
color?: string;
|
|
cap?: 'butt' | 'round';
|
|
/** Extra SVG props applied to the shape. */
|
|
shapeProps?: React.SVGProps<SVGElement>;
|
|
/** Custom pointer content, drawn pointing at 12 o'clock and rotated for you. */
|
|
children?: React.ReactNode;
|
|
}
|
|
|
|
/** Rotating indicator. Children (or the built-in shape) are authored pointing up. */
|
|
export const Pointer: React.FC<PointerProps> = ({
|
|
type = 'line',
|
|
radius,
|
|
length = 12,
|
|
width = 4,
|
|
color = 'currentColor',
|
|
cap = 'round',
|
|
shapeProps,
|
|
children,
|
|
}) => {
|
|
const { size, center, angle } = useKnobContext();
|
|
const r = radius ?? size / 2 - 4;
|
|
|
|
let shape: React.ReactNode = children;
|
|
if (!shape) {
|
|
if (type === 'line') {
|
|
shape = (
|
|
<line
|
|
x1={center}
|
|
y1={center - r}
|
|
x2={center}
|
|
y2={center - r + length}
|
|
stroke={color}
|
|
strokeWidth={width}
|
|
strokeLinecap={cap}
|
|
{...(shapeProps as React.SVGProps<SVGLineElement>)}
|
|
/>
|
|
);
|
|
} else if (type === 'circle') {
|
|
shape = (
|
|
<circle
|
|
cx={center}
|
|
cy={center - r + width / 2}
|
|
r={width}
|
|
fill={color}
|
|
{...(shapeProps as React.SVGProps<SVGCircleElement>)}
|
|
/>
|
|
);
|
|
} else {
|
|
const half = width / 2;
|
|
const tipY = center - r;
|
|
shape = (
|
|
<polygon
|
|
points={`${center},${tipY} ${center - half},${tipY + length} ${center + half},${tipY + length}`}
|
|
fill={color}
|
|
{...(shapeProps as React.SVGProps<SVGPolygonElement>)}
|
|
/>
|
|
);
|
|
}
|
|
}
|
|
|
|
return <g transform={`rotate(${angle} ${center} ${center})`}>{shape}</g>;
|
|
};
|