These expressions are quite sensitive to design since all our possible inputs would not be in the list. Maybe, a better choice would be to only allow numbers, or removing all non-numeric chars first, and then process/validate that.
However, if we just wish to check based on the inputs listed here, we might be able to find an expression, maybe something similar to this:
^[+]?(\d{3,4})[\s.-]?(\d{2,9})?([\s.-])?(\d{2,3})[\s.-]?(\d{2,3})$

RegEx
If this expression wasn't desired, it can be modified or changed in regex101.com.
RegEx Circuit
jex.im also helps to visualize the expressions.

JavaScript Demo
This snippet is just to show that how the capturing groups work:
const regex = /^[+]?(\d{3,4})[\s.-]?(\d{2,9})?([\s.-])?(\d{2,3})[\s.-]?(\d{2,3})$/mg;
const str = `+777 777 777 777
+777.777.777.777
+777 777777777
+777-777-777-777
+777777777777
7777 777 777
7777 777777
7777.777.777
7777-777-777
777-777-777
777.777.777
7777777777
7777 77 77 77
7777.77.77.77
7777-77-77-77`;
let m;
while ((m = regex.exec(str)) !== null) {
// This is necessary to avoid infinite loops with zero-width matches
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
// The result can be accessed through the `m`-variable.
m.forEach((match, groupIndex) => {
console.log(`Found match, group ${groupIndex}: ${match}`);
});
}