@clubmed/trident-ui 2.0.0-beta.24 → 2.0.0-beta.26

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clubmed/trident-ui",
3
- "version": "2.0.0-beta.24",
3
+ "version": "2.0.0-beta.26",
4
4
  "type": "module",
5
5
  "description": "Shared ClubMed React UI components",
6
6
  "keywords": [
@@ -139,7 +139,7 @@ var h = o, g = (e) => {
139
139
  }) : /* @__PURE__ */ m("div", {
140
140
  className: "flex gap-8",
141
141
  children: [/* @__PURE__ */ m("div", {
142
- className: e("relative rounded-pill z-0 w-[120px] flex-shrink-0", {
142
+ className: e("relative rounded-pill z-0 w-[130px] flex-shrink-0", {
143
143
  "bg-white": X !== "disabled",
144
144
  "bg-pearl border-middleGrey": X === "disabled"
145
145
  }),
@@ -153,13 +153,13 @@ var h = o, g = (e) => {
153
153
  "bg-pearl border-middleGrey": X === "disabled",
154
154
  "border-red": X === "error",
155
155
  "border-green": X === "success",
156
- "pe-[52px]": !0
156
+ "pe-[40px]": !0
157
157
  }),
158
158
  id: `${b}-prefix`,
159
159
  "aria-label": `${x}-prefix`,
160
160
  children: E.map((e) => /* @__PURE__ */ p("option", {
161
161
  value: e.code,
162
- children: e.code
162
+ children: e.label ?? e.code
163
163
  }, e.code))
164
164
  }), /* @__PURE__ */ p("div", {
165
165
  className: "pointer-events-none absolute inset-0 flex items-center justify-end px-20 py-12 -z-1",
@@ -1 +1 @@
1
- {"version":3,"file":"PhoneField.js","names":[],"sources":["../../../lib/ui/forms/PhoneField.tsx"],"sourcesContent":["import clsx from 'clsx';\nimport { useInternalStatus } from '../hooks/useInternalStatus';\nimport { FormControl, type FormControlProps } from './FormControl';\nimport { Icon, type IconicNames, type IconicTypes } from '@clubmed/trident-icons';\nimport {\n type ChangeEvent,\n type KeyboardEvent,\n useCallback,\n useEffect,\n useId,\n useRef,\n useState,\n} from 'react';\nimport {\n extractDigits,\n formatWithPattern,\n countDigitPlaceholders,\n DEFAULT_PHONE_PREFIXES,\n type PhonePrefix,\n} from '../helpers/phone';\n\nexport interface PhoneValue {\n full: string;\n prefix?: string;\n number?: string;\n raw: string;\n}\n\nexport interface PhoneFieldProps<Value = PhoneValue> extends FormControlProps<Value> {\n mode?: 'full' | 'split';\n pattern?: string;\n prefixes?: PhonePrefix[];\n defaultPrefix?: string;\n description?: string;\n icon?: IconicNames;\n iconType?: IconicTypes;\n errorMessage?: string;\n dataTestId?: string;\n placeholder?: string;\n}\n\n// Extract default to constant to prevent breaking memoization (rerender-memo-with-default-value)\nconst DEFAULT_PREFIXES = DEFAULT_PHONE_PREFIXES;\n\n// Extract literal prefix from pattern (everything before first #)\nconst getLiteralPrefixInfo = (pattern: string) => {\n const firstHashIndex = pattern.indexOf('#');\n const literalPrefix = firstHashIndex > 0 ? pattern.substring(0, firstHashIndex) : '';\n const literalPrefixDigits = extractDigits(literalPrefix);\n return { literalPrefix, literalPrefixDigits };\n};\n\n// Strip literal prefix digits from digit string\nconst stripLiteralPrefix = (allDigits: string, literalPrefixDigits: string) => {\n if (literalPrefixDigits.length > 0 && allDigits.startsWith(literalPrefixDigits)) {\n return allDigits.substring(literalPrefixDigits.length);\n }\n return allDigits;\n};\n\n// Calculate cursor position after formatting\nconst calculateCursorPosition = (\n digitsBeforeCursor: number,\n formatted: string,\n literalPrefixDigits: string,\n) => {\n let digitCount = 0;\n let skippedPrefixDigits = 0;\n\n for (let i = 0; i < formatted.length; i++) {\n if (/\\d/.test(formatted[i])) {\n if (skippedPrefixDigits < literalPrefixDigits.length) {\n skippedPrefixDigits++;\n continue;\n }\n\n digitCount++;\n if (digitCount === digitsBeforeCursor) {\n return i + 1;\n }\n }\n }\n\n return formatted.length;\n};\n\nexport const PhoneField = <Value = PhoneValue,>(props: PhoneFieldProps<Value>) => {\n const internalId = useId();\n\n const {\n id = internalId,\n name = id,\n label,\n value: externalValue,\n mode = 'full',\n pattern = '## ## ## ## ##',\n prefixes = DEFAULT_PREFIXES,\n defaultPrefix = prefixes[0]?.code || '+1',\n description,\n validationStatus = 'default',\n icon,\n iconType,\n errorMessage,\n disabled = false,\n required = false,\n hideRequiredStar,\n className,\n dataTestId = 'PhoneField',\n placeholder = '',\n onChange,\n ...rest\n } = props;\n\n const inputRef = useRef<HTMLInputElement>(null);\n const numberInputRef = useRef<HTMLInputElement>(null);\n const cursorPositionRef = useRef<number | null>(null);\n const [prefix, setPrefix] = useState(defaultPrefix);\n const [number, setNumber] = useState('');\n const [fullNumber, setFullNumber] = useState('');\n\n const internalStatus = useInternalStatus({\n isDisabled: disabled,\n validationStatus,\n });\n\n // Apply cursor position after state updates\n useEffect(() => {\n const ref = mode === 'full' ? inputRef : numberInputRef;\n if (cursorPositionRef.current !== null && ref.current) {\n ref.current.setSelectionRange(cursorPositionRef.current, cursorPositionRef.current);\n cursorPositionRef.current = null;\n }\n }, [fullNumber, number, mode]);\n\n // Initialize from external value\n useEffect(() => {\n if (externalValue && typeof externalValue === 'object' && 'full' in externalValue) {\n const phoneValue = externalValue as unknown as PhoneValue;\n if (mode === 'full') {\n setFullNumber(phoneValue.full || '');\n } else {\n setPrefix(phoneValue.prefix || defaultPrefix);\n setNumber(phoneValue.number || '');\n }\n }\n }, [externalValue, mode, defaultPrefix]);\n\n // Emit onChange with PhoneValue structure\n const emitChange = useCallback(\n (full: string, prefix?: string, number?: string) => {\n const raw = extractDigits(full);\n const phoneValue: PhoneValue = {\n full,\n prefix,\n number,\n raw,\n };\n onChange?.(name, phoneValue as Value);\n },\n [onChange, name],\n );\n\n // Unified handler for backspace/delete on non-digit characters\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLInputElement>, currentValue: string, isFullMode: boolean) => {\n if (e.key !== 'Backspace' && e.key !== 'Delete') {\n return;\n }\n\n const input = e.currentTarget;\n const cursorPosition = input.selectionStart || 0;\n const selectionEnd = input.selectionEnd || 0;\n\n // If there's a selection, let default behavior handle it\n if (cursorPosition !== selectionEnd) {\n return;\n }\n\n const { literalPrefixDigits } = getLiteralPrefixInfo(pattern);\n\n // Check if we're on a non-digit character\n const targetChar =\n e.key === 'Backspace' ? currentValue[cursorPosition - 1] : currentValue[cursorPosition];\n\n if (!targetChar || /\\d/.test(targetChar)) {\n return;\n }\n\n e.preventDefault();\n\n // Extract and clean digits\n const allDigits = stripLiteralPrefix(extractDigits(currentValue), literalPrefixDigits);\n const digitsBeforeCursorStr = stripLiteralPrefix(\n extractDigits(currentValue.substring(0, cursorPosition)),\n literalPrefixDigits,\n );\n const digitsBeforeCursor = digitsBeforeCursorStr.length;\n\n // Calculate new digits based on key\n let newDigits: string;\n let targetCursorDigits: number;\n\n if (e.key === 'Backspace') {\n if (digitsBeforeCursor === 0) return;\n newDigits =\n allDigits.slice(0, digitsBeforeCursor - 1) + allDigits.slice(digitsBeforeCursor);\n targetCursorDigits = digitsBeforeCursor - 1;\n } else {\n // Delete\n if (digitsBeforeCursor >= allDigits.length) return;\n newDigits =\n allDigits.slice(0, digitsBeforeCursor) + allDigits.slice(digitsBeforeCursor + 1);\n targetCursorDigits = digitsBeforeCursor;\n }\n\n // Format and update\n const formatted = formatWithPattern(newDigits, pattern);\n const newCursor = calculateCursorPosition(targetCursorDigits, formatted, literalPrefixDigits);\n cursorPositionRef.current = newCursor;\n\n if (isFullMode) {\n setFullNumber(formatted);\n emitChange(formatted);\n } else {\n setNumber(formatted);\n setPrefix((currentPrefix) => {\n const combined = `${currentPrefix} ${formatted}`.trim();\n emitChange(combined, currentPrefix, formatted);\n return currentPrefix;\n });\n }\n },\n [pattern, emitChange],\n );\n\n // Unified handler for input changes\n const handleInputChange = useCallback(\n (e: ChangeEvent<HTMLInputElement>, isFullMode: boolean) => {\n const inputValue = e.target.value;\n const cursorPosition = e.target.selectionStart || 0;\n\n const { literalPrefixDigits } = getLiteralPrefixInfo(pattern);\n\n // Extract and clean digits\n const allDigits = stripLiteralPrefix(extractDigits(inputValue), literalPrefixDigits);\n\n // Check against pattern limit\n const maxDigits = countDigitPlaceholders(pattern);\n if (allDigits.length > maxDigits) {\n return;\n }\n\n // Count digits before cursor\n const digitsBeforeCursorInInput = stripLiteralPrefix(\n extractDigits(inputValue.substring(0, cursorPosition)),\n literalPrefixDigits,\n );\n const digitsBeforeCursor = digitsBeforeCursorInInput.length;\n\n // Format the value\n const formatted = formatWithPattern(allDigits, pattern);\n\n // Calculate cursor position\n const newCursor = calculateCursorPosition(digitsBeforeCursor, formatted, literalPrefixDigits);\n cursorPositionRef.current = newCursor;\n\n // Update state\n if (isFullMode) {\n setFullNumber(formatted);\n emitChange(formatted);\n } else {\n setNumber(formatted);\n setPrefix((currentPrefix) => {\n const combined = `${currentPrefix} ${formatted}`.trim();\n emitChange(combined, currentPrefix, formatted);\n return currentPrefix;\n });\n }\n },\n [pattern, emitChange],\n );\n\n // Split mode: handle prefix change\n const handlePrefixChange = useCallback(\n (newPrefix: string) => {\n setPrefix(newPrefix);\n setNumber((currentNumber) => {\n const combined = `${newPrefix} ${currentNumber}`.trim();\n emitChange(combined, newPrefix, currentNumber);\n return currentNumber;\n });\n },\n [emitChange],\n );\n\n const formControlProps = {\n id,\n label,\n className,\n description,\n dataName: 'PhoneField',\n dataTestId,\n disabled,\n required,\n hideRequiredStar,\n validationStatus,\n errorMessage,\n };\n\n return (\n <FormControl {...formControlProps}>\n {mode === 'full' ? (\n // Full mode: single input with pattern masking\n <div className=\"relative\">\n <input\n {...(rest as any)}\n ref={inputRef}\n id={id}\n name={name}\n type=\"tel\"\n disabled={disabled}\n required={required}\n value={fullNumber}\n onChange={(e) => handleInputChange(e, true)}\n onKeyDown={(e) => handleKeyDown(e, fullNumber, true)}\n placeholder={placeholder}\n className={clsx(\n 'text-b3 rounded-pill w-full border overflow-hidden px-20 py-12 font-normal outline-none',\n {\n 'border-middleGrey focus:border-black active:border-black':\n internalStatus === 'default',\n 'ps-[52px]': icon,\n 'pe-[52px]': internalStatus === 'error' || internalStatus === 'success',\n 'bg-white text-black': internalStatus !== 'disabled',\n 'bg-pearl border-middleGrey': internalStatus === 'disabled',\n 'border-red': internalStatus === 'error',\n 'border-green': internalStatus === 'success',\n },\n )}\n aria-label={name}\n />\n\n <div\n className={clsx(\n 'pointer-events-none absolute inset-0 flex items-center justify-between px-20 py-12',\n {\n 'text-grey': internalStatus === 'disabled',\n 'text-red': internalStatus === 'error',\n 'text-green': internalStatus === 'success',\n },\n )}\n >\n {icon && <Icon name={icon} width=\"24px\" />}\n\n <span className=\"ms-auto flex gap-x-8\">\n {internalStatus === 'error' && (\n <Icon name=\"CrossDefault\" width=\"24px\" type={iconType} />\n )}\n\n {internalStatus === 'success' && (\n <Icon name=\"CheckDefault\" width=\"24px\" type={iconType} />\n )}\n </span>\n </div>\n </div>\n ) : (\n // Split mode: prefix dropdown + number input\n <div className=\"flex gap-8\">\n <div\n className={clsx('relative rounded-pill z-0 w-[120px] flex-shrink-0', {\n 'bg-white': internalStatus !== 'disabled',\n 'bg-pearl border-middleGrey': internalStatus === 'disabled',\n })}\n >\n <select\n disabled={disabled}\n value={prefix}\n onChange={(e) => handlePrefixChange(e.target.value)}\n className={clsx(\n 'text-b3 rounded-pill w-full border overflow-hidden px-20 py-12 font-semibold outline-none appearance-none bg-transparent',\n {\n 'border-middleGrey focus:border-black active:border-black':\n internalStatus === 'default',\n 'text-black': internalStatus !== 'disabled',\n 'bg-pearl border-middleGrey': internalStatus === 'disabled',\n 'border-red': internalStatus === 'error',\n 'border-green': internalStatus === 'success',\n 'pe-[52px]': true, // Space for dropdown arrow\n },\n )}\n id={`${id}-prefix`}\n aria-label={`${name}-prefix`}\n >\n {prefixes.map((p) => (\n <option key={p.code} value={p.code}>\n {p.code}\n </option>\n ))}\n </select>\n\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-end px-20 py-12 -z-1\">\n <Icon name=\"ArrowDefaultDown\" type=\"svg\" width=\"24px\" color=\"black\" />\n </div>\n </div>\n\n <div className=\"relative flex-1\">\n <input\n ref={numberInputRef}\n type=\"tel\"\n disabled={disabled}\n required={required}\n value={number}\n onChange={(e) => handleInputChange(e, false)}\n onKeyDown={(e) => handleKeyDown(e, number, false)}\n placeholder={placeholder}\n className={clsx(\n 'text-b3 rounded-pill w-full border overflow-hidden px-20 py-12 font-normal outline-none',\n {\n 'border-middleGrey focus:border-black active:border-black':\n internalStatus === 'default',\n 'pe-[52px]': internalStatus === 'error' || internalStatus === 'success',\n 'bg-white text-black': internalStatus !== 'disabled',\n 'bg-pearl border-middleGrey': internalStatus === 'disabled',\n 'border-red': internalStatus === 'error',\n 'border-green': internalStatus === 'success',\n },\n )}\n aria-label={`${name}-number`}\n />\n\n <div\n className={clsx(\n 'pointer-events-none absolute inset-0 flex items-center justify-end px-20 py-12',\n {\n 'text-grey': internalStatus === 'disabled',\n 'text-red': internalStatus === 'error',\n 'text-green': internalStatus === 'success',\n },\n )}\n >\n <span className=\"flex gap-x-8\">\n {internalStatus === 'error' && (\n <Icon name=\"CrossDefault\" width=\"24px\" type={iconType} />\n )}\n\n {internalStatus === 'success' && (\n <Icon name=\"CheckDefault\" width=\"24px\" type={iconType} />\n )}\n </span>\n </div>\n </div>\n </div>\n )}\n </FormControl>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"PhoneField.js","names":[],"sources":["../../../lib/ui/forms/PhoneField.tsx"],"sourcesContent":["import clsx from 'clsx';\nimport { useInternalStatus } from '../hooks/useInternalStatus';\nimport { FormControl, type FormControlProps } from './FormControl';\nimport { Icon, type IconicNames, type IconicTypes } from '@clubmed/trident-icons';\nimport {\n type ChangeEvent,\n type KeyboardEvent,\n useCallback,\n useEffect,\n useId,\n useRef,\n useState,\n} from 'react';\nimport {\n extractDigits,\n formatWithPattern,\n countDigitPlaceholders,\n DEFAULT_PHONE_PREFIXES,\n type PhonePrefix,\n} from '../helpers/phone';\n\nexport interface PhoneValue {\n full: string;\n prefix?: string;\n number?: string;\n raw: string;\n}\n\nexport interface PhoneFieldProps<Value = PhoneValue> extends FormControlProps<Value> {\n mode?: 'full' | 'split';\n pattern?: string;\n prefixes?: PhonePrefix[];\n defaultPrefix?: string;\n description?: string;\n icon?: IconicNames;\n iconType?: IconicTypes;\n errorMessage?: string;\n dataTestId?: string;\n placeholder?: string;\n}\n\n// Extract default to constant to prevent breaking memoization (rerender-memo-with-default-value)\nconst DEFAULT_PREFIXES = DEFAULT_PHONE_PREFIXES;\n\n// Extract literal prefix from pattern (everything before first #)\nconst getLiteralPrefixInfo = (pattern: string) => {\n const firstHashIndex = pattern.indexOf('#');\n const literalPrefix = firstHashIndex > 0 ? pattern.substring(0, firstHashIndex) : '';\n const literalPrefixDigits = extractDigits(literalPrefix);\n return { literalPrefix, literalPrefixDigits };\n};\n\n// Strip literal prefix digits from digit string\nconst stripLiteralPrefix = (allDigits: string, literalPrefixDigits: string) => {\n if (literalPrefixDigits.length > 0 && allDigits.startsWith(literalPrefixDigits)) {\n return allDigits.substring(literalPrefixDigits.length);\n }\n return allDigits;\n};\n\n// Calculate cursor position after formatting\nconst calculateCursorPosition = (\n digitsBeforeCursor: number,\n formatted: string,\n literalPrefixDigits: string,\n) => {\n let digitCount = 0;\n let skippedPrefixDigits = 0;\n\n for (let i = 0; i < formatted.length; i++) {\n if (/\\d/.test(formatted[i])) {\n if (skippedPrefixDigits < literalPrefixDigits.length) {\n skippedPrefixDigits++;\n continue;\n }\n\n digitCount++;\n if (digitCount === digitsBeforeCursor) {\n return i + 1;\n }\n }\n }\n\n return formatted.length;\n};\n\nexport const PhoneField = <Value = PhoneValue,>(props: PhoneFieldProps<Value>) => {\n const internalId = useId();\n\n const {\n id = internalId,\n name = id,\n label,\n value: externalValue,\n mode = 'full',\n pattern = '## ## ## ## ##',\n prefixes = DEFAULT_PREFIXES,\n defaultPrefix = prefixes[0]?.code || '+1',\n description,\n validationStatus = 'default',\n icon,\n iconType,\n errorMessage,\n disabled = false,\n required = false,\n hideRequiredStar,\n className,\n dataTestId = 'PhoneField',\n placeholder = '',\n onChange,\n ...rest\n } = props;\n\n const inputRef = useRef<HTMLInputElement>(null);\n const numberInputRef = useRef<HTMLInputElement>(null);\n const cursorPositionRef = useRef<number | null>(null);\n const [prefix, setPrefix] = useState(defaultPrefix);\n const [number, setNumber] = useState('');\n const [fullNumber, setFullNumber] = useState('');\n\n const internalStatus = useInternalStatus({\n isDisabled: disabled,\n validationStatus,\n });\n\n // Apply cursor position after state updates\n useEffect(() => {\n const ref = mode === 'full' ? inputRef : numberInputRef;\n if (cursorPositionRef.current !== null && ref.current) {\n ref.current.setSelectionRange(cursorPositionRef.current, cursorPositionRef.current);\n cursorPositionRef.current = null;\n }\n }, [fullNumber, number, mode]);\n\n // Initialize from external value\n useEffect(() => {\n if (externalValue && typeof externalValue === 'object' && 'full' in externalValue) {\n const phoneValue = externalValue as unknown as PhoneValue;\n if (mode === 'full') {\n setFullNumber(phoneValue.full || '');\n } else {\n setPrefix(phoneValue.prefix || defaultPrefix);\n setNumber(phoneValue.number || '');\n }\n }\n }, [externalValue, mode, defaultPrefix]);\n\n // Emit onChange with PhoneValue structure\n const emitChange = useCallback(\n (full: string, prefix?: string, number?: string) => {\n const raw = extractDigits(full);\n const phoneValue: PhoneValue = {\n full,\n prefix,\n number,\n raw,\n };\n onChange?.(name, phoneValue as Value);\n },\n [onChange, name],\n );\n\n // Unified handler for backspace/delete on non-digit characters\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLInputElement>, currentValue: string, isFullMode: boolean) => {\n if (e.key !== 'Backspace' && e.key !== 'Delete') {\n return;\n }\n\n const input = e.currentTarget;\n const cursorPosition = input.selectionStart || 0;\n const selectionEnd = input.selectionEnd || 0;\n\n // If there's a selection, let default behavior handle it\n if (cursorPosition !== selectionEnd) {\n return;\n }\n\n const { literalPrefixDigits } = getLiteralPrefixInfo(pattern);\n\n // Check if we're on a non-digit character\n const targetChar =\n e.key === 'Backspace' ? currentValue[cursorPosition - 1] : currentValue[cursorPosition];\n\n if (!targetChar || /\\d/.test(targetChar)) {\n return;\n }\n\n e.preventDefault();\n\n // Extract and clean digits\n const allDigits = stripLiteralPrefix(extractDigits(currentValue), literalPrefixDigits);\n const digitsBeforeCursorStr = stripLiteralPrefix(\n extractDigits(currentValue.substring(0, cursorPosition)),\n literalPrefixDigits,\n );\n const digitsBeforeCursor = digitsBeforeCursorStr.length;\n\n // Calculate new digits based on key\n let newDigits: string;\n let targetCursorDigits: number;\n\n if (e.key === 'Backspace') {\n if (digitsBeforeCursor === 0) return;\n newDigits =\n allDigits.slice(0, digitsBeforeCursor - 1) + allDigits.slice(digitsBeforeCursor);\n targetCursorDigits = digitsBeforeCursor - 1;\n } else {\n // Delete\n if (digitsBeforeCursor >= allDigits.length) return;\n newDigits =\n allDigits.slice(0, digitsBeforeCursor) + allDigits.slice(digitsBeforeCursor + 1);\n targetCursorDigits = digitsBeforeCursor;\n }\n\n // Format and update\n const formatted = formatWithPattern(newDigits, pattern);\n const newCursor = calculateCursorPosition(targetCursorDigits, formatted, literalPrefixDigits);\n cursorPositionRef.current = newCursor;\n\n if (isFullMode) {\n setFullNumber(formatted);\n emitChange(formatted);\n } else {\n setNumber(formatted);\n setPrefix((currentPrefix) => {\n const combined = `${currentPrefix} ${formatted}`.trim();\n emitChange(combined, currentPrefix, formatted);\n return currentPrefix;\n });\n }\n },\n [pattern, emitChange],\n );\n\n // Unified handler for input changes\n const handleInputChange = useCallback(\n (e: ChangeEvent<HTMLInputElement>, isFullMode: boolean) => {\n const inputValue = e.target.value;\n const cursorPosition = e.target.selectionStart || 0;\n\n const { literalPrefixDigits } = getLiteralPrefixInfo(pattern);\n\n // Extract and clean digits\n const allDigits = stripLiteralPrefix(extractDigits(inputValue), literalPrefixDigits);\n\n // Check against pattern limit\n const maxDigits = countDigitPlaceholders(pattern);\n if (allDigits.length > maxDigits) {\n return;\n }\n\n // Count digits before cursor\n const digitsBeforeCursorInInput = stripLiteralPrefix(\n extractDigits(inputValue.substring(0, cursorPosition)),\n literalPrefixDigits,\n );\n const digitsBeforeCursor = digitsBeforeCursorInInput.length;\n\n // Format the value\n const formatted = formatWithPattern(allDigits, pattern);\n\n // Calculate cursor position\n const newCursor = calculateCursorPosition(digitsBeforeCursor, formatted, literalPrefixDigits);\n cursorPositionRef.current = newCursor;\n\n // Update state\n if (isFullMode) {\n setFullNumber(formatted);\n emitChange(formatted);\n } else {\n setNumber(formatted);\n setPrefix((currentPrefix) => {\n const combined = `${currentPrefix} ${formatted}`.trim();\n emitChange(combined, currentPrefix, formatted);\n return currentPrefix;\n });\n }\n },\n [pattern, emitChange],\n );\n\n // Split mode: handle prefix change\n const handlePrefixChange = useCallback(\n (newPrefix: string) => {\n setPrefix(newPrefix);\n setNumber((currentNumber) => {\n const combined = `${newPrefix} ${currentNumber}`.trim();\n emitChange(combined, newPrefix, currentNumber);\n return currentNumber;\n });\n },\n [emitChange],\n );\n\n const formControlProps = {\n id,\n label,\n className,\n description,\n dataName: 'PhoneField',\n dataTestId,\n disabled,\n required,\n hideRequiredStar,\n validationStatus,\n errorMessage,\n };\n\n return (\n <FormControl {...formControlProps}>\n {mode === 'full' ? (\n // Full mode: single input with pattern masking\n <div className=\"relative\">\n <input\n {...(rest as any)}\n ref={inputRef}\n id={id}\n name={name}\n type=\"tel\"\n disabled={disabled}\n required={required}\n value={fullNumber}\n onChange={(e) => handleInputChange(e, true)}\n onKeyDown={(e) => handleKeyDown(e, fullNumber, true)}\n placeholder={placeholder}\n className={clsx(\n 'text-b3 rounded-pill w-full border overflow-hidden px-20 py-12 font-normal outline-none',\n {\n 'border-middleGrey focus:border-black active:border-black':\n internalStatus === 'default',\n 'ps-[52px]': icon,\n 'pe-[52px]': internalStatus === 'error' || internalStatus === 'success',\n 'bg-white text-black': internalStatus !== 'disabled',\n 'bg-pearl border-middleGrey': internalStatus === 'disabled',\n 'border-red': internalStatus === 'error',\n 'border-green': internalStatus === 'success',\n },\n )}\n aria-label={name}\n />\n\n <div\n className={clsx(\n 'pointer-events-none absolute inset-0 flex items-center justify-between px-20 py-12',\n {\n 'text-grey': internalStatus === 'disabled',\n 'text-red': internalStatus === 'error',\n 'text-green': internalStatus === 'success',\n },\n )}\n >\n {icon && <Icon name={icon} width=\"24px\" />}\n\n <span className=\"ms-auto flex gap-x-8\">\n {internalStatus === 'error' && (\n <Icon name=\"CrossDefault\" width=\"24px\" type={iconType} />\n )}\n\n {internalStatus === 'success' && (\n <Icon name=\"CheckDefault\" width=\"24px\" type={iconType} />\n )}\n </span>\n </div>\n </div>\n ) : (\n // Split mode: prefix dropdown + number input\n <div className=\"flex gap-8\">\n <div\n className={clsx('relative rounded-pill z-0 w-[130px] flex-shrink-0', {\n 'bg-white': internalStatus !== 'disabled',\n 'bg-pearl border-middleGrey': internalStatus === 'disabled',\n })}\n >\n <select\n disabled={disabled}\n value={prefix}\n onChange={(e) => handlePrefixChange(e.target.value)}\n className={clsx(\n 'text-b3 rounded-pill w-full border overflow-hidden px-20 py-12 font-semibold outline-none appearance-none bg-transparent',\n {\n 'border-middleGrey focus:border-black active:border-black':\n internalStatus === 'default',\n 'text-black': internalStatus !== 'disabled',\n 'bg-pearl border-middleGrey': internalStatus === 'disabled',\n 'border-red': internalStatus === 'error',\n 'border-green': internalStatus === 'success',\n 'pe-[40px]': true, // Space for dropdown arrow\n },\n )}\n id={`${id}-prefix`}\n aria-label={`${name}-prefix`}\n >\n {prefixes.map((p) => (\n <option key={p.code} value={p.code}>\n {p.label ?? p.code}\n </option>\n ))}\n </select>\n\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-end px-20 py-12 -z-1\">\n <Icon name=\"ArrowDefaultDown\" type=\"svg\" width=\"24px\" color=\"black\" />\n </div>\n </div>\n\n <div className=\"relative flex-1\">\n <input\n ref={numberInputRef}\n type=\"tel\"\n disabled={disabled}\n required={required}\n value={number}\n onChange={(e) => handleInputChange(e, false)}\n onKeyDown={(e) => handleKeyDown(e, number, false)}\n placeholder={placeholder}\n className={clsx(\n 'text-b3 rounded-pill w-full border overflow-hidden px-20 py-12 font-normal outline-none',\n {\n 'border-middleGrey focus:border-black active:border-black':\n internalStatus === 'default',\n 'pe-[52px]': internalStatus === 'error' || internalStatus === 'success',\n 'bg-white text-black': internalStatus !== 'disabled',\n 'bg-pearl border-middleGrey': internalStatus === 'disabled',\n 'border-red': internalStatus === 'error',\n 'border-green': internalStatus === 'success',\n },\n )}\n aria-label={`${name}-number`}\n />\n\n <div\n className={clsx(\n 'pointer-events-none absolute inset-0 flex items-center justify-end px-20 py-12',\n {\n 'text-grey': internalStatus === 'disabled',\n 'text-red': internalStatus === 'error',\n 'text-green': internalStatus === 'success',\n },\n )}\n >\n <span className=\"flex gap-x-8\">\n {internalStatus === 'error' && (\n <Icon name=\"CrossDefault\" width=\"24px\" type={iconType} />\n )}\n\n {internalStatus === 'success' && (\n <Icon name=\"CheckDefault\" width=\"24px\" type={iconType} />\n )}\n </span>\n </div>\n </div>\n </div>\n )}\n </FormControl>\n );\n};\n"],"mappings":"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"}
@@ -2,122 +2,122 @@
2
2
  var e = [
3
3
  {
4
4
  code: "+1",
5
- label: "US/Canada (+1)",
5
+ label: "USA +1",
6
6
  country: "US"
7
7
  },
8
8
  {
9
9
  code: "+44",
10
- label: "UK (+44)",
10
+ label: "UK +44",
11
11
  country: "GB"
12
12
  },
13
13
  {
14
14
  code: "+33",
15
- label: "France (+33)",
15
+ label: "Fra +33",
16
16
  country: "FR"
17
17
  },
18
18
  {
19
19
  code: "+49",
20
- label: "Germany (+49)",
20
+ label: "Ger +49",
21
21
  country: "DE"
22
22
  },
23
23
  {
24
24
  code: "+39",
25
- label: "Italy (+39)",
25
+ label: "Ita +39",
26
26
  country: "IT"
27
27
  },
28
28
  {
29
29
  code: "+34",
30
- label: "Spain (+34)",
30
+ label: "Spn +34",
31
31
  country: "ES"
32
32
  },
33
33
  {
34
34
  code: "+86",
35
- label: "China (+86)",
35
+ label: "Chn +86",
36
36
  country: "CN"
37
37
  },
38
38
  {
39
39
  code: "+91",
40
- label: "India (+91)",
40
+ label: "Ind +91",
41
41
  country: "IN"
42
42
  },
43
43
  {
44
44
  code: "+81",
45
- label: "Japan (+81)",
45
+ label: "JP +81",
46
46
  country: "JP"
47
47
  },
48
48
  {
49
49
  code: "+82",
50
- label: "South Korea (+82)",
50
+ label: "Kr +82",
51
51
  country: "KR"
52
52
  },
53
53
  {
54
54
  code: "+7",
55
- label: "Russia (+7)",
55
+ label: "Rus +7",
56
56
  country: "RU"
57
57
  },
58
58
  {
59
59
  code: "+61",
60
- label: "Australia (+61)",
60
+ label: "Aus +61",
61
61
  country: "AU"
62
62
  },
63
63
  {
64
64
  code: "+55",
65
- label: "Brazil (+55)",
65
+ label: "Bra +55",
66
66
  country: "BR"
67
67
  },
68
68
  {
69
69
  code: "+52",
70
- label: "Mexico (+52)",
70
+ label: "Mex +52",
71
71
  country: "MX"
72
72
  },
73
73
  {
74
74
  code: "+31",
75
- label: "Netherlands (+31)",
75
+ label: "NL +31",
76
76
  country: "NL"
77
77
  },
78
78
  {
79
79
  code: "+46",
80
- label: "Sweden (+46)",
80
+ label: "Swe +46",
81
81
  country: "SE"
82
82
  },
83
83
  {
84
84
  code: "+41",
85
- label: "Switzerland (+41)",
85
+ label: "Swi +41",
86
86
  country: "CH"
87
87
  },
88
88
  {
89
89
  code: "+32",
90
- label: "Belgium (+32)",
90
+ label: "Bel +32",
91
91
  country: "BE"
92
92
  },
93
93
  {
94
94
  code: "+48",
95
- label: "Poland (+48)",
95
+ label: "Pol +48",
96
96
  country: "PL"
97
97
  },
98
98
  {
99
99
  code: "+351",
100
- label: "Portugal (+351)",
100
+ label: "Por +351",
101
101
  country: "PT"
102
102
  },
103
103
  {
104
104
  code: "+30",
105
- label: "Greece (+30)",
105
+ label: "Gre +30",
106
106
  country: "GR"
107
107
  },
108
108
  {
109
109
  code: "+47",
110
- label: "Norway (+47)",
110
+ label: "Nor +47",
111
111
  country: "NO"
112
112
  },
113
113
  {
114
114
  code: "+45",
115
- label: "Denmark (+45)",
115
+ label: "Den +45",
116
116
  country: "DK"
117
117
  },
118
118
  {
119
119
  code: "+358",
120
- label: "Finland (+358)",
120
+ label: "Fin +358",
121
121
  country: "FI"
122
122
  }
123
123
  ];
@@ -1 +1 @@
1
- {"version":3,"file":"defaultPrefixes.js","names":[],"sources":["../../../../lib/ui/helpers/phone/defaultPrefixes.ts"],"sourcesContent":["/**\n * Default phone number prefixes for common countries\n */\n\nexport interface PhonePrefix {\n code: string;\n label?: string;\n country?: string;\n}\n\n/**\n * List of common country phone prefixes\n * Sorted by popularity/usage frequency\n */\nexport const DEFAULT_PHONE_PREFIXES: PhonePrefix[] = [\n { code: '+1', label: 'US/Canada (+1)', country: 'US' },\n { code: '+44', label: 'UK (+44)', country: 'GB' },\n { code: '+33', label: 'France (+33)', country: 'FR' },\n { code: '+49', label: 'Germany (+49)', country: 'DE' },\n { code: '+39', label: 'Italy (+39)', country: 'IT' },\n { code: '+34', label: 'Spain (+34)', country: 'ES' },\n { code: '+86', label: 'China (+86)', country: 'CN' },\n { code: '+91', label: 'India (+91)', country: 'IN' },\n { code: '+81', label: 'Japan (+81)', country: 'JP' },\n { code: '+82', label: 'South Korea (+82)', country: 'KR' },\n { code: '+7', label: 'Russia (+7)', country: 'RU' },\n { code: '+61', label: 'Australia (+61)', country: 'AU' },\n { code: '+55', label: 'Brazil (+55)', country: 'BR' },\n { code: '+52', label: 'Mexico (+52)', country: 'MX' },\n { code: '+31', label: 'Netherlands (+31)', country: 'NL' },\n { code: '+46', label: 'Sweden (+46)', country: 'SE' },\n { code: '+41', label: 'Switzerland (+41)', country: 'CH' },\n { code: '+32', label: 'Belgium (+32)', country: 'BE' },\n { code: '+48', label: 'Poland (+48)', country: 'PL' },\n { code: '+351', label: 'Portugal (+351)', country: 'PT' },\n { code: '+30', label: 'Greece (+30)', country: 'GR' },\n { code: '+47', label: 'Norway (+47)', country: 'NO' },\n { code: '+45', label: 'Denmark (+45)', country: 'DK' },\n { code: '+358', label: 'Finland (+358)', country: 'FI' },\n];\n"],"mappings":";AAcA,IAAa,IAAwC;CACnD;EAAE,MAAM;EAAM,OAAO;EAAkB,SAAS;EAAM;CACtD;EAAE,MAAM;EAAO,OAAO;EAAY,SAAS;EAAM;CACjD;EAAE,MAAM;EAAO,OAAO;EAAgB,SAAS;EAAM;CACrD;EAAE,MAAM;EAAO,OAAO;EAAiB,SAAS;EAAM;CACtD;EAAE,MAAM;EAAO,OAAO;EAAe,SAAS;EAAM;CACpD;EAAE,MAAM;EAAO,OAAO;EAAe,SAAS;EAAM;CACpD;EAAE,MAAM;EAAO,OAAO;EAAe,SAAS;EAAM;CACpD;EAAE,MAAM;EAAO,OAAO;EAAe,SAAS;EAAM;CACpD;EAAE,MAAM;EAAO,OAAO;EAAe,SAAS;EAAM;CACpD;EAAE,MAAM;EAAO,OAAO;EAAqB,SAAS;EAAM;CAC1D;EAAE,MAAM;EAAM,OAAO;EAAe,SAAS;EAAM;CACnD;EAAE,MAAM;EAAO,OAAO;EAAmB,SAAS;EAAM;CACxD;EAAE,MAAM;EAAO,OAAO;EAAgB,SAAS;EAAM;CACrD;EAAE,MAAM;EAAO,OAAO;EAAgB,SAAS;EAAM;CACrD;EAAE,MAAM;EAAO,OAAO;EAAqB,SAAS;EAAM;CAC1D;EAAE,MAAM;EAAO,OAAO;EAAgB,SAAS;EAAM;CACrD;EAAE,MAAM;EAAO,OAAO;EAAqB,SAAS;EAAM;CAC1D;EAAE,MAAM;EAAO,OAAO;EAAiB,SAAS;EAAM;CACtD;EAAE,MAAM;EAAO,OAAO;EAAgB,SAAS;EAAM;CACrD;EAAE,MAAM;EAAQ,OAAO;EAAmB,SAAS;EAAM;CACzD;EAAE,MAAM;EAAO,OAAO;EAAgB,SAAS;EAAM;CACrD;EAAE,MAAM;EAAO,OAAO;EAAgB,SAAS;EAAM;CACrD;EAAE,MAAM;EAAO,OAAO;EAAiB,SAAS;EAAM;CACtD;EAAE,MAAM;EAAQ,OAAO;EAAkB,SAAS;EAAM;CACzD"}
1
+ {"version":3,"file":"defaultPrefixes.js","names":[],"sources":["../../../../lib/ui/helpers/phone/defaultPrefixes.ts"],"sourcesContent":["/**\n * Default phone number prefixes for common countries\n */\n\nexport interface PhonePrefix {\n code: string;\n label?: string;\n country?: string;\n}\n\n/**\n * List of common country phone prefixes\n * Sorted by popularity/usage frequency\n */\nexport const DEFAULT_PHONE_PREFIXES: PhonePrefix[] = [\n { code: '+1', label: 'USA +1', country: 'US' },\n { code: '+44', label: 'UK +44', country: 'GB' },\n { code: '+33', label: 'Fra +33', country: 'FR' },\n { code: '+49', label: 'Ger +49', country: 'DE' },\n { code: '+39', label: 'Ita +39', country: 'IT' },\n { code: '+34', label: 'Spn +34', country: 'ES' },\n { code: '+86', label: 'Chn +86', country: 'CN' },\n { code: '+91', label: 'Ind +91', country: 'IN' },\n { code: '+81', label: 'JP +81', country: 'JP' },\n { code: '+82', label: 'Kr +82', country: 'KR' },\n { code: '+7', label: 'Rus +7', country: 'RU' },\n { code: '+61', label: 'Aus +61', country: 'AU' },\n { code: '+55', label: 'Bra +55', country: 'BR' },\n { code: '+52', label: 'Mex +52', country: 'MX' },\n { code: '+31', label: 'NL +31', country: 'NL' },\n { code: '+46', label: 'Swe +46', country: 'SE' },\n { code: '+41', label: 'Swi +41', country: 'CH' },\n { code: '+32', label: 'Bel +32', country: 'BE' },\n { code: '+48', label: 'Pol +48', country: 'PL' },\n { code: '+351', label: 'Por +351', country: 'PT' },\n { code: '+30', label: 'Gre +30', country: 'GR' },\n { code: '+47', label: 'Nor +47', country: 'NO' },\n { code: '+45', label: 'Den +45', country: 'DK' },\n { code: '+358', label: 'Fin +358', country: 'FI' },\n];\n"],"mappings":";AAcA,IAAa,IAAwC;CACnD;EAAE,MAAM;EAAM,OAAO;EAAU,SAAS;EAAM;CAC9C;EAAE,MAAM;EAAO,OAAO;EAAU,SAAS;EAAM;CAC/C;EAAE,MAAM;EAAO,OAAO;EAAW,SAAS;EAAM;CAChD;EAAE,MAAM;EAAO,OAAO;EAAW,SAAS;EAAM;CAChD;EAAE,MAAM;EAAO,OAAO;EAAW,SAAS;EAAM;CAChD;EAAE,MAAM;EAAO,OAAO;EAAW,SAAS;EAAM;CAChD;EAAE,MAAM;EAAO,OAAO;EAAW,SAAS;EAAM;CAChD;EAAE,MAAM;EAAO,OAAO;EAAW,SAAS;EAAM;CAChD;EAAE,MAAM;EAAO,OAAO;EAAU,SAAS;EAAM;CAC/C;EAAE,MAAM;EAAO,OAAO;EAAU,SAAS;EAAM;CAC/C;EAAE,MAAM;EAAM,OAAO;EAAU,SAAS;EAAM;CAC9C;EAAE,MAAM;EAAO,OAAO;EAAW,SAAS;EAAM;CAChD;EAAE,MAAM;EAAO,OAAO;EAAW,SAAS;EAAM;CAChD;EAAE,MAAM;EAAO,OAAO;EAAW,SAAS;EAAM;CAChD;EAAE,MAAM;EAAO,OAAO;EAAU,SAAS;EAAM;CAC/C;EAAE,MAAM;EAAO,OAAO;EAAW,SAAS;EAAM;CAChD;EAAE,MAAM;EAAO,OAAO;EAAW,SAAS;EAAM;CAChD;EAAE,MAAM;EAAO,OAAO;EAAW,SAAS;EAAM;CAChD;EAAE,MAAM;EAAO,OAAO;EAAW,SAAS;EAAM;CAChD;EAAE,MAAM;EAAQ,OAAO;EAAY,SAAS;EAAM;CAClD;EAAE,MAAM;EAAO,OAAO;EAAW,SAAS;EAAM;CAChD;EAAE,MAAM;EAAO,OAAO;EAAW,SAAS;EAAM;CAChD;EAAE,MAAM;EAAO,OAAO;EAAW,SAAS;EAAM;CAChD;EAAE,MAAM;EAAQ,OAAO;EAAY,SAAS;EAAM;CACnD"}