@opexa/portal-components 0.0.879 → 0.0.880

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17,7 +17,8 @@ export const MobileNumberField = ({ enabledCountries, mobileNumber, onMobileNumb
17
17
  const handleMobileChange = useCallback((e) => {
18
18
  onMobileNumberChange(e.target.value
19
19
  .replaceAll(' ', '')
20
- .replace(selectedCountry.areaCode, ''));
20
+ .replace(selectedCountry.areaCode, '')
21
+ .replace(/[^0-9]/g, ''));
21
22
  }, [onMobileNumberChange, selectedCountry]);
22
23
  if (enabledCountries.length === 0) {
23
24
  return (_jsxs(Field.Root, { invalid: !!error, children: [_jsx(Field.Label, { children: "Mobile Number" }), _jsxs("div", { className: "relative", children: [_jsxs("div", { className: "-translate-y-1/2 absolute top-1/2 left-3.5 flex shrink-0 items-center gap-md", children: [_jsx(localeInfo.country.flag, { className: "size-5" }), _jsx("span", { className: "text-text-placeholder", children: localeInfo.mobileNumber.areaCode })] }), _jsx(Field.Input, { ...(mobileNumberRegistration || {}), style: {
@@ -30,6 +30,7 @@ import { Field } from '../../ui/Field/index.js';
30
30
  import { PinInput } from '../../ui/PinInput/index.js';
31
31
  import { countryCodeParser } from '../../utils/countries/countryCodeParser.js';
32
32
  import { getCountryDetails } from '../../utils/countries/getAllCountries.js';
33
+ import { validateMobileNumber } from '../../utils/countries/validateMobileNumber.js';
33
34
  import { LOCALSTORAGE_PUSH_NOTIFICATION_TOKEN_KEY } from '../PortalProvider/PushNotifications.js';
34
35
  import { FacebookSignInTrigger } from './FacebookSignInTrigger.js';
35
36
  import { MobileNumberField } from './MobileNumberField.js';
@@ -43,10 +44,10 @@ const Step1Definition = (countryCode) => z.object({
43
44
  .string()
44
45
  .min(1, 'Mobile number is required')
45
46
  .superRefine((v, ctx) => {
46
- if (!countryCodeParser(v, countryCode)) {
47
+ if (!validateMobileNumber(countryCode, v)) {
47
48
  ctx.addIssue({
48
49
  code: z.ZodIssueCode.custom,
49
- message: 'Invalid mobile number',
50
+ message: 'Invalid mobile number format.',
50
51
  });
51
52
  }
52
53
  }),
@@ -33,6 +33,7 @@ import { Select } from '../../../ui/Select/index.js';
33
33
  import { Tooltip } from '../../../ui/Tooltip/index.js';
34
34
  import { countryCodeParser } from '../../../utils/countries/countryCodeParser.js';
35
35
  import { getCountryDetails } from '../../../utils/countries/getAllCountries.js';
36
+ import { validateMobileNumber } from '../../../utils/countries/validateMobileNumber.js';
36
37
  import { createPoll } from '../../../utils/createPoll.js';
37
38
  import DateOfBirthField from '../../DateOfBirthField.js';
38
39
  import { MobileNumberField } from '../../SignIn/MobileNumberField.js';
@@ -99,7 +100,17 @@ export function SignUpDefaultFormInternational() {
99
100
  }
100
101
  });
101
102
  const Step1Definition = z.object({
102
- mobileNumber: z.string().min(1, 'Mobile number is required'),
103
+ mobileNumber: z
104
+ .string()
105
+ .min(1, 'Mobile number is required')
106
+ .superRefine((v, ctx) => {
107
+ if (!validateMobileNumber(areaCode, v)) {
108
+ ctx.addIssue({
109
+ code: z.ZodIssueCode.custom,
110
+ message: 'Invalid mobile number format.',
111
+ });
112
+ }
113
+ }),
103
114
  termsAccepted: z.boolean().superRefine((v, ctx) => {
104
115
  if (!v) {
105
116
  ctx.addIssue({
@@ -0,0 +1 @@
1
+ export declare function validateMobileNumber(countryCode: string, mobileNumber: string): boolean;
@@ -0,0 +1,159 @@
1
+ export function validateMobileNumber(countryCode, mobileNumber) {
2
+ const cleaned = mobileNumber.replace(/[\s\-()]/g, '');
3
+ if (!/^\+?\d+$/.test(cleaned)) {
4
+ return false;
5
+ }
6
+ // Remove the country code if it's already in the number
7
+ let numberWithoutCode = cleaned;
8
+ if (cleaned.startsWith(countryCode)) {
9
+ numberWithoutCode = cleaned.substring(countryCode.length);
10
+ }
11
+ else if (cleaned.startsWith(countryCode.substring(1))) {
12
+ numberWithoutCode = cleaned.substring(countryCode.length - 1);
13
+ }
14
+ else if (cleaned.startsWith('+')) {
15
+ // Number has a different country code
16
+ return false;
17
+ }
18
+ // Country-specific validation rules
19
+ switch (countryCode) {
20
+ case '+63': // Philippines
21
+ return /^9\d{9}$/.test(numberWithoutCode);
22
+ case '+34': // Spain
23
+ return /^[67]\d{8}$/.test(numberWithoutCode);
24
+ case '+1': // US/Canada
25
+ return /^\d{10}$/.test(numberWithoutCode);
26
+ case '+1671': // Guam
27
+ case '+1670': // Northern Mariana Islands
28
+ case '+1868': // Trinidad and Tobago
29
+ return /^\d{7}$/.test(numberWithoutCode);
30
+ case '+44': // UK
31
+ return /^7\d{9}$/.test(numberWithoutCode);
32
+ case '+61': // Australia
33
+ return /^4\d{8}$/.test(numberWithoutCode);
34
+ case '+91': // India
35
+ return /^[6-9]\d{9}$/.test(numberWithoutCode);
36
+ case '+86': // China
37
+ return /^1\d{10}$/.test(numberWithoutCode);
38
+ case '+81': // Japan
39
+ return /^[789]0\d{8}$/.test(numberWithoutCode);
40
+ case '+82': // South Korea
41
+ return /^10\d{7,8}$/.test(numberWithoutCode);
42
+ case '+65': // Singapore
43
+ return /^[89]\d{7}$/.test(numberWithoutCode);
44
+ case '+60': // Malaysia
45
+ return /^1\d{8,9}$/.test(numberWithoutCode);
46
+ case '+62': // Indonesia
47
+ return /^8\d{8,11}$/.test(numberWithoutCode);
48
+ case '+66': // Thailand
49
+ return /^[689]\d{8}$/.test(numberWithoutCode);
50
+ case '+84': // Vietnam
51
+ return /^[3579]\d{8}$/.test(numberWithoutCode);
52
+ case '+852': // Hong Kong
53
+ return /^[4-79]\d{7}$/.test(numberWithoutCode);
54
+ case '+853': // Macau
55
+ return /^6\d{7}$/.test(numberWithoutCode);
56
+ case '+886': // Taiwan
57
+ return /^9\d{8}$/.test(numberWithoutCode);
58
+ case '+971': // UAE
59
+ return /^5\d{8}$/.test(numberWithoutCode);
60
+ case '+966': // Saudi Arabia
61
+ return /^5\d{8}$/.test(numberWithoutCode);
62
+ case '+974': // Qatar
63
+ return /^[3567]\d{7}$/.test(numberWithoutCode);
64
+ case '+973': // Bahrain
65
+ return /^3\d{7}$/.test(numberWithoutCode);
66
+ case '+968': // Oman
67
+ return /^9\d{7}$/.test(numberWithoutCode);
68
+ case '+965': // Kuwait
69
+ return /^[569]\d{7}$/.test(numberWithoutCode);
70
+ case '+962': // Jordan
71
+ return /^7\d{8}$/.test(numberWithoutCode);
72
+ case '+961': // Lebanon
73
+ return /^[378]\d{6,7}$/.test(numberWithoutCode);
74
+ case '+972': // Israel
75
+ return /^5\d{8}$/.test(numberWithoutCode);
76
+ case '+20': // Egypt
77
+ return /^1\d{9}$/.test(numberWithoutCode);
78
+ case '+27': // South Africa
79
+ return /^[678]\d{8}$/.test(numberWithoutCode);
80
+ case '+234': // Nigeria
81
+ return /^[789]0\d{8}$/.test(numberWithoutCode);
82
+ case '+55': // Brazil
83
+ return /^\d{2}9\d{8}$/.test(numberWithoutCode);
84
+ case '+52': // Mexico
85
+ return /^\d{10}$/.test(numberWithoutCode);
86
+ case '+54': // Argentina
87
+ return /^9\d{9}$/.test(numberWithoutCode);
88
+ case '+33': // France
89
+ return /^[67]\d{8}$/.test(numberWithoutCode);
90
+ case '+49': // Germany
91
+ return /^1\d{9,10}$/.test(numberWithoutCode);
92
+ case '+39': // Italy
93
+ return /^3\d{8,9}$/.test(numberWithoutCode);
94
+ case '+31': // Netherlands
95
+ return /^6\d{8}$/.test(numberWithoutCode);
96
+ case '+32': // Belgium
97
+ return /^4\d{8}$/.test(numberWithoutCode);
98
+ case '+41': // Switzerland
99
+ return /^7\d{8}$/.test(numberWithoutCode);
100
+ case '+43': // Austria
101
+ return /^6\d{9,12}$/.test(numberWithoutCode);
102
+ case '+45': // Denmark
103
+ return /^\d{8}$/.test(numberWithoutCode);
104
+ case '+46': // Sweden
105
+ return /^7\d{8}$/.test(numberWithoutCode);
106
+ case '+47': // Norway
107
+ return /^[49]\d{7}$/.test(numberWithoutCode);
108
+ case '+48': // Poland
109
+ return /^[45678]\d{8}$/.test(numberWithoutCode);
110
+ case '+351': // Portugal
111
+ return /^9\d{8}$/.test(numberWithoutCode);
112
+ case '+353': // Ireland
113
+ return /^8\d{8}$/.test(numberWithoutCode);
114
+ case '+30': // Greece
115
+ return /^6\d{9}$/.test(numberWithoutCode);
116
+ case '+90': // Turkey
117
+ return /^5\d{9}$/.test(numberWithoutCode);
118
+ case '+40': // Romania
119
+ return /^7\d{8}$/.test(numberWithoutCode);
120
+ case '+36': // Hungary
121
+ return /^[237]0\d{7}$/.test(numberWithoutCode);
122
+ case '+385': // Croatia
123
+ return /^9\d{7,8}$/.test(numberWithoutCode);
124
+ case '+421': // Slovakia
125
+ return /^9\d{8}$/.test(numberWithoutCode);
126
+ case '+358': // Finland
127
+ return /^[45]\d{8,9}$/.test(numberWithoutCode);
128
+ case '+370': // Lithuania
129
+ return /^6\d{7}$/.test(numberWithoutCode);
130
+ case '+371': // Latvia
131
+ return /^2\d{7}$/.test(numberWithoutCode);
132
+ case '+357': // Cyprus
133
+ return /^9\d{7}$/.test(numberWithoutCode);
134
+ case '+356': // Malta
135
+ return /^[79]\d{7}$/.test(numberWithoutCode);
136
+ case '+352': // Luxembourg
137
+ return /^6\d{8}$/.test(numberWithoutCode);
138
+ case '+64': // New Zealand
139
+ return /^2\d{7,9}$/.test(numberWithoutCode);
140
+ case '+673': // Brunei
141
+ return /^[789]\d{6}$/.test(numberWithoutCode);
142
+ case '+855': // Cambodia
143
+ return /^[16789]\d{7,8}$/.test(numberWithoutCode);
144
+ case '+998': // Uzbekistan
145
+ return /^9\d{8}$/.test(numberWithoutCode);
146
+ case '+964': // Iraq
147
+ return /^7\d{9}$/.test(numberWithoutCode);
148
+ case '+255': // Tanzania
149
+ return /^[67]\d{8}$/.test(numberWithoutCode);
150
+ case '+239': // São Tomé and Príncipe
151
+ return /^9[89]\d{5}$/.test(numberWithoutCode);
152
+ case '+213': // Algeria
153
+ return /^[567]\d{8}$/.test(numberWithoutCode);
154
+ case '+297': // Aruba
155
+ return /^[5679]\d{6}$/.test(numberWithoutCode);
156
+ default:
157
+ return /^\d{6,15}$/.test(numberWithoutCode);
158
+ }
159
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opexa/portal-components",
3
- "version": "0.0.879",
3
+ "version": "0.0.880",
4
4
  "exports": {
5
5
  "./ui/*": {
6
6
  "types": "./dist/ui/*/index.d.ts",