/** * Types exposed through the public API */ import type { VectorSettings } from "../components/Vector/vector-types.js"; import { StoreType, Data, DataInput } from "./internal.js"; import type { BeautifyUnionType, UnionToIntersection } from "./utils.js"; export type RenderFn = (get: (key: string) => any) => boolean; /** * Utility types that joins a value with its settings */ export type InputWithSettings = { [key in K]: V; } & { type?: LevaInputs; } & Settings; /** * Either the raw value, either the value with its settings * In other words => value || { value, ...settings } */ export type MergedInputWithSettings = V | InputWithSettings; /** * Special Inputs */ export declare enum SpecialInputs { BUTTON = "BUTTON", BUTTON_GROUP = "BUTTON_GROUP", MONITOR = "MONITOR", FOLDER = "FOLDER" } export declare enum LevaInputs { SELECT = "SELECT", IMAGE = "IMAGE", NUMBER = "NUMBER", COLOR = "COLOR", STRING = "STRING", BOOLEAN = "BOOLEAN", INTERVAL = "INTERVAL", VECTOR3D = "VECTOR3D", VECTOR2D = "VECTOR2D" } export type ButtonSettings = { disabled?: boolean; }; export type ButtonInput = { type: SpecialInputs.BUTTON; onClick: (get: (path: string) => any) => void; settings: ButtonSettings; }; export type ButtonGroupOpts = { [title: string]: (get: (path: string) => any) => void; }; export type ButtonGroupInputOpts = ButtonGroupOpts | { label?: string | React.JSX.Element | null; opts: ButtonGroupOpts; }; export type ButtonGroupInput = { type: SpecialInputs.BUTTON_GROUP; opts: ButtonGroupInputOpts; }; export type MonitorSettings = { graph?: boolean; interval?: number; }; export type MonitorInput = { type: SpecialInputs.MONITOR; objectOrFn: React.MutableRefObject | Function; settings: MonitorSettings; }; export type SpecialInput = MonitorInput | ButtonInput | ButtonGroupInput; export type FolderSettings = { collapsed?: boolean; render?: RenderFn; color?: string; /** works similar to css order property */ order?: number; }; export type NumberSettings = { min?: number; max?: number; step?: number; }; export type VectorObj = Record; export type Vector2dArray = [number, number]; export type Vector2d = Vector2dArray | VectorObj; export type Vector2dSettings = VectorSettings & { joystick?: boolean | 'invertY'; lock?: boolean; }; export type Vector2dInput = MergedInputWithSettings; export type Vector3dArray = [number, number, number]; export type Vector3d = Vector3dArray | VectorObj; export type Vector3dSettings = VectorSettings & { lock?: boolean; }; export type Vector3dInput = MergedInputWithSettings; export type IntervalInput = { value: [number, number]; min: number; max: number; }; export type ImageInput = { image: undefined | string; }; type SelectInput = { options: any[] | Record; value?: any; }; type SelectWithValueInput = { options: T[] | Record; value: K; }; type SelectWithoutValueInput = { options: T[] | Record; }; type ColorRgbaInput = { r: number; g: number; b: number; a?: number; }; type ColorHslaInput = { h: number; s: number; l: number; a?: number; }; type ColorHsvaInput = { h: number; s: number; v: number; a?: number; }; export type ColorVectorInput = ColorRgbaInput | ColorHslaInput | ColorHsvaInput; type BooleanInput = boolean; type StringSettings = { rows?: boolean | number; editable?: boolean; }; type StringInput = InputWithSettings; export type FolderInput = { type: SpecialInputs.FOLDER; schema: Schema; settings: FolderSettings; }; export type CustomInput = { type: string; __customInput: Value; }; type SchemaItem = InputWithSettings | InputWithSettings | InputWithSettings | IntervalInput | ColorVectorInput | Vector2dInput | Vector3dInput | ImageInput | SelectInput | BooleanInput | StringInput | CustomInput; type GenericSchemaItemOptions = { render?: RenderFn; label?: string | React.JSX.Element; hint?: string; order?: number; }; type OnHandlerContext = DataInput & { get(path: string): any; }; type OnChangeHandlerContext = OnHandlerContext & { /** * Whether the onChange handler is invoked initially. */ initial: boolean; }; export type OnChangeHandler = (value: any, path: string, context: OnChangeHandlerContext) => void; type TransientOnChangeSchemaItemOptions = { onChange: OnChangeHandler; transient?: true; }; type NonTransientOnChangeSchemaItemOptions = { onChange: OnChangeHandler; transient: false; }; type NoOnChangeSchemaItemOptions = { onChange?: undefined; transient?: undefined; }; type OnChangeSchemaItemOptions = TransientOnChangeSchemaItemOptions | NonTransientOnChangeSchemaItemOptions | NoOnChangeSchemaItemOptions; export type InputOptions = GenericSchemaItemOptions & OnChangeSchemaItemOptions & { optional?: boolean; disabled?: boolean; onEditStart?: (value: any, path: string, context: OnHandlerContext) => void; onEditEnd?: (value: any, path: string, context: OnHandlerContext) => void; }; type SchemaItemWithOptions = number | boolean | string | (SchemaItem & InputOptions) | (SpecialInput & GenericSchemaItemOptions) | FolderInput; export type Schema = Record; /** * Dummy type used internally to flag non compatible input types. * @internal */ type NotAPrimitiveType = { ____: 'NotAPrimitiveType'; }; type PrimitiveToValue

