Flexible Mask for IP addresses
First of all thank you and great work team,
I was wondering if you help me to create mask for IP address, and here what I have created
[/\d/, /\d/, /\d/, '.', /\d/, /\d/, /\d/, '.', /\d/, /\d/, /\d/, '.', /\d/, /\d/, /\d/]
it work fine for (192.168.111.083) format but I want to make it more flexible which accept following format
10.2.5.6 instead of 010.002.005.006
Would be very Interessted in a solution for this!!!
There is no an easy/built-in way to do this... but I'm sure it wouldn't be too difficult. You would need to create a mask function that validates the IP based on number of digits and placement of dots..
Is anyone able to share more details on this?
Just a guess since I'm only looking into using this module for something else and checking out any potential issues, but have you tried:
[/\d?/, /\d?/, /\d/, '.', /\d?/, /\d?/, /\d/, '.', /\d?/, /\d?/, /\d/, '.', /\d?/, /\d?/, /\d/]
I tested using /\d?\d?\d.\d?\d?\d.\d?\d?\d.\d?\d?\d/g in a regex tester and it seemed to capture what you're looking for.
Oops, thx @BioPhoton , the array is correct, but I forgot to escape the '.' in the regex, should be \d?\d?\d\.\d?\d?\d\.\d?\d?\d\.\d?\d?\d which finds any valid IP that's a substring, or \b\d?\d?\d\.\d?\d?\d\.\d?\d?\d\.\d?\d?\d\b if you want to bound it exactly.
Updated your link w/o bounding, w/ bounding
Here's an online regex tester with this regex: https://regex101.com/r/3YQ4wC/1
I am doing this:
const value = '1.2.3.4.5.6.7.8.9';
const results = conformToMask(value, [/\d?/, /\d?/, /\d/, '.', /\d?/, /\d?/, /\d/, '.', /\d?/, /\d?/, /\d/, '.', /\d?/, /\d?/, /\d/]);
console.log(results.conformedValue);
And I getting 1.2.3.4.5.6.7.8 as a result. Maybe someone knows what is wrong?
My solution -
const ipMask = value => {
const chars = value.split("");
const createIpGroup = (charsArr, position) => [
/[0-2]/,
charsArr[position] === "2" ? /[0-5]/ : /[0-9]/,
charsArr[position] === "2" ? /[0-5]/ : /[0-9]/
];
const ipGroup1 = createIpGroup(chars, 0);
const ipGroup2 = createIpGroup(chars, 4);
const ipGroup3 = createIpGroup(chars, 8);
const ipGroup4 = createIpGroup(chars, 12);
return ipGroup1
.concat(".")
.concat(ipGroup2)
.concat(".")
.concat(ipGroup3)
.concat(".")
.concat(ipGroup4);
};
<MaskedInput mask={ipMask} placeholder="000.000.000.000" />
@AAtamaniuk - Have you done anything with ip6?

@AAtamaniuk that's still not quite flexible, but to be fair, I don't really see a ux friendly way masking ipv4 or ipv6
Faced with the same problem, at least found a way through the pipe function:
const props = {
mask: value => Array(value.length).fill(/[\d.]/),
pipe: value => {
if (value === '.' || value.endsWith('..')) return false;
const parts = value.split('.');
if (
parts.length > 4 ||
parts.some(part => part === '00' || part < 0 || part > 255)
) {
return false;
}
return value;
},
};
https://codesandbox.io/s/1v32jk0x7q
few improvements to the previous post:
const props = {
guide: true,
mask: value => {
let result = [];
const chunks = value.split(".");
for (let i = 0; i < 4; ++i) {
const chunk = (chunks[i] || "").replace(/_/gi, "");
if (chunk === "") {
result.push(/\d/, /\d/, /\d/, ".");
continue;
} else if (+chunk === 0) {
result.push(/\d/, ".");
continue;
} else if (
chunks.length < 4 ||
(chunk.length < 3 && chunks[i].indexOf("_") !== -1)
) {
if (
(chunk.length < 2 && +`${chunk}00` > 255) ||
(chunk.length < 3 && +`${chunk}0` > 255)
) {
result.push(/\d/, /\d/, ".");
continue;
} else {
result.push(/\d/, /\d/, /\d/, ".");
continue;
}
} else {
result.push(...new Array(chunk.length).fill(/\d/), ".");
continue;
}
}
result = result.slice(0, -1);
return result;
},
pipe: value => {
if (value === "." || value.endsWith("..")) return false;
const parts = value.split(".");
if (
parts.length > 4 ||
parts.some(part => part === "00" || part < 0 || part > 255)
) {
return false;
}
return value;
}
};
now it works with placeholder
https://codesandbox.io/embed/react-text-mask-ip-kg27g
more some improvements. :)
If the result of the mask is not important to you.
const props = {
guide: false,
mask: (value, data) => {
const mask = Array(value.length).fill(/[\d.]/)
const chunks = value.split('.');
for (let i = 0; i < 4; ++i) {
const chunk = (chunks[i] || "");
if (255 % +chunk === 255) {
mask[value.length - 1] = '.';
mask[value.length] = /[\d.]/;
}
}
return mask;
},
pipe: value => {
if (value === "." || value.endsWith("..")) return false;
const parts = value.split(".");
if (
parts.length > 4 ||
parts.some(part => part === "00" || part < 0 || part > 255)
) {
return false;
}
return value;
}
};