git-statistics 0.1.0

Collect commits from Git repository and present statistics in a comfortable way.
Documentation
import React, {type FocusEvent, useCallback} from 'react';
import {clsx} from 'clsx';
import {clamp} from 'lodash-es';

/* eslint-disable @typescript-eslint/consistent-type-definitions */
interface NumberInputProps extends React.HTMLProps<HTMLInputElement> {
	readonly onConfirm?: (value: number) => void;
}

export default function NumberInput({onConfirm, onChange, defaultValue, className, ...props}: NumberInputProps & React.HTMLProps<HTMLInputElement>) {
	const [previous, setPrevious] = React.useState<NumberInputProps['defaultValue']>(defaultValue);

	const onKeydown = useCallback((e: React.KeyboardEvent<HTMLInputElement> | FocusEvent<HTMLInputElement>) => {
		if (e.type === 'keydown' && (e as never as KeyboardEvent).key !== 'Enter') {
			return;
		}

		if (e.currentTarget.value === '') {
			e.currentTarget.value = String(previous);
		}

		let value = Number(e.currentTarget.value);
		value = clamp(value, props.min as number ?? -Infinity, props.max as number ?? Infinity);
		e.currentTarget.value = String(value);
		onConfirm?.(value);
	}, [onConfirm, previous]);

	const handleChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
		onChange?.(e);
		if (e.currentTarget.value === '') {
			return;
		}

		setPrevious(e.currentTarget.value);
	}, [onChange]);

	return (
		<input
			type='number'
			className={clsx(['input input-xs input-bordered', className])}
			defaultValue={defaultValue}
			onInput={handleChange}
			onKeyDown={onKeydown}
			onBlur={onKeydown}
			{...props}
		/>
	);
}