@open-mercato/ui 0.6.1-develop.3069.d40b4417a9 → 0.6.1-develop.3090.06ab462170

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.
@@ -11,12 +11,15 @@ export type PhoneDuplicateMatch = {
11
11
  }
12
12
 
13
13
  export type PhoneNumberFieldProps = {
14
+ id?: string
14
15
  value?: string | null
15
16
  onValueChange: (next: string | undefined) => void
16
17
  onDigitsChange?: (digits: string | null) => void
17
18
  externalError?: string | null
18
19
  disabled?: boolean
19
20
  autoFocus?: boolean
21
+ ariaLabel?: string
22
+ ariaDescribedBy?: string
20
23
  placeholder?: string
21
24
  minDigits?: number
22
25
  checkingLabel?: string
@@ -30,12 +33,15 @@ const DEFAULT_MIN_DIGITS = 6
30
33
  const DEFAULT_INVALID_LABEL = 'Enter a valid phone number with country code (e.g. +1 212 555 1234)'
31
34
 
32
35
  export function PhoneNumberField({
36
+ id,
33
37
  value,
34
38
  onValueChange,
35
39
  onDigitsChange,
36
40
  externalError,
37
41
  disabled = false,
38
42
  autoFocus,
43
+ ariaLabel,
44
+ ariaDescribedBy,
39
45
  placeholder,
40
46
  minDigits = DEFAULT_MIN_DIGITS,
41
47
  checkingLabel,
@@ -52,7 +58,10 @@ export function PhoneNumberField({
52
58
  const [checking, setChecking] = React.useState(false)
53
59
  const [validationHint, setValidationHint] = React.useState<string | null>(null)
54
60
  const userEditingRef = React.useRef(false)
55
- const visibleValidationHint = externalError ? null : validationHint
61
+ const externalFieldError = externalError && externalError.trim().length > 0 ? externalError : null
62
+ const errorMessage = externalFieldError ?? validationHint
63
+ const errorId = errorMessage && id ? `${id}-error` : undefined
64
+ const describedBy = [ariaDescribedBy, errorId].filter((part): part is string => Boolean(part)).join(' ') || undefined
56
65
 
57
66
  React.useEffect(() => {
58
67
  if (userEditingRef.current) return
@@ -145,10 +154,14 @@ export function PhoneNumberField({
145
154
  placeholder={placeholder}
146
155
  autoFocus={autoFocus}
147
156
  disabled={disabled}
157
+ id={id}
158
+ aria-label={ariaLabel}
159
+ aria-describedby={describedBy}
160
+ aria-invalid={errorMessage ? 'true' : undefined}
148
161
  data-crud-focus-target=""
149
162
  />
150
- {visibleValidationHint ? (
151
- <p className="text-xs text-destructive">{visibleValidationHint}</p>
163
+ {errorMessage ? (
164
+ <p id={errorId} className="text-xs text-destructive">{errorMessage}</p>
152
165
  ) : null}
153
166
  {!disabled && duplicate && duplicateLabel && duplicateLinkLabel ? (
154
167
  <p className="text-xs text-amber-600">
@@ -56,11 +56,11 @@ describe('PhoneNumberField', () => {
56
56
  expect(screen.queryByText('Use an international phone number.')).not.toBeInTheDocument()
57
57
  })
58
58
 
59
- it('hides the blur-time validation hint when an external field error is present', () => {
59
+ it('renders an external field error instead of the blur-time validation hint', () => {
60
60
  render(
61
61
  <PhoneFieldHarness
62
62
  invalidLabel="Use an international phone number."
63
- externalError="Use an international phone number."
63
+ externalError="Server says the phone is invalid."
64
64
  />,
65
65
  )
66
66
 
@@ -68,6 +68,8 @@ describe('PhoneNumberField', () => {
68
68
  fireEvent.change(input, { target: { value: '12345' } })
69
69
  fireEvent.blur(input)
70
70
 
71
+ expect(screen.getByText('Server says the phone is invalid.')).toBeInTheDocument()
71
72
  expect(screen.queryByText('Use an international phone number.')).not.toBeInTheDocument()
73
+ expect(input).toHaveAttribute('aria-invalid', 'true')
72
74
  })
73
75
  })