= P extends CustomInput ? BeautifyUnionType : P extends ImageInput ? string | undefined : P extends SelectWithValueInput ? SelectValue | Options : P extends SelectWithoutValueInput ? Options : P extends IntervalInput ? [number, number] : P extends { value: infer Value; } ? PrimitiveToValue : P extends VectorObj ? P : P extends Vector3dArray ? [number, number, number] : P extends Vector2dArray ? [number, number] : P extends number ? number : P extends string ? string : P extends boolean ? boolean : NotAPrimitiveType; export type SchemaToValues = BeautifyUnionType>>; type EndLeaf = { ___leaf: 'leaf'; }; type Join = EndLeaf extends Leaf2 ? { [i in Leaf1Key]: Leaf1[Leaf1Key]; } : Leaf2; type Tree = { 0: Leaf extends { schema: infer Schema; } ? { [Key in keyof Schema]: Join; } : never; 1: never; 2: { [Key in LeafKey]: Leaf extends { optional: true; } | { disabled: true; } ? PrimitiveToValue | undefined : PrimitiveToValue; }; 3: { [Key in keyof Leaf]: Join>; }[keyof Leaf]; 4: EndLeaf; }[LeafKey extends '' ? 3 : Leaf extends FolderInput ? 0 : Leaf extends SpecialInput ? 1 : PrimitiveToValue extends NotAPrimitiveType ? Leaf extends object ? 3 : 4 : Leaf extends TransientOnChangeSchemaItemOptions ? IncludeTransient extends true ? 2 : 1 : 2]; /** * If P is '' then T is the whole schema and we shouldn't run any type check * on the schema, to the risk that { a: 1, b: 2 } is recognized as Vector * instead of a two number inputs. */ /** * Interface to build a plugin. * * @public */ export interface Plugin { /** * The component that shows the input value; */ component: React.ComponentType; /** * Normalizes the input into a { value, settings } object. * * @example * Let's consider a color with an inverted settings option that computes the negative * of that color. The plugin could look something like: * ```ts * myColorPlugin({ color: '#fff', inverted: true }) * ``` * * In that case, your normalize funciton would be something like: * ```ts * function normalize({ color, inverted }) { * return { value: color, settings: { inverted }} * } * ``` */ normalize?: (input: Input, path: string, data: Data) => { value: Value; settings?: InternalSettings; }; /** * Sanitizes the user value before registering it to the store. For * example, the Number plugin would santize "3.00" into 3. If the provided * value isn't formatted properly, the sanitize function should throw. */ sanitize?: (value: any, settings: InternalSettings, prevValue: any, path: string, store: StoreType) => Value; /** * Formats the value into the value that will be displayed by the component. * If the input value of the Number plugin, then format will add proper * padding and show "3.00". * (Prop name in useInputContext context hook is `displayedValue`) */ format?: (value: any, settings: InternalSettings) => any; } export type InputContextProps = { id: string; label: string | React.JSX.Element; hint?: string; path: string; key: string; optional: boolean; disabled: boolean; disable: (flag: boolean) => void; storeId: string; value: unknown; displayValue: unknown; onChange: React.Dispatch; emitOnEditStart: () => void; emitOnEditEnd: () => void; onUpdate: (v: any | ((v: any) => any)) => void; settings: unknown; setSettings: (v: any) => void; }; /** * Interface consumed by the useInputContext hook so that its returned values * are properly typed. * * @example * ```ts * useInputContext>() * ``` * @public */ export interface LevaInputProps { path?: string; id?: string; hint?: string; disabled?: boolean; displayValue: DisplayValue; value: V; onChange: React.Dispatch; emitOnEditStart: () => void; emitOnEditEnd: () => void; onUpdate: (v: any | ((v: any) => any)) => void; settings: InternalSettings; setSettings: (v: Partial) => void; } export {};