67 lines
1.6 KiB
TypeScript
67 lines
1.6 KiB
TypeScript
export const DECIMAL_INPUT_PATTERN = /^-?\d*([.,]\d*)?$/;
|
|
|
|
export const normalizeDecimalInput = (value: string): string => {
|
|
return value.replace(",", ".");
|
|
};
|
|
|
|
export const trimToScale = (value: string, scale: number): string => {
|
|
const normalized = normalizeDecimalInput(value);
|
|
|
|
if (!normalized.includes(".")) {
|
|
return normalized;
|
|
}
|
|
|
|
const [integerPart, decimalPart = ""] = normalized.split(".");
|
|
|
|
return `${integerPart}.${decimalPart.slice(0, scale)}`;
|
|
};
|
|
|
|
export const parseDecimalOrNull = (value: string): number | null => {
|
|
const normalized = normalizeDecimalInput(value).trim();
|
|
|
|
if (normalized === "") {
|
|
return null;
|
|
}
|
|
|
|
if (normalized === "-" || normalized === "." || normalized === "-.") {
|
|
return null;
|
|
}
|
|
|
|
const parsed = Number(normalized);
|
|
|
|
if (!Number.isFinite(parsed)) {
|
|
return null;
|
|
}
|
|
|
|
return parsed;
|
|
};
|
|
|
|
export const clampNumber = (value: number, min?: number, max?: number): number => {
|
|
if (typeof min === "number" && value < min) {
|
|
return min;
|
|
}
|
|
|
|
if (typeof max === "number" && value > max) {
|
|
return max;
|
|
}
|
|
|
|
return value;
|
|
};
|
|
|
|
export const formatDecimalValue = (value: number | null | undefined, scale: number): string => {
|
|
if (value === null || value === undefined || Number.isNaN(value)) {
|
|
return "";
|
|
}
|
|
|
|
const asString = String(value);
|
|
|
|
if (!asString.includes(".")) {
|
|
return asString;
|
|
}
|
|
|
|
const [integerPart, decimalPart = ""] = asString.split(".");
|
|
const trimmedDecimalPart = decimalPart.slice(0, scale).replace(/0+$/, "");
|
|
|
|
return trimmedDecimalPart.length > 0 ? `${integerPart}.${trimmedDecimalPart}` : `${integerPart}`;
|
|
};
|