Skip to content

Commit 6dad6bf

Browse files
committed
fix: correct auto-format and phone validation edge cases
Resolves review findings on the Text field format handling: - stripSeparator treated a whitespace separator as absent, so a space separator was rendered but never stripped, leaking the grouping characters into the stored value and payload. Only a genuinely empty separator now short-circuits. - parseGroupLengths relied on parseInt alone, silently accepting partial values such as "3foo" and "3.5" as 3. Tokens are now validated as whole positive integers before parsing. - The phone pattern matched digit-free input like "-------" or seven spaces. A lookahead now requires at least one digit, leaving the allowed characters, length range, and optional leading "+" unchanged. - The auto-format group row resolves enableFormatting through getSettingValue, so the setting works in JS mode as well as literal.
1 parent c698713 commit 6dad6bf

2 files changed

Lines changed: 8 additions & 5 deletions

File tree

shesha-reactjs/src/designer-components/textField/settingsForm.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export const getSettings: SettingsFormMarkupFactory = ({ fbf, removeStyleRouter
5151
{ type: 'textField', propertyName: 'formatGroups', label: 'Group lengths', size: 'small', jsSetting: true, tooltip: 'Comma-separated lengths of each group, e.g. 3,4' },
5252
{ type: 'textField', propertyName: 'formatSeparator', label: 'Separator', size: 'small', jsSetting: true, tooltip: 'Character(s) displayed between groups, e.g. -. Visual only, not included in the stored value.' },
5353
],
54-
visibleJs: 'return data?.enableFormatting === true;',
54+
visibleJs: 'return getSettingValue(data?.enableFormatting) === true;',
5555
}),
5656
undefined, 'return getSettingValue(data?.textType) === "text";')
5757
.stdCollapsiblePanel('Validations', (fb) => fb

shesha-reactjs/src/designer-components/textField/utils.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { IStyleValue } from "@/providers/form/models";
22
import { useSettingValue } from '@/providers/settings';
33
import { ISettingIdentifier } from '@/providers/settings/models';
4-
import { isNullOrWhiteSpace } from '@/utils/nullables';
4+
import { isDefined, isNullOrWhiteSpace } from '@/utils/nullables';
55
import { useMemo } from 'react';
66
import { TextType } from './interfaces';
77

@@ -28,7 +28,8 @@ export const TEXT_TYPE_FORMATS: Partial<Record<TextType, ITextTypeFormatConfig>>
2828
},
2929
phone: {
3030
// Lenient: leading "+", digits, spaces, dashes, dots and parentheses, 7-20 chars.
31-
pattern: /^\+?[0-9\s\-().]{7,20}$/,
31+
// The lookahead requires at least one digit, so separators alone (e.g. "-------") are rejected.
32+
pattern: /^\+?(?=.*[0-9])[0-9\s\-().]{7,20}$/,
3233
message: 'Please enter a valid phone number',
3334
inputType: 'tel',
3435
autoComplete: 'tel',
@@ -50,13 +51,15 @@ export const parseGroupLengths = (groups: string | undefined): number[] => {
5051
if (isNullOrWhiteSpace(groups)) return [];
5152
return groups
5253
.split(',')
53-
.map((part) => parseInt(part.trim(), 10))
54+
.map((part) => part.trim())
55+
.filter((part) => /^\d+$/.test(part))
56+
.map((part) => parseInt(part, 10))
5457
.filter((length) => Number.isFinite(length) && length > 0);
5558
};
5659

5760
/** Removes every occurrence of `separator` from `value`, leaving only the raw characters. */
5861
export const stripSeparator = (value: string, separator: string): string => {
59-
if (isNullOrWhiteSpace(value) || isNullOrWhiteSpace(separator)) return value;
62+
if (isNullOrWhiteSpace(value) || !isDefined(separator) || separator === '') return value;
6063
const escapedSeparator = separator.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
6164
return value.split(new RegExp(escapedSeparator, 'g')).join('');
6265
};

0 commit comments

Comments
 (0)