mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 21:41:57 +00:00
91 lines
2.4 KiB
TypeScript
91 lines
2.4 KiB
TypeScript
'use client';
|
||
|
||
import { ChangeEvent } from 'react';
|
||
import {
|
||
PatternFormat,
|
||
NumberFormatBase,
|
||
NumberFormatBaseProps,
|
||
OnValueChange,
|
||
} from 'react-number-format';
|
||
import TextInput, { TextInputProps } from '@/components/input/TextInput';
|
||
|
||
interface PatternInputProps extends Omit<TextInputProps, 'type'> {
|
||
/**
|
||
* Format pattern, contoh: "##/##/####", "(###) ###-####", "####-####-####"
|
||
*/
|
||
format: string;
|
||
/** Mask karakter kosong, misal "_" */
|
||
mask?: string;
|
||
/** Menampilkan mask walau value kosong */
|
||
allowEmptyFormatting?: boolean;
|
||
/** Placeholder karakter format, default: "#" */
|
||
patternChar?: string;
|
||
/** Jika true, izinkan huruf (A-Z) selain angka */
|
||
inputVehicleNumber?: boolean;
|
||
type?: 'text' | 'password' | 'tel';
|
||
}
|
||
|
||
/**
|
||
* PatternInput – tetap backward-compatible dengan Storybook
|
||
* tapi bisa menerima huruf jika `allowCharacters={true}`
|
||
*/
|
||
const PatternInput = ({
|
||
type = 'text',
|
||
format,
|
||
mask = '_',
|
||
allowEmptyFormatting = false,
|
||
patternChar = '#',
|
||
inputVehicleNumber = false,
|
||
onChange,
|
||
...restProps
|
||
}: PatternInputProps) => {
|
||
const handleValueChange: OnValueChange = (values, { event }) => {
|
||
const newEvent = event as ChangeEvent<HTMLInputElement> | undefined;
|
||
if (newEvent) {
|
||
newEvent.target.value = values.value.toUpperCase();
|
||
onChange?.(newEvent);
|
||
}
|
||
};
|
||
|
||
if (inputVehicleNumber) {
|
||
return (
|
||
<NumberFormatBase
|
||
{...restProps}
|
||
type={type}
|
||
customInput={TextInput}
|
||
format={(value) => {
|
||
const clean = value.replace(/[^a-z0-9]/gi, '').toUpperCase();
|
||
|
||
const match = clean.match(/^([A-Z]{0,2})(\d{0,4})([A-Z]{0,3})$/);
|
||
if (!match) return clean;
|
||
const [, prefix, number, suffix] = match;
|
||
return [prefix, number, suffix].filter(Boolean).join(' ');
|
||
}}
|
||
removeFormatting={(val) => val.replace(/\s+/g, '')}
|
||
isValidInputCharacter={(char) => /^[a-z0-9]$/i.test(char)}
|
||
getCaretBoundary={(val) =>
|
||
Array(val.length + 1)
|
||
.fill(true)
|
||
.map(Boolean)
|
||
}
|
||
onValueChange={handleValueChange}
|
||
/>
|
||
);
|
||
}
|
||
|
||
return (
|
||
<PatternFormat
|
||
{...restProps}
|
||
type={type}
|
||
format={format}
|
||
mask={mask}
|
||
allowEmptyFormatting={allowEmptyFormatting}
|
||
patternChar={patternChar}
|
||
customInput={TextInput}
|
||
onValueChange={handleValueChange}
|
||
/>
|
||
);
|
||
};
|
||
|
||
export default PatternInput;
|