DreamKnob/packages/dreamknob/src/primitives/Pointer.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

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>;
};