Spaces:
Running
Running
File size: 4,268 Bytes
3aea7c6 18b0fa5 3aea7c6 18b0fa5 3aea7c6 18b0fa5 3aea7c6 18b0fa5 3aea7c6 18b0fa5 3aea7c6 18b0fa5 3aea7c6 18b0fa5 3aea7c6 18b0fa5 3aea7c6 18b0fa5 3aea7c6 18b0fa5 3aea7c6 18b0fa5 3aea7c6 18b0fa5 3aea7c6 18b0fa5 3aea7c6 18b0fa5 3aea7c6 18b0fa5 3aea7c6 18b0fa5 3aea7c6 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
/**
* Combines and optimizes CSS class names using clsx and tailwind-merge
*
* This utility function combines multiple class names and resolves
* Tailwind CSS conflicts by keeping the last conflicting class.
*
* @param inputs - Class values to combine (strings, objects, arrays)
* @returns Optimized class name string
*
* @example
* cn('px-2 py-1', 'px-4') // Result: 'py-1 px-4'
* cn('text-red-500', condition && 'text-blue-500') // Conditional classes
*/
export function cn(...inputs: ClassValue[]): string {
return twMerge(clsx(inputs));
}
// === Servo Position and Angle Conversion Functions ===
/**
* Converts a servo position to an angle in degrees
*
* Servo positions range from 0 to 4096, representing a full 360° rotation.
* This function maps the position to its corresponding angle.
*
* @param position - The servo position (0 to 4096)
* @returns The corresponding angle (0 to 360 degrees)
*
* @example
* servoPositionToAngle(0) // Returns: 0
* servoPositionToAngle(2048) // Returns: 180
* servoPositionToAngle(4096) // Returns: 360
*/
export function servoPositionToAngle(position: number): number {
return (position / 4096) * 360;
}
/**
* Converts degrees to a servo position
*
* Maps angle in degrees to the corresponding servo position value.
* Clamps the result to the valid servo range (0-4096).
*
* @param degrees - The angle in degrees (0 to 360)
* @returns The corresponding servo position (0 to 4096)
*
* @example
* degreesToServoPosition(0) // Returns: 0
* degreesToServoPosition(180) // Returns: 2048
* degreesToServoPosition(360) // Returns: 4096
*/
export function degreesToServoPosition(degrees: number): number {
return Math.min(Math.round((degrees * 4096) / 360), 4096);
}
// === Angle Unit Conversion Functions ===
/**
* Converts radians to degrees
*
* @param radians - The angle in radians
* @returns The angle in degrees
*
* @example
* radiansToDegrees(Math.PI) // Returns: 180
* radiansToDegrees(Math.PI / 2) // Returns: 90
*/
export function radiansToDegrees(radians: number): number {
return (radians * 180) / Math.PI;
}
/**
* Converts degrees to radians
*
* @param degrees - The angle in degrees
* @returns The angle in radians
*
* @example
* degreesToRadians(180) // Returns: Math.PI
* degreesToRadians(90) // Returns: Math.PI / 2
*/
export function degreesToRadians(degrees: number): number {
return (degrees * Math.PI) / 180;
}
/**
* Converts radians to a servo position
*
* Combines radian-to-degree conversion with servo position mapping.
* Useful for direct conversion from joint angles to servo commands.
*
* @param radians - The angle in radians
* @returns The corresponding servo position (0 to 4096)
*
* @example
* radiansToServoPosition(0) // Returns: 0
* radiansToServoPosition(Math.PI) // Returns: 2048
* radiansToServoPosition(2*Math.PI) // Returns: 4096
*/
export function radiansToServoPosition(radians: number): number {
return Math.min(Math.round((radians * 4096) / (2 * Math.PI)), 4096);
}
// === TypeScript Utility Types ===
/**
* Utility type that removes the 'child' property from a type
* Useful for component prop interfaces that shouldn't accept child elements
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type WithoutChild<T> = T extends { child?: any } ? Omit<T, "child"> : T;
/**
* Utility type that removes the 'children' property from a type
* Useful for component prop interfaces that shouldn't accept children
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type WithoutChildren<T> = T extends { children?: any } ? Omit<T, "children"> : T;
/**
* Utility type that removes both 'child' and 'children' properties
* Combines WithoutChild and WithoutChildren for maximum flexibility
*/
export type WithoutChildrenOrChild<T> = WithoutChildren<WithoutChild<T>>;
/**
* Utility type that adds an optional ref property for HTML element references
* @template T - The base type to extend
* @template U - The HTML element type (defaults to HTMLElement)
*/
export type WithElementRef<T, U extends HTMLElement = HTMLElement> = T & { ref?: U | null };
|