import { type KeyboardEvent as ReactKeyboardEvent, type RefObject } from 'react'; import type { AriaLabelingProps, DataTestId, StylingProps } from '@dynatrace/strato-components/core'; import type { FormControlProps } from '../../../core/types/form-control-props.js'; import type { SpinButtonTextSelection } from '../types.js'; /** * Configuration object on how a numeric value is formatted. * @internal */ export type NumberSpinButtonDisplayFormat = { /** * Number of characters the value is left padded with. * @defaultValue 0 */ length: number; /** * Characters to use for padding the value. * @defaultValue '0' */ chars?: string; }; /** * Props for the controlled and uncontrolled version for the NumberSpinButton component. * @internal */ export type NumberSpinButtonProps = FormControlProps void> & StylingProps & DataTestId & AriaLabelingProps & { /** * Handler is called on input but before an internal state update is done. * @param candidate - The candidate scheduled as new internal state * @param e - The input event containing necessary input details. The state update can be blocked by setting the provided event to default prevented. */ onBeforeInput?: (candidate: string, e: InputEvent) => void; /** * Callback transformer to modify the value on ArrowUp key press. * @param value - Current value of the number-spin-button * @param e - Details about the keyboard event. * @returns New numeric state to set to the spin button. * @defaultValue `(v) => v-1` */ onArrowUp?: (value: number | null, e: ReactKeyboardEvent) => number | null; /** * Callback transformer to modify the value on ArrowDown key press. * @param value - Current value of the number-spin-button * @param e - Details about the keyboard event. * @returns New numeric state to set to the spin button. * @defaultValue `(v) => v+1` */ onArrowDown?: (value: number | null, e: ReactKeyboardEvent) => number | null; /** * Callback transformer to modify the value on PageUp key press. * @param value - Current value of the number-spin-button * @param e - Details about the keyboard event. * @returns New numeric state to set to the spin button. * @defaultValue `(v) => v-10` */ onPageUp?: (value: number | null, e: ReactKeyboardEvent) => number | null; /** * Callback transformer to modify the value on PageDown key press. * @param value - Current value of the number-spin-button * @param e - Details about the keyboard event. * @returns New numeric state to set to the spin button. * @defaultValue `(v) => v+10` */ onPageDown?: (value: number | null, e: ReactKeyboardEvent) => number | null; /** * Callback transformer to modify the value on Home key press. * @param value - Current value of the number-spin-button * @param e - Details about the keyboard event. * @returns New numeric state to set to the spin button. * @defaultValue `(v) => minValue ?? v` */ onHome?: (value: number | null, e: ReactKeyboardEvent) => number | null; /** * Callback transformer to modify the value on Home key press. * @param value - Current value of the number-spin-button * @param e - Details about the keyboard event. * @returns New numeric state to set to the spin button. * @defaultValue `(v) => maxValue ?? v` */ onEnd?: (value: number | null, e: ReactKeyboardEvent) => number | null; /** * Lower value boundary. */ minValue?: number; /** * Upper value boundary. */ maxValue?: number; /** * Configuration object on how to format the numeric state. */ displayFormat?: NumberSpinButtonDisplayFormat; /** * Placeholder to show, if the text content of the spinbutton is empty. * @defaultValue '' */ placeholder?: string; /** * Whether the spinbutton is in readonly mode. * @defaultValue false */ readOnly?: boolean; /** * Whether the spinbutton is disabled. * @defaultValue false */ disabled?: boolean; /** * Whether a spinbutton value is required. * @defaultValue false */ required?: boolean; /** * Determine if the spinbutton is in error state or not. * @defaultValue false */ hasError?: boolean; /** * Callback transformer to modify the value on key press. */ onKeyDownHandler?: (e: ReactKeyboardEvent) => void; }; /** * Imperative handler to give access to the root span element of the spinbutton. * It provides additional methods to interact with the spinbutton. * @internal */ export interface NumberSpinButtonRef { /** Type of the spinbutton. */ type: 'number'; /** A ref to the root span element of the spinbutton. */ readonly element: RefObject; /** Set cursor selection. */ setSelection: (selection: SpinButtonTextSelection) => void; /** Get current cursor selection if the spinbutton has focus. Returns `undefined` otherwise. */ getSelection: () => SpinButtonTextSelection | undefined; /** Select all text content.*/ selectAll: () => void; /** Deselect any text selection. */ deselectAll: () => void; /** Apply a text value to the spinbutton. If possible, the input string will be parsed as an integer and updates the internal numeric state of the spinbutton. */ applyText: (input: string, fireOnChange?: boolean) => void; /** Clear the text content of the spinbutton. */ clearValue: (fireOnChange?: boolean) => void; }