80 lines
1.8 KiB
TypeScript

import { TextInput } from "./TextInput";
export function IPInput(p: {
label: string;
editable: boolean;
value?: string;
onValueChange?: (newVal: string | undefined) => void;
version: 4 | 6;
}): React.ReactElement {
const { onValueChange, ...props } = p;
return (
<TextInput
onValueChange={(v) => {
onValueChange?.(p.version === 4 ? sanitizeIpV4(v) : sanitizeIpV6(v));
}}
{...props}
/>
);
}
function sanitizeIpV4(s: string | undefined): string | undefined {
if (s === "" || s === undefined) return s;
let split = s.split(".");
if (split.length > 4) split.splice(4);
let needAnotherIteration = false;
const res = split
.map((v) => {
if (v === "") return "";
const num = Number(v);
if (isNaN(num) || num < 0) return "0";
if (num > 255) {
needAnotherIteration = true;
return v.slice(0, 2) + "." + v.slice(2);
}
return num.toString();
})
.join(".");
return needAnotherIteration ? sanitizeIpV4(res) : res;
}
function sanitizeIpV6(s: string | undefined): string | undefined {
if (s === "" || s === undefined) return s;
const split = s.split(":");
if (split.length > 8) split.splice(8);
let needAnotherIteration = false;
let res = split
.map((e) => {
if (e === "") return e;
const num = parseInt(e, 16);
if (isNaN(num)) return "0";
let s = num.toString(16);
if (num > 0xffff) {
needAnotherIteration = true;
return s.slice(0, 4) + ":" + s.slice(4);
}
return s;
})
.join(":");
const firstIndex = res.indexOf("::");
let nextIndex = res.lastIndexOf("::");
while (nextIndex !== firstIndex) {
res = res.slice(0, nextIndex) + res.slice(nextIndex + 1);
nextIndex = res.lastIndexOf("::");
}
return needAnotherIteration ? sanitizeIpV6(res) : res;
}