@open-mercato/ui 0.9.0 → 0.9.1-develop.7462.1.94c09f158f
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/dist/backend/CrudForm.js +30 -13
- package/dist/backend/CrudForm.js.map +2 -2
- package/dist/backend/FlashMessages.js +25 -1
- package/dist/backend/FlashMessages.js.map +2 -2
- package/dist/backend/confirm-dialog/ConfirmDialog.js +11 -0
- package/dist/backend/confirm-dialog/ConfirmDialog.js.map +2 -2
- package/dist/backend/inputs/PhoneNumberField.js +17 -5
- package/dist/backend/inputs/PhoneNumberField.js.map +2 -2
- package/dist/backend/progress/useProgressSse.js +13 -8
- package/dist/backend/progress/useProgressSse.js.map +2 -2
- package/package.json +5 -4
- package/src/backend/CrudForm.tsx +44 -15
- package/src/backend/FlashMessages.tsx +34 -1
- package/src/backend/__tests__/CrudForm.embeddedExtraActions.test.tsx +114 -0
- package/src/backend/__tests__/CrudForm.fieldChangeRenders.test.tsx +127 -0
- package/src/backend/__tests__/FlashMessages.test.tsx +65 -0
- package/src/backend/__tests__/useProgressSse.test.tsx +122 -0
- package/src/backend/confirm-dialog/ConfirmDialog.tsx +16 -0
- package/src/backend/confirm-dialog/__tests__/ConfirmDialog.test.tsx +29 -0
- package/src/backend/inputs/PhoneNumberField.tsx +17 -11
- package/src/backend/inputs/__tests__/PhoneNumberField.renders.test.tsx +35 -0
- package/src/backend/progress/useProgressSse.ts +22 -8
|
@@ -24,8 +24,26 @@ function isSameOriginFlashNavigation() {
|
|
|
24
24
|
return false;
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
|
+
const PENDING_FLASH_MAX_AGE_MS = 5e3;
|
|
28
|
+
let listeningFlashHostCount = 0;
|
|
29
|
+
let pendingFlash = null;
|
|
30
|
+
function readPendingFlash() {
|
|
31
|
+
const pending = pendingFlash;
|
|
32
|
+
if (!pending) return null;
|
|
33
|
+
if (Date.now() - pending.queuedAt > PENDING_FLASH_MAX_AGE_MS) {
|
|
34
|
+
pendingFlash = null;
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
setTimeout(() => {
|
|
38
|
+
if (pendingFlash === pending) pendingFlash = null;
|
|
39
|
+
}, 0);
|
|
40
|
+
return pending;
|
|
41
|
+
}
|
|
27
42
|
function flash(message, type = "info") {
|
|
28
43
|
if (typeof window === "undefined") return;
|
|
44
|
+
if (listeningFlashHostCount === 0) {
|
|
45
|
+
pendingFlash = { message, type, queuedAt: Date.now() };
|
|
46
|
+
}
|
|
29
47
|
const evt = new CustomEvent("flash", { detail: { message, type } });
|
|
30
48
|
window.dispatchEvent(evt);
|
|
31
49
|
}
|
|
@@ -170,7 +188,13 @@ function FlashMessagesInner() {
|
|
|
170
188
|
showFlash(text, t);
|
|
171
189
|
};
|
|
172
190
|
window.addEventListener("flash", handler);
|
|
173
|
-
|
|
191
|
+
listeningFlashHostCount += 1;
|
|
192
|
+
const pending = readPendingFlash();
|
|
193
|
+
if (pending) showFlash(pending.message, pending.type);
|
|
194
|
+
return () => {
|
|
195
|
+
listeningFlashHostCount -= 1;
|
|
196
|
+
window.removeEventListener("flash", handler);
|
|
197
|
+
};
|
|
174
198
|
}, [showFlash]);
|
|
175
199
|
const handleDismiss = React.useCallback(() => {
|
|
176
200
|
clearDismissTimer();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/backend/FlashMessages.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { Alert, type AlertStatus } from '../primitives/alert'\n\nexport type FlashKind = 'success' | 'error' | 'warning' | 'info'\n\nconst flashKindToAlertStatus: Record<FlashKind, AlertStatus> = {\n success: 'success',\n error: 'error',\n warning: 'warning',\n info: 'information',\n}\n\nfunction normalizeFlashKind(value: string | null | undefined): FlashKind {\n if (value && Object.prototype.hasOwnProperty.call(flashKindToAlertStatus, value)) {\n return value as FlashKind\n }\n return 'success'\n}\n\n// A URL-supplied flash is only trustworthy when the navigation that carried it\n// originated from the same origin (an in-app POST->GET redirect or client-side\n// navigation). Cross-origin links \u2014 the phishing/content-spoofing vector \u2014 must\n// not be allowed to render attacker-controlled copy inside an authoritative banner.\nfunction isSameOriginFlashNavigation(): boolean {\n if (typeof window === 'undefined') return false\n const referrer = document.referrer\n // No referrer (direct load, bookmark, or referrer stripped) is ambiguous, not a\n // cross-origin redirect we can attribute to an attacker page; allow it.\n if (!referrer) return true\n try {\n return new URL(referrer).origin === window.location.origin\n } catch {\n return false\n }\n}\n\n// Programmatic API to show a flash message without navigation.\n// Consumers can import { flash } and call flash('text', 'error').\nexport function flash(message: string, type: FlashKind = 'info') {\n if (typeof window === 'undefined') return\n const evt = new CustomEvent('flash', { detail: { message, type } })\n window.dispatchEvent(evt)\n}\n\n// Two hosts mount `<FlashMessages />` over the same page: `FrontendLayout`\n// wraps the entire app (backend routes included, via `AppProviders`) and\n// `AppShell` mounts its own copy inside `<main>`. Both listen to the same\n// `flash` event, so every backend toast rendered twice \u2014 two stacked fixed\n// overlays, each with its own dismiss button, so dismissing one left the other\n// behind. Both mount points are public surfaces third-party apps rely on, so\n// instead of deleting one, only the first host to mount renders; the others\n// keep their state in sync and take over if it unmounts.\nconst mountedFlashHostIds: symbol[] = []\nconst flashHostListeners = new Set<() => void>()\n\nfunction notifyFlashHostListeners() {\n for (const listener of flashHostListeners) listener()\n}\n\nfunction subscribeFlashHosts(listener: () => void): () => void {\n flashHostListeners.add(listener)\n return () => {\n flashHostListeners.delete(listener)\n }\n}\n\nfunction getPrimaryFlashHostId(): symbol | null {\n return mountedFlashHostIds[0] ?? null\n}\n\nfunction getServerFlashHostId(): symbol | null {\n return null\n}\n\nfunction useIsPrimaryFlashHost(): boolean {\n const hostIdRef = React.useRef<symbol | null>(null)\n if (hostIdRef.current === null) hostIdRef.current = Symbol('om-flash-host')\n const hostId = hostIdRef.current\n\n React.useEffect(() => {\n mountedFlashHostIds.push(hostId)\n notifyFlashHostListeners()\n return () => {\n const index = mountedFlashHostIds.indexOf(hostId)\n if (index >= 0) mountedFlashHostIds.splice(index, 1)\n notifyFlashHostListeners()\n }\n }, [hostId])\n\n return React.useSyncExternalStore(subscribeFlashHosts, getPrimaryFlashHostId, getServerFlashHostId) === hostId\n}\n\ntype HistoryMethod = History['pushState']\n\nfunction useLocationKey() {\n const [locationKey, setLocationKey] = React.useState(() => {\n if (typeof window === 'undefined') return ''\n return window.location.href\n })\n const locationKeyRef = React.useRef(locationKey)\n\n React.useEffect(() => {\n locationKeyRef.current = locationKey\n }, [locationKey])\n\n React.useEffect(() => {\n if (typeof window === 'undefined') return\n\n let active = true\n const scheduleUpdate = (href: string) => {\n const run = () => {\n if (!active) return\n if (locationKeyRef.current === href) return\n locationKeyRef.current = href\n setLocationKey(href)\n }\n if (typeof queueMicrotask === 'function') {\n queueMicrotask(run)\n } else {\n setTimeout(run, 0)\n }\n }\n const updateLocation = () => {\n if (!active) return\n const href = window.location.href\n if (href === locationKeyRef.current) return\n scheduleUpdate(href)\n }\n\n const deferredUpdateLocation = () => {\n setTimeout(updateLocation, 0)\n }\n\n const originalPush: HistoryMethod = window.history.pushState.bind(window.history)\n const originalReplace: HistoryMethod = window.history.replaceState.bind(window.history)\n\n const pushState: HistoryMethod = (...args) => {\n originalPush(...args)\n deferredUpdateLocation()\n }\n\n const replaceState: HistoryMethod = (...args) => {\n originalReplace(...args)\n deferredUpdateLocation()\n }\n\n window.history.pushState = pushState\n window.history.replaceState = replaceState\n window.addEventListener('popstate', updateLocation)\n window.addEventListener('hashchange', updateLocation)\n updateLocation()\n\n return () => {\n active = false\n window.history.pushState = originalPush\n window.history.replaceState = originalReplace\n window.removeEventListener('popstate', updateLocation)\n window.removeEventListener('hashchange', updateLocation)\n }\n }, [])\n\n return locationKey\n}\n\nfunction FlashMessagesInner() {\n const [msg, setMsg] = React.useState<string | null>(null)\n const [kind, setKind] = React.useState<FlashKind>('info')\n const isPrimaryHost = useIsPrimaryFlashHost()\n const locationKey = useLocationKey()\n const dismissTimerRef = React.useRef<ReturnType<typeof setTimeout> | null>(null)\n\n const clearDismissTimer = React.useCallback(() => {\n if (dismissTimerRef.current) {\n clearTimeout(dismissTimerRef.current)\n dismissTimerRef.current = null\n }\n }, [])\n\n const showFlash = React.useCallback((message: string, type: FlashKind) => {\n clearDismissTimer()\n setMsg(message)\n setKind(type)\n dismissTimerRef.current = setTimeout(() => {\n dismissTimerRef.current = null\n setMsg(null)\n }, 3000)\n }, [clearDismissTimer])\n\n React.useEffect(() => {\n return () => {\n clearDismissTimer()\n }\n }, [clearDismissTimer])\n\n // Read flash from URL on any navigation change (client-side too)\n React.useEffect(() => {\n if (typeof window === 'undefined') return\n const url = new URL(window.location.href)\n const message = url.searchParams.get('flash')\n const type = normalizeFlashKind(url.searchParams.get('type'))\n if (message) {\n // Always strip the params so a spoofed link does not linger in history,\n // but only render the banner for same-origin navigations.\n const trusted = isSameOriginFlashNavigation()\n url.searchParams.delete('flash')\n url.searchParams.delete('type')\n window.history.replaceState({}, '', url.toString())\n if (trusted) {\n showFlash(message, type)\n }\n }\n }, [locationKey, showFlash])\n\n // Listen for programmatic flash events\n React.useEffect(() => {\n const handler = (e: Event) => {\n const ce = e as CustomEvent<{ message?: string; type?: FlashKind }>\n const text = ce.detail?.message\n const t = ce.detail?.type || 'info'\n if (!text) return\n showFlash(text, t)\n }\n window.addEventListener('flash', handler as EventListener)\n return () => window.removeEventListener('flash', handler as EventListener)\n }, [showFlash])\n\n const handleDismiss = React.useCallback(() => {\n clearDismissTimer()\n setMsg(null)\n }, [clearDismissTimer])\n\n if (!msg || !isPrimaryHost) return null\n\n return (\n <div className=\"pointer-events-none fixed left-3 right-3 top-3 z-toast sm:left-auto sm:right-4 sm:w-[380px]\">\n <div className=\"pointer-events-auto\">\n <Alert\n status={flashKindToAlertStatus[kind]}\n size=\"sm\"\n dismissible\n onDismiss={handleDismiss}\n className=\"shadow-md\"\n >\n {msg}\n </Alert>\n </div>\n </div>\n )\n}\n\nexport function FlashMessages() {\n return (\n <React.Suspense fallback={null}>\n <FlashMessagesInner />\n </React.Suspense>\n )\n}\n"],
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { Alert, type AlertStatus } from '../primitives/alert'\n\nexport type FlashKind = 'success' | 'error' | 'warning' | 'info'\n\nconst flashKindToAlertStatus: Record<FlashKind, AlertStatus> = {\n success: 'success',\n error: 'error',\n warning: 'warning',\n info: 'information',\n}\n\nfunction normalizeFlashKind(value: string | null | undefined): FlashKind {\n if (value && Object.prototype.hasOwnProperty.call(flashKindToAlertStatus, value)) {\n return value as FlashKind\n }\n return 'success'\n}\n\n// A URL-supplied flash is only trustworthy when the navigation that carried it\n// originated from the same origin (an in-app POST->GET redirect or client-side\n// navigation). Cross-origin links \u2014 the phishing/content-spoofing vector \u2014 must\n// not be allowed to render attacker-controlled copy inside an authoritative banner.\nfunction isSameOriginFlashNavigation(): boolean {\n if (typeof window === 'undefined') return false\n const referrer = document.referrer\n // No referrer (direct load, bookmark, or referrer stripped) is ambiguous, not a\n // cross-origin redirect we can attribute to an attacker page; allow it.\n if (!referrer) return true\n try {\n return new URL(referrer).origin === window.location.origin\n } catch {\n return false\n }\n}\n\n// A page that flashes from a mount effect (e.g. reading an OAuth callback's\n// result params) can run before any `<FlashMessages />` host has attached its\n// listener: on a full page load hydration is split across Suspense boundaries,\n// so the page's effects may commit ahead of the hosts' and the event would be\n// dropped. Keep the latest undelivered message briefly and let the hosts that\n// start listening in the same commit show it, so the primary-host election\n// stays in sync.\nconst PENDING_FLASH_MAX_AGE_MS = 5000\nlet listeningFlashHostCount = 0\nlet pendingFlash: { message: string; type: FlashKind; queuedAt: number } | null = null\n\nfunction readPendingFlash(): { message: string; type: FlashKind } | null {\n const pending = pendingFlash\n if (!pending) return null\n if (Date.now() - pending.queuedAt > PENDING_FLASH_MAX_AGE_MS) {\n pendingFlash = null\n return null\n }\n setTimeout(() => {\n if (pendingFlash === pending) pendingFlash = null\n }, 0)\n return pending\n}\n\n// Programmatic API to show a flash message without navigation.\n// Consumers can import { flash } and call flash('text', 'error').\nexport function flash(message: string, type: FlashKind = 'info') {\n if (typeof window === 'undefined') return\n if (listeningFlashHostCount === 0) {\n pendingFlash = { message, type, queuedAt: Date.now() }\n }\n const evt = new CustomEvent('flash', { detail: { message, type } })\n window.dispatchEvent(evt)\n}\n\n// Two hosts mount `<FlashMessages />` over the same page: `FrontendLayout`\n// wraps the entire app (backend routes included, via `AppProviders`) and\n// `AppShell` mounts its own copy inside `<main>`. Both listen to the same\n// `flash` event, so every backend toast rendered twice \u2014 two stacked fixed\n// overlays, each with its own dismiss button, so dismissing one left the other\n// behind. Both mount points are public surfaces third-party apps rely on, so\n// instead of deleting one, only the first host to mount renders; the others\n// keep their state in sync and take over if it unmounts.\nconst mountedFlashHostIds: symbol[] = []\nconst flashHostListeners = new Set<() => void>()\n\nfunction notifyFlashHostListeners() {\n for (const listener of flashHostListeners) listener()\n}\n\nfunction subscribeFlashHosts(listener: () => void): () => void {\n flashHostListeners.add(listener)\n return () => {\n flashHostListeners.delete(listener)\n }\n}\n\nfunction getPrimaryFlashHostId(): symbol | null {\n return mountedFlashHostIds[0] ?? null\n}\n\nfunction getServerFlashHostId(): symbol | null {\n return null\n}\n\nfunction useIsPrimaryFlashHost(): boolean {\n const hostIdRef = React.useRef<symbol | null>(null)\n if (hostIdRef.current === null) hostIdRef.current = Symbol('om-flash-host')\n const hostId = hostIdRef.current\n\n React.useEffect(() => {\n mountedFlashHostIds.push(hostId)\n notifyFlashHostListeners()\n return () => {\n const index = mountedFlashHostIds.indexOf(hostId)\n if (index >= 0) mountedFlashHostIds.splice(index, 1)\n notifyFlashHostListeners()\n }\n }, [hostId])\n\n return React.useSyncExternalStore(subscribeFlashHosts, getPrimaryFlashHostId, getServerFlashHostId) === hostId\n}\n\ntype HistoryMethod = History['pushState']\n\nfunction useLocationKey() {\n const [locationKey, setLocationKey] = React.useState(() => {\n if (typeof window === 'undefined') return ''\n return window.location.href\n })\n const locationKeyRef = React.useRef(locationKey)\n\n React.useEffect(() => {\n locationKeyRef.current = locationKey\n }, [locationKey])\n\n React.useEffect(() => {\n if (typeof window === 'undefined') return\n\n let active = true\n const scheduleUpdate = (href: string) => {\n const run = () => {\n if (!active) return\n if (locationKeyRef.current === href) return\n locationKeyRef.current = href\n setLocationKey(href)\n }\n if (typeof queueMicrotask === 'function') {\n queueMicrotask(run)\n } else {\n setTimeout(run, 0)\n }\n }\n const updateLocation = () => {\n if (!active) return\n const href = window.location.href\n if (href === locationKeyRef.current) return\n scheduleUpdate(href)\n }\n\n const deferredUpdateLocation = () => {\n setTimeout(updateLocation, 0)\n }\n\n const originalPush: HistoryMethod = window.history.pushState.bind(window.history)\n const originalReplace: HistoryMethod = window.history.replaceState.bind(window.history)\n\n const pushState: HistoryMethod = (...args) => {\n originalPush(...args)\n deferredUpdateLocation()\n }\n\n const replaceState: HistoryMethod = (...args) => {\n originalReplace(...args)\n deferredUpdateLocation()\n }\n\n window.history.pushState = pushState\n window.history.replaceState = replaceState\n window.addEventListener('popstate', updateLocation)\n window.addEventListener('hashchange', updateLocation)\n updateLocation()\n\n return () => {\n active = false\n window.history.pushState = originalPush\n window.history.replaceState = originalReplace\n window.removeEventListener('popstate', updateLocation)\n window.removeEventListener('hashchange', updateLocation)\n }\n }, [])\n\n return locationKey\n}\n\nfunction FlashMessagesInner() {\n const [msg, setMsg] = React.useState<string | null>(null)\n const [kind, setKind] = React.useState<FlashKind>('info')\n const isPrimaryHost = useIsPrimaryFlashHost()\n const locationKey = useLocationKey()\n const dismissTimerRef = React.useRef<ReturnType<typeof setTimeout> | null>(null)\n\n const clearDismissTimer = React.useCallback(() => {\n if (dismissTimerRef.current) {\n clearTimeout(dismissTimerRef.current)\n dismissTimerRef.current = null\n }\n }, [])\n\n const showFlash = React.useCallback((message: string, type: FlashKind) => {\n clearDismissTimer()\n setMsg(message)\n setKind(type)\n dismissTimerRef.current = setTimeout(() => {\n dismissTimerRef.current = null\n setMsg(null)\n }, 3000)\n }, [clearDismissTimer])\n\n React.useEffect(() => {\n return () => {\n clearDismissTimer()\n }\n }, [clearDismissTimer])\n\n // Read flash from URL on any navigation change (client-side too)\n React.useEffect(() => {\n if (typeof window === 'undefined') return\n const url = new URL(window.location.href)\n const message = url.searchParams.get('flash')\n const type = normalizeFlashKind(url.searchParams.get('type'))\n if (message) {\n // Always strip the params so a spoofed link does not linger in history,\n // but only render the banner for same-origin navigations.\n const trusted = isSameOriginFlashNavigation()\n url.searchParams.delete('flash')\n url.searchParams.delete('type')\n window.history.replaceState({}, '', url.toString())\n if (trusted) {\n showFlash(message, type)\n }\n }\n }, [locationKey, showFlash])\n\n // Listen for programmatic flash events\n React.useEffect(() => {\n const handler = (e: Event) => {\n const ce = e as CustomEvent<{ message?: string; type?: FlashKind }>\n const text = ce.detail?.message\n const t = ce.detail?.type || 'info'\n if (!text) return\n showFlash(text, t)\n }\n window.addEventListener('flash', handler as EventListener)\n listeningFlashHostCount += 1\n const pending = readPendingFlash()\n if (pending) showFlash(pending.message, pending.type)\n return () => {\n listeningFlashHostCount -= 1\n window.removeEventListener('flash', handler as EventListener)\n }\n }, [showFlash])\n\n const handleDismiss = React.useCallback(() => {\n clearDismissTimer()\n setMsg(null)\n }, [clearDismissTimer])\n\n if (!msg || !isPrimaryHost) return null\n\n return (\n <div className=\"pointer-events-none fixed left-3 right-3 top-3 z-toast sm:left-auto sm:right-4 sm:w-[380px]\">\n <div className=\"pointer-events-auto\">\n <Alert\n status={flashKindToAlertStatus[kind]}\n size=\"sm\"\n dismissible\n onDismiss={handleDismiss}\n className=\"shadow-md\"\n >\n {msg}\n </Alert>\n </div>\n </div>\n )\n}\n\nexport function FlashMessages() {\n return (\n <React.Suspense fallback={null}>\n <FlashMessagesInner />\n </React.Suspense>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -25,6 +25,7 @@ function ConfirmDialog({
|
|
|
25
25
|
const [internalOpen, setInternalOpen] = React.useState(false);
|
|
26
26
|
const cancelButtonRef = React.useRef(null);
|
|
27
27
|
const confirmButtonRef = React.useRef(null);
|
|
28
|
+
const restoreAriaHiddenRef = React.useRef(false);
|
|
28
29
|
const [portalTarget, setPortalTarget] = React.useState(null);
|
|
29
30
|
const reactId = React.useId();
|
|
30
31
|
const titleId = `confirm-dialog-title-${reactId}`;
|
|
@@ -63,10 +64,20 @@ function ConfirmDialog({
|
|
|
63
64
|
}
|
|
64
65
|
}, 0);
|
|
65
66
|
}
|
|
67
|
+
if (dialog.getAttribute("aria-hidden") === "true") {
|
|
68
|
+
dialog.removeAttribute("aria-hidden");
|
|
69
|
+
restoreAriaHiddenRef.current = true;
|
|
70
|
+
}
|
|
66
71
|
} else {
|
|
67
72
|
if (dialog.open) {
|
|
68
73
|
dialog.close();
|
|
69
74
|
}
|
|
75
|
+
if (restoreAriaHiddenRef.current) {
|
|
76
|
+
restoreAriaHiddenRef.current = false;
|
|
77
|
+
if (dialog.hasAttribute("data-aria-hidden")) {
|
|
78
|
+
dialog.setAttribute("aria-hidden", "true");
|
|
79
|
+
}
|
|
80
|
+
}
|
|
70
81
|
}
|
|
71
82
|
}, [open, resolvedCancelText, portalTarget]);
|
|
72
83
|
React.useEffect(() => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/backend/confirm-dialog/ConfirmDialog.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\";\nimport * as React from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useT } from \"@open-mercato/shared/lib/i18n/context\";\nimport { Button } from \"@open-mercato/ui/primitives/button\";\nimport { IconButton } from \"../../primitives/icon-button\";\nimport { cn } from \"@open-mercato/shared/lib/utils\";\nimport { Loader2, X } from \"lucide-react\";\n\nexport type ConfirmDialogProps = {\n /** Whether the dialog is open (controlled mode \u2014 used by useConfirmDialog) */\n open?: boolean;\n /** Callback when open state changes (controlled mode) */\n onOpenChange?: (open: boolean) => void;\n /** Callback when user confirms */\n onConfirm: () => void | Promise<void>;\n /** Callback when user cancels (optional, defaults to closing) */\n onCancel?: () => void;\n /** Dialog title. Defaults to i18n key \"ui.dialogs.confirm.defaultTitle\" (\"Are you sure?\") */\n title?: string;\n /** Dialog body text / description */\n text?: string;\n /** Confirm button label. Defaults to i18n \"ui.dialogs.confirm.confirmText\" (\"Confirm\").\n * Pass `false` to hide the confirm button entirely. */\n confirmText?: string | false;\n /** Cancel button label. Defaults to i18n \"ui.dialogs.confirm.cancelText\" (\"Cancel\").\n * Pass `false` to hide the cancel button entirely. */\n cancelText?: string | false;\n /** Visual variant \u2014 \"destructive\" renders the confirm button in red */\n variant?: \"default\" | \"destructive\";\n /** Whether the confirm button shows a loading spinner.\n * Useful for async onConfirm handlers (e.g., waiting for API response before closing). */\n loading?: boolean;\n /** Trigger element \u2014 when provided, component manages its own open state (declarative mode).\n * Clicking the trigger opens the dialog. */\n trigger?: React.ReactNode;\n};\n\nexport function ConfirmDialog({\n open: controlledOpen,\n onOpenChange,\n onConfirm,\n onCancel,\n title,\n text,\n confirmText,\n cancelText,\n variant = \"default\",\n loading = false,\n trigger,\n}: ConfirmDialogProps) {\n const t = useT();\n const dialogRef = React.useRef<HTMLDialogElement>(null);\n const [internalOpen, setInternalOpen] = React.useState(false);\n const cancelButtonRef = React.useRef<HTMLButtonElement>(null);\n const confirmButtonRef = React.useRef<HTMLButtonElement>(null);\n const [portalTarget, setPortalTarget] = React.useState<HTMLElement | null>(null);\n // Unique IDs so multiple ConfirmDialog instances on the same page don't\n // collide and make `aria-labelledby` resolve to the wrong dialog's title.\n const reactId = React.useId();\n const titleId = `confirm-dialog-title-${reactId}`;\n const descriptionId = `confirm-dialog-description-${reactId}`;\n\n // Determine if we're in controlled mode (open prop provided) or declarative mode (trigger provided)\n const isControlled = controlledOpen !== undefined;\n const open = isControlled ? controlledOpen : internalOpen;\n const setOpen = isControlled\n ? onOpenChange || (() => {})\n : setInternalOpen;\n const handleCancelCallback = React.useCallback(() => {\n if (!isControlled) {\n onCancel?.();\n }\n }, [isControlled, onCancel]);\n\n // Default text values from i18n\n const resolvedTitle =\n title ?? t(\"ui.dialogs.confirm.defaultTitle\", \"Are you sure?\");\n const resolvedConfirmText =\n confirmText === false\n ? false\n : confirmText ?? t(\"ui.dialogs.confirm.confirmText\", \"Confirm\");\n const resolvedCancelText =\n cancelText === false\n ? false\n : cancelText ?? t(\"ui.dialogs.confirm.cancelText\", \"Cancel\");\n const closeAriaLabel = t(\"ui.dialog.close.ariaLabel\", \"Close\");\n const requestClose = React.useCallback(() => {\n setOpen(false);\n handleCancelCallback();\n }, [setOpen, handleCancelCallback]);\n\n React.useLayoutEffect(() => {\n setPortalTarget(document.body);\n }, []);\n\n // Handle dialog open/close with native showModal/close\n React.useLayoutEffect(() => {\n const dialog = dialogRef.current;\n if (!dialog) return;\n\n if (open) {\n if (!dialog.open) {\n dialog.showModal();\n // Focus cancel button (safe default) or confirm if no cancel\n setTimeout(() => {\n if (resolvedCancelText !== false && cancelButtonRef.current) {\n cancelButtonRef.current.focus();\n } else if (confirmButtonRef.current) {\n confirmButtonRef.current.focus();\n }\n }, 0);\n }\n } else {\n if (dialog.open) {\n dialog.close();\n }\n }\n }, [open, resolvedCancelText, portalTarget]);\n\n // Handle native cancel event (Escape key)\n React.useEffect(() => {\n const dialog = dialogRef.current;\n if (!dialog) return;\n\n const handleCancel = (e: Event) => {\n // Prevent close if loading\n if (loading) {\n e.preventDefault();\n return;\n }\n requestClose();\n };\n\n dialog.addEventListener(\"cancel\", handleCancel);\n return () => dialog.removeEventListener(\"cancel\", handleCancel);\n }, [loading, requestClose]);\n\n React.useEffect(() => {\n if (!open) return;\n\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key !== \"Escape\") return;\n if (!(event.target instanceof Node) || !dialogRef.current?.contains(event.target)) return;\n event.preventDefault();\n event.stopPropagation();\n if (!loading) requestClose();\n };\n\n window.addEventListener(\"keydown\", handleEscape, true);\n return () => window.removeEventListener(\"keydown\", handleEscape, true);\n }, [loading, open, requestClose]);\n\n // Handle backdrop click\n const handleBackdropClick = (e: React.MouseEvent<HTMLDialogElement>) => {\n // Only close if clicking directly on the dialog (backdrop), not its children\n if (e.target === dialogRef.current && !loading) {\n requestClose();\n }\n };\n\n // Handle keyboard shortcuts\n React.useEffect(() => {\n if (!open) return;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n // Cmd/Ctrl+Enter confirms\n if ((e.metaKey || e.ctrlKey) && e.key === \"Enter\" && !loading) {\n e.preventDefault();\n handleConfirm();\n }\n };\n\n window.addEventListener(\"keydown\", handleKeyDown);\n return () => window.removeEventListener(\"keydown\", handleKeyDown);\n }, [open, loading]);\n\n const handleConfirm = async () => {\n await onConfirm();\n // Don't auto-close if loading \u2014 let the parent control when to close\n if (!loading) {\n setOpen(false);\n }\n };\n\n const handleCancel = () => {\n requestClose();\n };\n\n const handleTriggerClick = () => {\n if (trigger) {\n setOpen(true);\n }\n };\n\n const dialogElement = (\n <dialog\n ref={dialogRef}\n role=\"alertdialog\"\n aria-labelledby={titleId}\n aria-describedby={text ? descriptionId : undefined}\n onClick={handleBackdropClick}\n className={cn(\n // Reset dialog defaults\n \"m-0 p-0 max-w-none bg-transparent border-none pointer-events-auto\",\n // Backdrop styling\n \"backdrop:bg-black/50 backdrop:backdrop-blur-sm backdrop:transition-opacity\",\n // Mobile: bottom sheet\n \"fixed inset-x-0 bottom-0 top-auto w-full\",\n // Desktop: centered\n \"sm:inset-auto sm:mx-auto sm:my-auto sm:max-w-md sm:top-1/2 sm:left-1/2 sm:-translate-x-1/2 sm:-translate-y-1/2\",\n // Animation with reduced motion support\n \"motion-safe:open:animate-in motion-safe:open:fade-in-0 motion-safe:open:slide-in-from-bottom-4\",\n \"sm:motion-safe:open:slide-in-from-bottom-0 sm:motion-safe:open:zoom-in-95\",\n // Duration\n \"motion-safe:open:duration-300\"\n )}\n >\n <div\n role=\"document\"\n className={cn(\n // Panel container\n \"flex flex-col gap-4 rounded-t-2xl border-t bg-card p-6 text-foreground shadow-lg\",\n \"sm:rounded-xl sm:border\",\n // Relative positioning for close button\n \"relative\"\n )}\n >\n {/* Close button */}\n <IconButton\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={handleCancel}\n disabled={loading}\n aria-label={closeAriaLabel}\n className=\"absolute right-4 top-4 opacity-70 hover:opacity-100\"\n >\n <X className=\"h-4 w-4\" />\n </IconButton>\n\n {/* Title */}\n <h2\n id={titleId}\n className={cn(\n \"text-sm font-medium leading-snug tracking-tight pr-6\",\n // Mobile: centered, Desktop: left-aligned\n \"text-center sm:text-left\"\n )}\n >\n {resolvedTitle}\n </h2>\n\n {/* Description (optional) */}\n {text && (\n <p\n id={descriptionId}\n className=\"text-sm font-medium leading-snug text-muted-foreground\"\n >\n {text}\n </p>\n )}\n\n {/* Actions */}\n <div className=\"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\">\n {resolvedCancelText !== false && (\n <Button\n ref={cancelButtonRef}\n variant=\"outline\"\n onClick={handleCancel}\n disabled={loading}\n className=\"w-full sm:w-auto\"\n >\n {resolvedCancelText}\n </Button>\n )}\n {resolvedConfirmText !== false && (\n <Button\n ref={confirmButtonRef}\n variant={variant === \"destructive\" ? \"destructive-solid\" : \"default\"}\n onClick={handleConfirm}\n disabled={loading}\n className=\"w-full sm:w-auto\"\n >\n {loading && <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" />}\n {resolvedConfirmText}\n </Button>\n )}\n </div>\n </div>\n </dialog>\n );\n\n return (\n <>\n {trigger && (\n <div onClick={handleTriggerClick} className=\"inline-block\" role=\"presentation\">\n {trigger}\n </div>\n )}\n\n {portalTarget ? createPortal(dialogElement, portalTarget) : null}\n </>\n );\n}\n"],
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["\"use client\";\nimport * as React from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useT } from \"@open-mercato/shared/lib/i18n/context\";\nimport { Button } from \"@open-mercato/ui/primitives/button\";\nimport { IconButton } from \"../../primitives/icon-button\";\nimport { cn } from \"@open-mercato/shared/lib/utils\";\nimport { Loader2, X } from \"lucide-react\";\n\nexport type ConfirmDialogProps = {\n /** Whether the dialog is open (controlled mode \u2014 used by useConfirmDialog) */\n open?: boolean;\n /** Callback when open state changes (controlled mode) */\n onOpenChange?: (open: boolean) => void;\n /** Callback when user confirms */\n onConfirm: () => void | Promise<void>;\n /** Callback when user cancels (optional, defaults to closing) */\n onCancel?: () => void;\n /** Dialog title. Defaults to i18n key \"ui.dialogs.confirm.defaultTitle\" (\"Are you sure?\") */\n title?: string;\n /** Dialog body text / description */\n text?: string;\n /** Confirm button label. Defaults to i18n \"ui.dialogs.confirm.confirmText\" (\"Confirm\").\n * Pass `false` to hide the confirm button entirely. */\n confirmText?: string | false;\n /** Cancel button label. Defaults to i18n \"ui.dialogs.confirm.cancelText\" (\"Cancel\").\n * Pass `false` to hide the cancel button entirely. */\n cancelText?: string | false;\n /** Visual variant \u2014 \"destructive\" renders the confirm button in red */\n variant?: \"default\" | \"destructive\";\n /** Whether the confirm button shows a loading spinner.\n * Useful for async onConfirm handlers (e.g., waiting for API response before closing). */\n loading?: boolean;\n /** Trigger element \u2014 when provided, component manages its own open state (declarative mode).\n * Clicking the trigger opens the dialog. */\n trigger?: React.ReactNode;\n};\n\nexport function ConfirmDialog({\n open: controlledOpen,\n onOpenChange,\n onConfirm,\n onCancel,\n title,\n text,\n confirmText,\n cancelText,\n variant = \"default\",\n loading = false,\n trigger,\n}: ConfirmDialogProps) {\n const t = useT();\n const dialogRef = React.useRef<HTMLDialogElement>(null);\n const [internalOpen, setInternalOpen] = React.useState(false);\n const cancelButtonRef = React.useRef<HTMLButtonElement>(null);\n const confirmButtonRef = React.useRef<HTMLButtonElement>(null);\n const restoreAriaHiddenRef = React.useRef(false);\n const [portalTarget, setPortalTarget] = React.useState<HTMLElement | null>(null);\n // Unique IDs so multiple ConfirmDialog instances on the same page don't\n // collide and make `aria-labelledby` resolve to the wrong dialog's title.\n const reactId = React.useId();\n const titleId = `confirm-dialog-title-${reactId}`;\n const descriptionId = `confirm-dialog-description-${reactId}`;\n\n // Determine if we're in controlled mode (open prop provided) or declarative mode (trigger provided)\n const isControlled = controlledOpen !== undefined;\n const open = isControlled ? controlledOpen : internalOpen;\n const setOpen = isControlled\n ? onOpenChange || (() => {})\n : setInternalOpen;\n const handleCancelCallback = React.useCallback(() => {\n if (!isControlled) {\n onCancel?.();\n }\n }, [isControlled, onCancel]);\n\n // Default text values from i18n\n const resolvedTitle =\n title ?? t(\"ui.dialogs.confirm.defaultTitle\", \"Are you sure?\");\n const resolvedConfirmText =\n confirmText === false\n ? false\n : confirmText ?? t(\"ui.dialogs.confirm.confirmText\", \"Confirm\");\n const resolvedCancelText =\n cancelText === false\n ? false\n : cancelText ?? t(\"ui.dialogs.confirm.cancelText\", \"Cancel\");\n const closeAriaLabel = t(\"ui.dialog.close.ariaLabel\", \"Close\");\n const requestClose = React.useCallback(() => {\n setOpen(false);\n handleCancelCallback();\n }, [setOpen, handleCancelCallback]);\n\n React.useLayoutEffect(() => {\n setPortalTarget(document.body);\n }, []);\n\n // Handle dialog open/close with native showModal/close\n React.useLayoutEffect(() => {\n const dialog = dialogRef.current;\n if (!dialog) return;\n\n if (open) {\n if (!dialog.open) {\n dialog.showModal();\n // Focus cancel button (safe default) or confirm if no cancel\n setTimeout(() => {\n if (resolvedCancelText !== false && cancelButtonRef.current) {\n cancelButtonRef.current.focus();\n } else if (confirmButtonRef.current) {\n confirmButtonRef.current.focus();\n }\n }, 0);\n }\n // A modal opened underneath (e.g. a Radix Dialog) marks every sibling in\n // <body> `aria-hidden`, including this portalled element. Shown on top\n // of that modal it must stay reachable for assistive technology.\n if (dialog.getAttribute(\"aria-hidden\") === \"true\") {\n dialog.removeAttribute(\"aria-hidden\");\n restoreAriaHiddenRef.current = true;\n }\n } else {\n if (dialog.open) {\n dialog.close();\n }\n if (restoreAriaHiddenRef.current) {\n restoreAriaHiddenRef.current = false;\n // Hand the attribute back only while the modal that hid us is still\n // open; its own cleanup has otherwise already removed the marker.\n if (dialog.hasAttribute(\"data-aria-hidden\")) {\n dialog.setAttribute(\"aria-hidden\", \"true\");\n }\n }\n }\n }, [open, resolvedCancelText, portalTarget]);\n\n // Handle native cancel event (Escape key)\n React.useEffect(() => {\n const dialog = dialogRef.current;\n if (!dialog) return;\n\n const handleCancel = (e: Event) => {\n // Prevent close if loading\n if (loading) {\n e.preventDefault();\n return;\n }\n requestClose();\n };\n\n dialog.addEventListener(\"cancel\", handleCancel);\n return () => dialog.removeEventListener(\"cancel\", handleCancel);\n }, [loading, requestClose]);\n\n React.useEffect(() => {\n if (!open) return;\n\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key !== \"Escape\") return;\n if (!(event.target instanceof Node) || !dialogRef.current?.contains(event.target)) return;\n event.preventDefault();\n event.stopPropagation();\n if (!loading) requestClose();\n };\n\n window.addEventListener(\"keydown\", handleEscape, true);\n return () => window.removeEventListener(\"keydown\", handleEscape, true);\n }, [loading, open, requestClose]);\n\n // Handle backdrop click\n const handleBackdropClick = (e: React.MouseEvent<HTMLDialogElement>) => {\n // Only close if clicking directly on the dialog (backdrop), not its children\n if (e.target === dialogRef.current && !loading) {\n requestClose();\n }\n };\n\n // Handle keyboard shortcuts\n React.useEffect(() => {\n if (!open) return;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n // Cmd/Ctrl+Enter confirms\n if ((e.metaKey || e.ctrlKey) && e.key === \"Enter\" && !loading) {\n e.preventDefault();\n handleConfirm();\n }\n };\n\n window.addEventListener(\"keydown\", handleKeyDown);\n return () => window.removeEventListener(\"keydown\", handleKeyDown);\n }, [open, loading]);\n\n const handleConfirm = async () => {\n await onConfirm();\n // Don't auto-close if loading \u2014 let the parent control when to close\n if (!loading) {\n setOpen(false);\n }\n };\n\n const handleCancel = () => {\n requestClose();\n };\n\n const handleTriggerClick = () => {\n if (trigger) {\n setOpen(true);\n }\n };\n\n const dialogElement = (\n <dialog\n ref={dialogRef}\n role=\"alertdialog\"\n aria-labelledby={titleId}\n aria-describedby={text ? descriptionId : undefined}\n onClick={handleBackdropClick}\n className={cn(\n // Reset dialog defaults\n \"m-0 p-0 max-w-none bg-transparent border-none pointer-events-auto\",\n // Backdrop styling\n \"backdrop:bg-black/50 backdrop:backdrop-blur-sm backdrop:transition-opacity\",\n // Mobile: bottom sheet\n \"fixed inset-x-0 bottom-0 top-auto w-full\",\n // Desktop: centered\n \"sm:inset-auto sm:mx-auto sm:my-auto sm:max-w-md sm:top-1/2 sm:left-1/2 sm:-translate-x-1/2 sm:-translate-y-1/2\",\n // Animation with reduced motion support\n \"motion-safe:open:animate-in motion-safe:open:fade-in-0 motion-safe:open:slide-in-from-bottom-4\",\n \"sm:motion-safe:open:slide-in-from-bottom-0 sm:motion-safe:open:zoom-in-95\",\n // Duration\n \"motion-safe:open:duration-300\"\n )}\n >\n <div\n role=\"document\"\n className={cn(\n // Panel container\n \"flex flex-col gap-4 rounded-t-2xl border-t bg-card p-6 text-foreground shadow-lg\",\n \"sm:rounded-xl sm:border\",\n // Relative positioning for close button\n \"relative\"\n )}\n >\n {/* Close button */}\n <IconButton\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={handleCancel}\n disabled={loading}\n aria-label={closeAriaLabel}\n className=\"absolute right-4 top-4 opacity-70 hover:opacity-100\"\n >\n <X className=\"h-4 w-4\" />\n </IconButton>\n\n {/* Title */}\n <h2\n id={titleId}\n className={cn(\n \"text-sm font-medium leading-snug tracking-tight pr-6\",\n // Mobile: centered, Desktop: left-aligned\n \"text-center sm:text-left\"\n )}\n >\n {resolvedTitle}\n </h2>\n\n {/* Description (optional) */}\n {text && (\n <p\n id={descriptionId}\n className=\"text-sm font-medium leading-snug text-muted-foreground\"\n >\n {text}\n </p>\n )}\n\n {/* Actions */}\n <div className=\"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\">\n {resolvedCancelText !== false && (\n <Button\n ref={cancelButtonRef}\n variant=\"outline\"\n onClick={handleCancel}\n disabled={loading}\n className=\"w-full sm:w-auto\"\n >\n {resolvedCancelText}\n </Button>\n )}\n {resolvedConfirmText !== false && (\n <Button\n ref={confirmButtonRef}\n variant={variant === \"destructive\" ? \"destructive-solid\" : \"default\"}\n onClick={handleConfirm}\n disabled={loading}\n className=\"w-full sm:w-auto\"\n >\n {loading && <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" />}\n {resolvedConfirmText}\n </Button>\n )}\n </div>\n </div>\n </dialog>\n );\n\n return (\n <>\n {trigger && (\n <div onClick={handleTriggerClick} className=\"inline-block\" role=\"presentation\">\n {trigger}\n </div>\n )}\n\n {portalTarget ? createPortal(dialogElement, portalTarget) : null}\n </>\n );\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["handleCancel"]
|
|
7
7
|
}
|
|
@@ -400,6 +400,22 @@ function PhoneNumberField({
|
|
|
400
400
|
() => buildPhoneCountryOptions(countriesProp, t, locale),
|
|
401
401
|
[countriesProp, t, locale]
|
|
402
402
|
);
|
|
403
|
+
const countryItems = React.useMemo(
|
|
404
|
+
() => countryOptions.map(({ country: optionCountry, label }) => /* @__PURE__ */ jsxs(
|
|
405
|
+
SelectItem,
|
|
406
|
+
{
|
|
407
|
+
value: optionCountry.iso2,
|
|
408
|
+
textValue: label,
|
|
409
|
+
children: [
|
|
410
|
+
/* @__PURE__ */ jsx(SelectItemLeading, { children: /* @__PURE__ */ jsx("span", { className: "text-base leading-none", children: optionCountry.flag }) }),
|
|
411
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: label }),
|
|
412
|
+
/* @__PURE__ */ jsx("span", { className: "ml-2 text-xs text-muted-foreground tabular-nums", children: optionCountry.dialCode })
|
|
413
|
+
]
|
|
414
|
+
},
|
|
415
|
+
`${optionCountry.iso2}-${optionCountry.dialCode}`
|
|
416
|
+
)),
|
|
417
|
+
[countryOptions]
|
|
418
|
+
);
|
|
403
419
|
const fallbackCountry = React.useMemo(
|
|
404
420
|
() => defaultCountryIso2 && findCountryByIso(defaultCountryIso2) || DEFAULT_COUNTRY,
|
|
405
421
|
[defaultCountryIso2]
|
|
@@ -556,11 +572,7 @@ function PhoneNumberField({
|
|
|
556
572
|
]
|
|
557
573
|
}
|
|
558
574
|
),
|
|
559
|
-
/* @__PURE__ */ jsx(SelectContent, { align: "start", children:
|
|
560
|
-
/* @__PURE__ */ jsx(SelectItemLeading, { children: /* @__PURE__ */ jsx("span", { className: "text-base leading-none", children: c.flag }) }),
|
|
561
|
-
/* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: label }),
|
|
562
|
-
/* @__PURE__ */ jsx("span", { className: "ml-2 text-xs text-muted-foreground tabular-nums", children: c.dialCode })
|
|
563
|
-
] }, `${c.iso2}-${c.dialCode}`)) })
|
|
575
|
+
/* @__PURE__ */ jsx(SelectContent, { align: "start", children: countryItems })
|
|
564
576
|
] }),
|
|
565
577
|
/* @__PURE__ */ jsx("div", { "aria-hidden": "true", className: "w-px self-stretch bg-input" }),
|
|
566
578
|
/* @__PURE__ */ jsx(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/backend/inputs/PhoneNumberField.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useOptionalLocale, useT, type TranslateFn } from '@open-mercato/shared/lib/i18n/context'\nimport { extractPhoneDigits, validatePhoneNumber } from '@open-mercato/shared/lib/phone'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectItemLeading,\n SelectTrigger,\n} from '../../primitives/select'\n\nexport type PhoneDuplicateMatch = {\n id: string\n label: string\n href: string\n}\n\nexport type PhoneCountry = {\n /** ISO 3166-1 alpha-2 code. */\n iso2: string\n /** International dial code (with `+`). */\n dialCode: string\n /**\n * Human-readable country name (English). Used as the last-resort fallback\n * when neither a locale file nor the platform's region data can name the\n * country in the active locale.\n */\n label: string\n /** Emoji flag (no asset dependency). */\n flag: string\n}\n\n/**\n * Emoji flag for an ISO 3166-1 alpha-2 code, assembled from the two regional\n * indicator symbols. Deriving it keeps the (large) dictionary free of hand-typed\n * emoji and guarantees the flag always matches the code.\n */\nfunction iso2ToFlagEmoji(iso2: string): string {\n const letters = iso2.toUpperCase().replace(/[^A-Z]/g, '')\n if (letters.length !== 2) return ''\n const base = 0x1f1e6\n return String.fromCodePoint(\n base + letters.charCodeAt(0) - 65,\n base + letters.charCodeAt(1) - 65,\n )\n}\n\n/**\n * Complete static dictionary of geographic countries and territories that have\n * an ISO 3166-1 alpha-2 code and an international calling code, based on the\n * ITU / Wikipedia list of telephone country codes.\n *\n * Rules baked into this data:\n * - Labels are English; flags are derived from the ISO code (`iso2ToFlagEmoji`).\n * - Non-geographic / international service codes (`+800`, `+808`, `+870`,\n * `+881`, `+882`, \u2026) are intentionally excluded.\n * - North American Numbering Plan territories carry their full `+1<NPA>` dial\n * code (e.g. Bahamas `+1242`) so longest-prefix matching resolves them before\n * the generic `+1`. The US and Canada BOTH use a bare `+1` and cannot be told\n * apart from the prefix alone \u2014 auto-detection favours the US.\n * - Several sovereign countries share a calling code with dependent territories\n * (e.g. `+44` UK/Guernsey/Jersey/Isle of Man); `PRIMARY_DIAL_OWNERS` records\n * the country that wins auto-detection for those shared codes.\n */\nconst RAW_PHONE_COUNTRIES: Array<Omit<PhoneCountry, 'flag'>> = [\n { iso2: 'US', dialCode: '+1', label: 'United States' },\n { iso2: 'CA', dialCode: '+1', label: 'Canada' },\n { iso2: 'AG', dialCode: '+1268', label: 'Antigua and Barbuda' },\n { iso2: 'AI', dialCode: '+1264', label: 'Anguilla' },\n { iso2: 'AS', dialCode: '+1684', label: 'American Samoa' },\n { iso2: 'BB', dialCode: '+1246', label: 'Barbados' },\n { iso2: 'BM', dialCode: '+1441', label: 'Bermuda' },\n { iso2: 'BS', dialCode: '+1242', label: 'Bahamas' },\n { iso2: 'DM', dialCode: '+1767', label: 'Dominica' },\n { iso2: 'DO', dialCode: '+1809', label: 'Dominican Republic' },\n { iso2: 'GD', dialCode: '+1473', label: 'Grenada' },\n { iso2: 'GU', dialCode: '+1671', label: 'Guam' },\n { iso2: 'JM', dialCode: '+1876', label: 'Jamaica' },\n { iso2: 'KN', dialCode: '+1869', label: 'Saint Kitts and Nevis' },\n { iso2: 'KY', dialCode: '+1345', label: 'Cayman Islands' },\n { iso2: 'LC', dialCode: '+1758', label: 'Saint Lucia' },\n { iso2: 'MP', dialCode: '+1670', label: 'Northern Mariana Islands' },\n { iso2: 'MS', dialCode: '+1664', label: 'Montserrat' },\n { iso2: 'PR', dialCode: '+1787', label: 'Puerto Rico' },\n { iso2: 'SX', dialCode: '+1721', label: 'Sint Maarten' },\n { iso2: 'TC', dialCode: '+1649', label: 'Turks and Caicos Islands' },\n { iso2: 'TT', dialCode: '+1868', label: 'Trinidad and Tobago' },\n { iso2: 'VC', dialCode: '+1784', label: 'Saint Vincent and the Grenadines' },\n { iso2: 'VG', dialCode: '+1284', label: 'British Virgin Islands' },\n { iso2: 'VI', dialCode: '+1340', label: 'U.S. Virgin Islands' },\n { iso2: 'EG', dialCode: '+20', label: 'Egypt' },\n { iso2: 'SS', dialCode: '+211', label: 'South Sudan' },\n { iso2: 'MA', dialCode: '+212', label: 'Morocco' },\n { iso2: 'EH', dialCode: '+212', label: 'Western Sahara' },\n { iso2: 'DZ', dialCode: '+213', label: 'Algeria' },\n { iso2: 'TN', dialCode: '+216', label: 'Tunisia' },\n { iso2: 'LY', dialCode: '+218', label: 'Libya' },\n { iso2: 'GM', dialCode: '+220', label: 'Gambia' },\n { iso2: 'SN', dialCode: '+221', label: 'Senegal' },\n { iso2: 'MR', dialCode: '+222', label: 'Mauritania' },\n { iso2: 'ML', dialCode: '+223', label: 'Mali' },\n { iso2: 'GN', dialCode: '+224', label: 'Guinea' },\n { iso2: 'CI', dialCode: '+225', label: \"C\u00F4te d'Ivoire\" },\n { iso2: 'BF', dialCode: '+226', label: 'Burkina Faso' },\n { iso2: 'NE', dialCode: '+227', label: 'Niger' },\n { iso2: 'TG', dialCode: '+228', label: 'Togo' },\n { iso2: 'BJ', dialCode: '+229', label: 'Benin' },\n { iso2: 'MU', dialCode: '+230', label: 'Mauritius' },\n { iso2: 'LR', dialCode: '+231', label: 'Liberia' },\n { iso2: 'SL', dialCode: '+232', label: 'Sierra Leone' },\n { iso2: 'GH', dialCode: '+233', label: 'Ghana' },\n { iso2: 'NG', dialCode: '+234', label: 'Nigeria' },\n { iso2: 'TD', dialCode: '+235', label: 'Chad' },\n { iso2: 'CF', dialCode: '+236', label: 'Central African Republic' },\n { iso2: 'CM', dialCode: '+237', label: 'Cameroon' },\n { iso2: 'CV', dialCode: '+238', label: 'Cape Verde' },\n { iso2: 'ST', dialCode: '+239', label: 'S\u00E3o Tom\u00E9 and Pr\u00EDncipe' },\n { iso2: 'GQ', dialCode: '+240', label: 'Equatorial Guinea' },\n { iso2: 'GA', dialCode: '+241', label: 'Gabon' },\n { iso2: 'CG', dialCode: '+242', label: 'Republic of the Congo' },\n { iso2: 'CD', dialCode: '+243', label: 'DR Congo' },\n { iso2: 'AO', dialCode: '+244', label: 'Angola' },\n { iso2: 'GW', dialCode: '+245', label: 'Guinea-Bissau' },\n { iso2: 'IO', dialCode: '+246', label: 'British Indian Ocean Territory' },\n { iso2: 'SC', dialCode: '+248', label: 'Seychelles' },\n { iso2: 'SD', dialCode: '+249', label: 'Sudan' },\n { iso2: 'RW', dialCode: '+250', label: 'Rwanda' },\n { iso2: 'ET', dialCode: '+251', label: 'Ethiopia' },\n { iso2: 'SO', dialCode: '+252', label: 'Somalia' },\n { iso2: 'DJ', dialCode: '+253', label: 'Djibouti' },\n { iso2: 'KE', dialCode: '+254', label: 'Kenya' },\n { iso2: 'TZ', dialCode: '+255', label: 'Tanzania' },\n { iso2: 'UG', dialCode: '+256', label: 'Uganda' },\n { iso2: 'BI', dialCode: '+257', label: 'Burundi' },\n { iso2: 'MZ', dialCode: '+258', label: 'Mozambique' },\n { iso2: 'ZM', dialCode: '+260', label: 'Zambia' },\n { iso2: 'MG', dialCode: '+261', label: 'Madagascar' },\n { iso2: 'RE', dialCode: '+262', label: 'R\u00E9union' },\n { iso2: 'YT', dialCode: '+262', label: 'Mayotte' },\n { iso2: 'ZW', dialCode: '+263', label: 'Zimbabwe' },\n { iso2: 'NA', dialCode: '+264', label: 'Namibia' },\n { iso2: 'MW', dialCode: '+265', label: 'Malawi' },\n { iso2: 'LS', dialCode: '+266', label: 'Lesotho' },\n { iso2: 'BW', dialCode: '+267', label: 'Botswana' },\n { iso2: 'SZ', dialCode: '+268', label: 'Eswatini' },\n { iso2: 'KM', dialCode: '+269', label: 'Comoros' },\n { iso2: 'ZA', dialCode: '+27', label: 'South Africa' },\n { iso2: 'SH', dialCode: '+290', label: 'Saint Helena' },\n { iso2: 'ER', dialCode: '+291', label: 'Eritrea' },\n { iso2: 'AW', dialCode: '+297', label: 'Aruba' },\n { iso2: 'FO', dialCode: '+298', label: 'Faroe Islands' },\n { iso2: 'GL', dialCode: '+299', label: 'Greenland' },\n { iso2: 'GR', dialCode: '+30', label: 'Greece' },\n { iso2: 'NL', dialCode: '+31', label: 'Netherlands' },\n { iso2: 'BE', dialCode: '+32', label: 'Belgium' },\n { iso2: 'FR', dialCode: '+33', label: 'France' },\n { iso2: 'ES', dialCode: '+34', label: 'Spain' },\n { iso2: 'GI', dialCode: '+350', label: 'Gibraltar' },\n { iso2: 'PT', dialCode: '+351', label: 'Portugal' },\n { iso2: 'LU', dialCode: '+352', label: 'Luxembourg' },\n { iso2: 'IE', dialCode: '+353', label: 'Ireland' },\n { iso2: 'IS', dialCode: '+354', label: 'Iceland' },\n { iso2: 'AL', dialCode: '+355', label: 'Albania' },\n { iso2: 'MT', dialCode: '+356', label: 'Malta' },\n { iso2: 'CY', dialCode: '+357', label: 'Cyprus' },\n { iso2: 'FI', dialCode: '+358', label: 'Finland' },\n { iso2: 'AX', dialCode: '+358', label: '\u00C5land Islands' },\n { iso2: 'BG', dialCode: '+359', label: 'Bulgaria' },\n { iso2: 'HU', dialCode: '+36', label: 'Hungary' },\n { iso2: 'LT', dialCode: '+370', label: 'Lithuania' },\n { iso2: 'LV', dialCode: '+371', label: 'Latvia' },\n { iso2: 'EE', dialCode: '+372', label: 'Estonia' },\n { iso2: 'MD', dialCode: '+373', label: 'Moldova' },\n { iso2: 'AM', dialCode: '+374', label: 'Armenia' },\n { iso2: 'BY', dialCode: '+375', label: 'Belarus' },\n { iso2: 'AD', dialCode: '+376', label: 'Andorra' },\n { iso2: 'MC', dialCode: '+377', label: 'Monaco' },\n { iso2: 'SM', dialCode: '+378', label: 'San Marino' },\n { iso2: 'VA', dialCode: '+379', label: 'Vatican City' },\n { iso2: 'UA', dialCode: '+380', label: 'Ukraine' },\n { iso2: 'RS', dialCode: '+381', label: 'Serbia' },\n { iso2: 'ME', dialCode: '+382', label: 'Montenegro' },\n { iso2: 'XK', dialCode: '+383', label: 'Kosovo' },\n { iso2: 'HR', dialCode: '+385', label: 'Croatia' },\n { iso2: 'SI', dialCode: '+386', label: 'Slovenia' },\n { iso2: 'BA', dialCode: '+387', label: 'Bosnia and Herzegovina' },\n { iso2: 'MK', dialCode: '+389', label: 'North Macedonia' },\n { iso2: 'IT', dialCode: '+39', label: 'Italy' },\n { iso2: 'RO', dialCode: '+40', label: 'Romania' },\n { iso2: 'CH', dialCode: '+41', label: 'Switzerland' },\n { iso2: 'CZ', dialCode: '+420', label: 'Czechia' },\n { iso2: 'SK', dialCode: '+421', label: 'Slovakia' },\n { iso2: 'LI', dialCode: '+423', label: 'Liechtenstein' },\n { iso2: 'AT', dialCode: '+43', label: 'Austria' },\n { iso2: 'GB', dialCode: '+44', label: 'United Kingdom' },\n { iso2: 'GG', dialCode: '+44', label: 'Guernsey' },\n { iso2: 'JE', dialCode: '+44', label: 'Jersey' },\n { iso2: 'IM', dialCode: '+44', label: 'Isle of Man' },\n { iso2: 'DK', dialCode: '+45', label: 'Denmark' },\n { iso2: 'SE', dialCode: '+46', label: 'Sweden' },\n { iso2: 'NO', dialCode: '+47', label: 'Norway' },\n { iso2: 'SJ', dialCode: '+47', label: 'Svalbard and Jan Mayen' },\n { iso2: 'PL', dialCode: '+48', label: 'Poland' },\n { iso2: 'DE', dialCode: '+49', label: 'Germany' },\n { iso2: 'FK', dialCode: '+500', label: 'Falkland Islands' },\n { iso2: 'BZ', dialCode: '+501', label: 'Belize' },\n { iso2: 'GT', dialCode: '+502', label: 'Guatemala' },\n { iso2: 'SV', dialCode: '+503', label: 'El Salvador' },\n { iso2: 'HN', dialCode: '+504', label: 'Honduras' },\n { iso2: 'NI', dialCode: '+505', label: 'Nicaragua' },\n { iso2: 'CR', dialCode: '+506', label: 'Costa Rica' },\n { iso2: 'PA', dialCode: '+507', label: 'Panama' },\n { iso2: 'PM', dialCode: '+508', label: 'Saint Pierre and Miquelon' },\n { iso2: 'HT', dialCode: '+509', label: 'Haiti' },\n { iso2: 'PE', dialCode: '+51', label: 'Peru' },\n { iso2: 'MX', dialCode: '+52', label: 'Mexico' },\n { iso2: 'CU', dialCode: '+53', label: 'Cuba' },\n { iso2: 'AR', dialCode: '+54', label: 'Argentina' },\n { iso2: 'BR', dialCode: '+55', label: 'Brazil' },\n { iso2: 'CL', dialCode: '+56', label: 'Chile' },\n { iso2: 'CO', dialCode: '+57', label: 'Colombia' },\n { iso2: 'VE', dialCode: '+58', label: 'Venezuela' },\n { iso2: 'GP', dialCode: '+590', label: 'Guadeloupe' },\n { iso2: 'BL', dialCode: '+590', label: 'Saint Barth\u00E9lemy' },\n { iso2: 'MF', dialCode: '+590', label: 'Saint Martin' },\n { iso2: 'BO', dialCode: '+591', label: 'Bolivia' },\n { iso2: 'GY', dialCode: '+592', label: 'Guyana' },\n { iso2: 'EC', dialCode: '+593', label: 'Ecuador' },\n { iso2: 'GF', dialCode: '+594', label: 'French Guiana' },\n { iso2: 'PY', dialCode: '+595', label: 'Paraguay' },\n { iso2: 'MQ', dialCode: '+596', label: 'Martinique' },\n { iso2: 'SR', dialCode: '+597', label: 'Suriname' },\n { iso2: 'UY', dialCode: '+598', label: 'Uruguay' },\n { iso2: 'CW', dialCode: '+599', label: 'Cura\u00E7ao' },\n { iso2: 'BQ', dialCode: '+599', label: 'Caribbean Netherlands' },\n { iso2: 'MY', dialCode: '+60', label: 'Malaysia' },\n { iso2: 'AU', dialCode: '+61', label: 'Australia' },\n { iso2: 'CX', dialCode: '+61', label: 'Christmas Island' },\n { iso2: 'CC', dialCode: '+61', label: 'Cocos (Keeling) Islands' },\n { iso2: 'ID', dialCode: '+62', label: 'Indonesia' },\n { iso2: 'PH', dialCode: '+63', label: 'Philippines' },\n { iso2: 'NZ', dialCode: '+64', label: 'New Zealand' },\n { iso2: 'SG', dialCode: '+65', label: 'Singapore' },\n { iso2: 'TH', dialCode: '+66', label: 'Thailand' },\n { iso2: 'TL', dialCode: '+670', label: 'Timor-Leste' },\n { iso2: 'NF', dialCode: '+672', label: 'Norfolk Island' },\n { iso2: 'BN', dialCode: '+673', label: 'Brunei' },\n { iso2: 'NR', dialCode: '+674', label: 'Nauru' },\n { iso2: 'PG', dialCode: '+675', label: 'Papua New Guinea' },\n { iso2: 'TO', dialCode: '+676', label: 'Tonga' },\n { iso2: 'SB', dialCode: '+677', label: 'Solomon Islands' },\n { iso2: 'VU', dialCode: '+678', label: 'Vanuatu' },\n { iso2: 'FJ', dialCode: '+679', label: 'Fiji' },\n { iso2: 'PW', dialCode: '+680', label: 'Palau' },\n { iso2: 'WF', dialCode: '+681', label: 'Wallis and Futuna' },\n { iso2: 'CK', dialCode: '+682', label: 'Cook Islands' },\n { iso2: 'NU', dialCode: '+683', label: 'Niue' },\n { iso2: 'WS', dialCode: '+685', label: 'Samoa' },\n { iso2: 'KI', dialCode: '+686', label: 'Kiribati' },\n { iso2: 'NC', dialCode: '+687', label: 'New Caledonia' },\n { iso2: 'TV', dialCode: '+688', label: 'Tuvalu' },\n { iso2: 'PF', dialCode: '+689', label: 'French Polynesia' },\n { iso2: 'TK', dialCode: '+690', label: 'Tokelau' },\n { iso2: 'FM', dialCode: '+691', label: 'Micronesia' },\n { iso2: 'MH', dialCode: '+692', label: 'Marshall Islands' },\n { iso2: 'RU', dialCode: '+7', label: 'Russia' },\n { iso2: 'KZ', dialCode: '+7', label: 'Kazakhstan' },\n { iso2: 'JP', dialCode: '+81', label: 'Japan' },\n { iso2: 'KR', dialCode: '+82', label: 'South Korea' },\n { iso2: 'VN', dialCode: '+84', label: 'Vietnam' },\n { iso2: 'KP', dialCode: '+850', label: 'North Korea' },\n { iso2: 'HK', dialCode: '+852', label: 'Hong Kong' },\n { iso2: 'MO', dialCode: '+853', label: 'Macau' },\n { iso2: 'KH', dialCode: '+855', label: 'Cambodia' },\n { iso2: 'LA', dialCode: '+856', label: 'Laos' },\n { iso2: 'CN', dialCode: '+86', label: 'China' },\n { iso2: 'BD', dialCode: '+880', label: 'Bangladesh' },\n { iso2: 'TW', dialCode: '+886', label: 'Taiwan' },\n { iso2: 'TR', dialCode: '+90', label: 'Turkey' },\n { iso2: 'IN', dialCode: '+91', label: 'India' },\n { iso2: 'PK', dialCode: '+92', label: 'Pakistan' },\n { iso2: 'AF', dialCode: '+93', label: 'Afghanistan' },\n { iso2: 'LK', dialCode: '+94', label: 'Sri Lanka' },\n { iso2: 'MM', dialCode: '+95', label: 'Myanmar' },\n { iso2: 'MV', dialCode: '+960', label: 'Maldives' },\n { iso2: 'LB', dialCode: '+961', label: 'Lebanon' },\n { iso2: 'JO', dialCode: '+962', label: 'Jordan' },\n { iso2: 'SY', dialCode: '+963', label: 'Syria' },\n { iso2: 'IQ', dialCode: '+964', label: 'Iraq' },\n { iso2: 'KW', dialCode: '+965', label: 'Kuwait' },\n { iso2: 'SA', dialCode: '+966', label: 'Saudi Arabia' },\n { iso2: 'YE', dialCode: '+967', label: 'Yemen' },\n { iso2: 'OM', dialCode: '+968', label: 'Oman' },\n { iso2: 'PS', dialCode: '+970', label: 'Palestine' },\n { iso2: 'AE', dialCode: '+971', label: 'United Arab Emirates' },\n { iso2: 'IL', dialCode: '+972', label: 'Israel' },\n { iso2: 'BH', dialCode: '+973', label: 'Bahrain' },\n { iso2: 'QA', dialCode: '+974', label: 'Qatar' },\n { iso2: 'BT', dialCode: '+975', label: 'Bhutan' },\n { iso2: 'MN', dialCode: '+976', label: 'Mongolia' },\n { iso2: 'NP', dialCode: '+977', label: 'Nepal' },\n { iso2: 'TJ', dialCode: '+992', label: 'Tajikistan' },\n { iso2: 'TM', dialCode: '+993', label: 'Turkmenistan' },\n { iso2: 'AZ', dialCode: '+994', label: 'Azerbaijan' },\n { iso2: 'GE', dialCode: '+995', label: 'Georgia' },\n { iso2: 'KG', dialCode: '+996', label: 'Kyrgyzstan' },\n { iso2: 'UZ', dialCode: '+998', label: 'Uzbekistan' },\n { iso2: 'IR', dialCode: '+98', label: 'Iran' },\n]\n\nexport const PHONE_COUNTRIES: PhoneCountry[] = RAW_PHONE_COUNTRIES\n .map((country) => ({ ...country, flag: iso2ToFlagEmoji(country.iso2) }))\n .sort((a, b) => a.label.localeCompare(b.label, 'en', { sensitivity: 'base' }))\n\n/**\n * Translation key holding a country's display name, e.g.\n * `ui.inputs.phoneNumberField.countryName.PL`. Locale files only need entries\n * for the countries whose platform-provided name a deployment wants to\n * change. This is a distinct namespace from\n * `ui.inputs.phoneNumberField.country` (the picker's trigger label) so a\n * nested locale file can hold both.\n */\nexport function phoneCountryLabelKey(iso2: string): string {\n return `ui.inputs.phoneNumberField.countryName.${iso2.toUpperCase()}`\n}\n\nconst regionDisplayNamesByLocale = new Map<string, Intl.DisplayNames | null>()\n\nfunction getRegionDisplayNames(locale: string): Intl.DisplayNames | null {\n const cached = regionDisplayNamesByLocale.get(locale)\n if (cached !== undefined) return cached\n let displayNames: Intl.DisplayNames | null = null\n try {\n displayNames = new Intl.DisplayNames([locale], { type: 'region' })\n } catch {\n displayNames = null\n }\n regionDisplayNamesByLocale.set(locale, displayNames)\n return displayNames\n}\n\n/**\n * Country name in `locale` from the platform's own region data, or `null` when\n * the runtime cannot name that region (unknown code, trimmed ICU data).\n */\nfunction regionDisplayName(iso2: string, locale: string | undefined): string | null {\n if (!locale) return null\n const code = iso2.toUpperCase()\n if (!/^[A-Z]{2}$/.test(code)) return null\n const displayNames = getRegionDisplayNames(locale)\n if (!displayNames) return null\n try {\n const name = displayNames.of(code)\n return name && name !== code ? name : null\n } catch {\n return null\n }\n}\n\nfunction isEnglishLocale(locale: string | undefined): boolean {\n return !locale || locale.toLowerCase().split(/[-_]/)[0] === 'en'\n}\n\n/**\n * Display name for a built-in country in the active locale. A locale-file entry\n * wins so a deployment can correct or override any name; otherwise the\n * platform's region data localizes it; the English label is the last resort.\n *\n * English deliberately skips the region data: the dictionary already holds\n * curated English names, and CLDR spells several of them differently\n * (\"Antigua & Barbuda\" for \"Antigua and Barbuda\"), so consulting it would\n * silently rewrite existing English copy for no gain.\n */\nexport function resolvePhoneCountryLabel(\n country: PhoneCountry,\n t: TranslateFn,\n locale: string | undefined,\n): string {\n const translated = t(phoneCountryLabelKey(country.iso2), '')\n if (translated) return translated\n if (isEnglishLocale(locale)) return country.label\n return regionDisplayName(country.iso2, locale) ?? country.label\n}\n\nexport type PhoneCountryOption = {\n country: PhoneCountry\n label: string\n}\n\n/**\n * Locale safe to hand to `localeCompare`. A tag `Intl` cannot construct would\n * throw there just as it does in `getRegionDisplayNames`, so both fall back to\n * English together.\n */\nfunction resolveCollationLocale(locale: string | undefined): string {\n if (!locale) return 'en'\n return getRegionDisplayNames(locale) ? locale : 'en'\n}\n\n/**\n * Options rendered in the country dropdown. A caller-supplied list is\n * authoritative \u2014 its labels and its order are preserved verbatim \u2014 while the\n * built-in dictionary is localized and re-sorted for the active locale, since\n * its module-level ordering is alphabetical by the English name.\n */\nexport function buildPhoneCountryOptions(\n countries: PhoneCountry[] | undefined,\n t: TranslateFn,\n locale: string | undefined,\n): PhoneCountryOption[] {\n if (countries) return countries.map((country) => ({ country, label: country.label }))\n const collationLocale = resolveCollationLocale(locale)\n return PHONE_COUNTRIES\n .map((country) => ({ country, label: resolvePhoneCountryLabel(country, t, locale) }))\n .sort((a, b) => a.label.localeCompare(b.label, collationLocale, { sensitivity: 'base' }))\n}\n\n/**\n * Sovereign/primary country that wins auto-detection for a calling code shared\n * by several territories. US vs. Canada is the one irreducible ambiguity \u2014 both\n * are `+1` \u2014 and it resolves to the US.\n */\nconst PRIMARY_DIAL_OWNERS: Record<string, string> = {\n '+1': 'US',\n '+7': 'RU',\n '+44': 'GB',\n '+47': 'NO',\n '+61': 'AU',\n '+212': 'MA',\n '+262': 'RE',\n '+358': 'FI',\n '+590': 'GP',\n '+599': 'CW',\n}\n\nconst DEFAULT_COUNTRY =\n PHONE_COUNTRIES.find((country) => country.iso2 === 'US') ?? PHONE_COUNTRIES[0]\n\n// Match longer prefixes first (e.g. `+1242` before `+1`); for equal-length codes\n// shared by several territories, prefer the sovereign in `PRIMARY_DIAL_OWNERS`.\nconst COUNTRIES_BY_DIAL_LENGTH = [...PHONE_COUNTRIES].sort((a, b) => {\n if (b.dialCode.length !== a.dialCode.length) return b.dialCode.length - a.dialCode.length\n const aPrimary = PRIMARY_DIAL_OWNERS[a.dialCode] === a.iso2 ? 0 : 1\n const bPrimary = PRIMARY_DIAL_OWNERS[b.dialCode] === b.iso2 ? 0 : 1\n return aPrimary - bPrimary\n})\n\nfunction findCountryByIso(iso2: string): PhoneCountry | undefined {\n return PHONE_COUNTRIES.find((c) => c.iso2 === iso2)\n}\n\nfunction parseCountryFromValue(value: string | null | undefined): PhoneCountry | null {\n if (!value) return null\n const trimmed = value.trim()\n if (!trimmed.startsWith('+')) return null\n for (const country of COUNTRIES_BY_DIAL_LENGTH) {\n if (trimmed.startsWith(country.dialCode)) return country\n }\n return null\n}\n\nfunction extractLocalNumber(value: string | null | undefined, dialCode: string): string {\n if (!value) return ''\n const trimmed = value.trim()\n if (!trimmed.startsWith(dialCode)) return trimmed\n return trimmed.slice(dialCode.length).trim()\n}\n\nfunction composeValue(country: PhoneCountry, localNumber: string): string {\n const trimmed = localNumber.trim()\n if (!trimmed) return ''\n if (trimmed.startsWith('+')) return trimmed\n return `${country.dialCode} ${trimmed}`\n}\n\nexport type PhoneNumberFieldProps = {\n id?: string\n value?: string | null\n onValueChange: (next: string | undefined) => void\n onDigitsChange?: (digits: string | null) => void\n externalError?: string | null\n disabled?: boolean\n autoFocus?: boolean\n ariaLabel?: string\n ariaDescribedBy?: string\n placeholder?: string\n minDigits?: number\n checkingLabel?: string\n duplicateLabel?: (match: PhoneDuplicateMatch) => string\n duplicateLinkLabel?: string\n invalidLabel?: string\n onDuplicateLookup?: (normalizedValue: string) => Promise<PhoneDuplicateMatch | null>\n /**\n * Override the static country list (e.g. limit to specific markets, or supply\n * names already translated by the host). Both the labels and the order of the\n * supplied list are rendered verbatim.\n */\n countries?: PhoneCountry[]\n /** Initial country shown when `value` is empty / unparseable. Defaults to US. */\n defaultCountryIso2?: string\n size?: 32 | 36 | 40\n countryLabel?: string\n renderCountryIcon?: (country: PhoneCountry) => React.ReactNode\n}\n\nconst DEFAULT_MIN_DIGITS = 6\nconst DEFAULT_PLACEHOLDER = '(555) 000-0000'\n\nexport function PhoneNumberField({\n id,\n value,\n onValueChange,\n onDigitsChange,\n externalError,\n disabled = false,\n autoFocus,\n ariaLabel,\n ariaDescribedBy,\n placeholder,\n minDigits = DEFAULT_MIN_DIGITS,\n checkingLabel,\n duplicateLabel,\n duplicateLinkLabel,\n invalidLabel,\n onDuplicateLookup,\n countries: countriesProp,\n defaultCountryIso2,\n size,\n countryLabel,\n renderCountryIcon,\n}: PhoneNumberFieldProps) {\n const t = useT()\n const locale = useOptionalLocale()\n const resolvedInvalidLabel = invalidLabel ?? t(\n 'ui.inputs.phoneNumberField.invalid',\n 'Enter a valid phone number with country code (e.g. +1 212 555 1234)'\n )\n const resolvedCheckingLabel = checkingLabel ?? t(\n 'ui.inputs.phoneNumberField.checking',\n 'Checking for duplicates\u2026'\n )\n const resolvedDuplicateLinkLabel = duplicateLinkLabel ?? t(\n 'ui.inputs.phoneNumberField.duplicateLink',\n 'Open record'\n )\n const resolvedPlaceholder = placeholder ?? DEFAULT_PLACEHOLDER\n const countryOptions = React.useMemo(\n () => buildPhoneCountryOptions(countriesProp, t, locale),\n [countriesProp, t, locale],\n )\n const fallbackCountry = React.useMemo(\n () => (defaultCountryIso2 && findCountryByIso(defaultCountryIso2)) || DEFAULT_COUNTRY,\n [defaultCountryIso2],\n )\n\n const initialCountry = React.useMemo(\n () => parseCountryFromValue(value) ?? fallbackCountry,\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [],\n )\n const [country, setCountry] = React.useState<PhoneCountry>(initialCountry)\n const [localNumber, setLocalNumber] = React.useState<string>(() =>\n extractLocalNumber(value, initialCountry.dialCode),\n )\n const [duplicate, setDuplicate] = React.useState<PhoneDuplicateMatch | null>(null)\n const [checking, setChecking] = React.useState(false)\n const [validationHint, setValidationHint] = React.useState<string | null>(null)\n const [focused, setFocused] = React.useState(false)\n const userEditingRef = React.useRef(false)\n\n const externalFieldError = externalError && externalError.trim().length > 0 ? externalError : null\n const errorMessage = externalFieldError ?? validationHint\n const errorId = errorMessage && id ? `${id}-error` : undefined\n const describedBy = [ariaDescribedBy, errorId].filter((part): part is string => Boolean(part)).join(' ') || undefined\n const composedValue = composeValue(country, localNumber)\n\n // Sync local state when `value` updates externally and the user is not editing.\n React.useEffect(() => {\n if (userEditingRef.current) return\n if (value == null || value === '') {\n setLocalNumber('')\n onDigitsChange?.(null)\n return\n }\n const parsed = parseCountryFromValue(value)\n if (parsed) setCountry(parsed)\n const next = extractLocalNumber(value, parsed?.dialCode ?? country.dialCode)\n setLocalNumber(next)\n onDigitsChange?.(extractPhoneDigits(String(value)) || null)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [value])\n\n // Debounced duplicate lookup.\n React.useEffect(() => {\n if (!onDuplicateLookup || disabled) {\n setDuplicate(null)\n setChecking(false)\n return\n }\n const digits = extractPhoneDigits(composedValue)\n if (!digits || digits.length < minDigits) {\n setDuplicate(null)\n setChecking(false)\n return\n }\n\n let cancelled = false\n setChecking(true)\n const handle = window.setTimeout(async () => {\n try {\n const match = await onDuplicateLookup(digits)\n if (!cancelled) setDuplicate(match)\n } catch {\n if (!cancelled) setDuplicate(null)\n } finally {\n if (!cancelled) setChecking(false)\n }\n }, 350)\n\n return () => {\n cancelled = true\n window.clearTimeout(handle)\n }\n }, [composedValue, disabled, minDigits, onDuplicateLookup])\n\n const emit = React.useCallback(\n (nextCountry: PhoneCountry, nextLocal: string) => {\n const composed = composeValue(nextCountry, nextLocal)\n onValueChange(composed.length ? composed : undefined)\n onDigitsChange?.(extractPhoneDigits(composed) || null)\n },\n [onDigitsChange, onValueChange],\n )\n\n const handleCountryChange = React.useCallback(\n (iso2: string) => {\n const next = findCountryByIso(iso2)\n if (!next) return\n userEditingRef.current = true\n setCountry(next)\n setValidationHint(null)\n emit(next, localNumber)\n },\n [emit, localNumber],\n )\n\n const handleLocalChange = React.useCallback(\n (event: React.ChangeEvent<HTMLInputElement>) => {\n const next = event.target.value\n userEditingRef.current = true\n setLocalNumber(next)\n setValidationHint(null)\n emit(country, next)\n },\n [country, emit],\n )\n\n const handleBlur = React.useCallback(() => {\n userEditingRef.current = false\n setFocused(false)\n const trimmed = localNumber.trim()\n if (!trimmed) {\n setLocalNumber('')\n setValidationHint(null)\n onValueChange(undefined)\n onDigitsChange?.(null)\n return\n }\n const composed = composeValue(country, trimmed)\n const result = validatePhoneNumber(composed)\n if (result.valid) {\n const normalizedLocal = extractLocalNumber(result.normalized ?? composed, country.dialCode)\n setLocalNumber(normalizedLocal)\n setValidationHint(null)\n onValueChange(result.normalized || undefined)\n onDigitsChange?.(result.digits || null)\n } else {\n setValidationHint(resolvedInvalidLabel)\n onValueChange(composed)\n onDigitsChange?.(result.digits || null)\n }\n }, [country, localNumber, onDigitsChange, onValueChange, resolvedInvalidLabel])\n\n const containerErrorBorder = errorMessage ? 'border-status-error-icon' : 'border-input'\n const containerFocusBorder = errorMessage\n ? 'border-status-error-icon shadow-focus'\n : 'border-brand-violet shadow-focus'\n\n return (\n <div className=\"space-y-2\">\n <div\n className={cn(\n 'flex items-stretch w-full rounded-md border bg-background shadow-xs transition-colors',\n size === 32 && 'h-8',\n size === 36 && 'h-9',\n size === 40 && 'h-10 rounded-lg',\n disabled\n ? 'bg-bg-disabled border-border-disabled cursor-not-allowed'\n : focused\n ? containerFocusBorder\n : `${containerErrorBorder} hover:border-foreground/30`,\n )}\n aria-invalid={errorMessage ? 'true' : undefined}\n data-slot=\"phone-input-wrapper\"\n >\n <Select value={country.iso2} onValueChange={handleCountryChange} disabled={disabled}>\n <SelectTrigger\n aria-label={countryLabel ?? (ariaLabel ? `${ariaLabel} country` : t('ui.inputs.phoneNumberField.country', 'Country code'))}\n size={size}\n className={cn(\n 'h-auto w-auto shrink-0 gap-1.5 rounded-none rounded-l-md border-0 bg-transparent px-2.5 py-2 shadow-none',\n 'hover:bg-muted/40 focus:bg-muted/40 focus-visible:shadow-none focus-visible:border-0',\n 'disabled:bg-transparent disabled:hover:bg-transparent',\n size && 'h-full gap-2 rounded-l-none py-0 pl-2.5 pr-2 [&>svg]:size-5',\n size === 32 && 'pl-1.5 pr-1',\n )}\n onFocus={() => setFocused(true)}\n onBlur={() => setFocused(false)}\n >\n <span className={cn('text-base leading-none', size && 'inline-flex size-5 shrink-0 items-center justify-center text-xl [&_img]:size-full')} aria-hidden=\"true\">{renderCountryIcon ? renderCountryIcon(country) : country.flag}</span>\n <span className={cn(\"text-sm text-foreground tabular-nums\", disabled && \"text-text-disabled\")}>{country.dialCode}</span>\n </SelectTrigger>\n <SelectContent align=\"start\">\n {countryOptions.map(({ country: c, label }) => (\n <SelectItem key={`${c.iso2}-${c.dialCode}`} value={c.iso2} textValue={label}>\n <SelectItemLeading>\n <span className=\"text-base leading-none\">{c.flag}</span>\n </SelectItemLeading>\n <span className=\"flex-1 truncate\">{label}</span>\n <span className=\"ml-2 text-xs text-muted-foreground tabular-nums\">{c.dialCode}</span>\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <div aria-hidden=\"true\" className=\"w-px self-stretch bg-input\" />\n <input\n type=\"tel\"\n inputMode=\"tel\"\n autoComplete=\"tel-national\"\n value={localNumber}\n onChange={handleLocalChange}\n onBlur={handleBlur}\n onFocus={() => setFocused(true)}\n placeholder={resolvedPlaceholder}\n autoFocus={autoFocus}\n disabled={disabled}\n id={id}\n aria-label={ariaLabel}\n aria-describedby={describedBy}\n aria-invalid={errorMessage ? 'true' : undefined}\n data-crud-focus-target=\"\"\n className={cn(\n 'flex-1 min-w-0 bg-transparent px-3 py-2 text-sm leading-5 outline-none',\n 'placeholder:text-muted-foreground',\n 'disabled:cursor-not-allowed disabled:text-text-disabled disabled:placeholder:text-text-disabled',\n size && 'h-full py-0 pr-2.5',\n size === 32 && 'pl-2 pr-1.5',\n )}\n />\n </div>\n {errorMessage ? (\n <p id={errorId} role=\"alert\" className=\"text-xs text-status-error-text\">{errorMessage}</p>\n ) : null}\n {!disabled && duplicate && duplicateLabel ? (\n <p className=\"text-xs text-status-warning-text\">\n {duplicateLabel(duplicate)}{' '}\n <a className=\"font-medium text-brand-violet underline underline-offset-2\" href={duplicate.href}>\n {resolvedDuplicateLinkLabel}\n </a>\n </p>\n ) : null}\n {!disabled && !duplicate && checking ? (\n <p className=\"text-xs text-muted-foreground\">{resolvedCheckingLabel}</p>\n ) : null}\n </div>\n )\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useOptionalLocale, useT, type TranslateFn } from '@open-mercato/shared/lib/i18n/context'\nimport { extractPhoneDigits, validatePhoneNumber } from '@open-mercato/shared/lib/phone'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectItemLeading,\n SelectTrigger,\n} from '../../primitives/select'\n\nexport type PhoneDuplicateMatch = {\n id: string\n label: string\n href: string\n}\n\nexport type PhoneCountry = {\n /** ISO 3166-1 alpha-2 code. */\n iso2: string\n /** International dial code (with `+`). */\n dialCode: string\n /**\n * Human-readable country name (English). Used as the last-resort fallback\n * when neither a locale file nor the platform's region data can name the\n * country in the active locale.\n */\n label: string\n /** Emoji flag (no asset dependency). */\n flag: string\n}\n\n/**\n * Emoji flag for an ISO 3166-1 alpha-2 code, assembled from the two regional\n * indicator symbols. Deriving it keeps the (large) dictionary free of hand-typed\n * emoji and guarantees the flag always matches the code.\n */\nfunction iso2ToFlagEmoji(iso2: string): string {\n const letters = iso2.toUpperCase().replace(/[^A-Z]/g, '')\n if (letters.length !== 2) return ''\n const base = 0x1f1e6\n return String.fromCodePoint(\n base + letters.charCodeAt(0) - 65,\n base + letters.charCodeAt(1) - 65,\n )\n}\n\n/**\n * Complete static dictionary of geographic countries and territories that have\n * an ISO 3166-1 alpha-2 code and an international calling code, based on the\n * ITU / Wikipedia list of telephone country codes.\n *\n * Rules baked into this data:\n * - Labels are English; flags are derived from the ISO code (`iso2ToFlagEmoji`).\n * - Non-geographic / international service codes (`+800`, `+808`, `+870`,\n * `+881`, `+882`, \u2026) are intentionally excluded.\n * - North American Numbering Plan territories carry their full `+1<NPA>` dial\n * code (e.g. Bahamas `+1242`) so longest-prefix matching resolves them before\n * the generic `+1`. The US and Canada BOTH use a bare `+1` and cannot be told\n * apart from the prefix alone \u2014 auto-detection favours the US.\n * - Several sovereign countries share a calling code with dependent territories\n * (e.g. `+44` UK/Guernsey/Jersey/Isle of Man); `PRIMARY_DIAL_OWNERS` records\n * the country that wins auto-detection for those shared codes.\n */\nconst RAW_PHONE_COUNTRIES: Array<Omit<PhoneCountry, 'flag'>> = [\n { iso2: 'US', dialCode: '+1', label: 'United States' },\n { iso2: 'CA', dialCode: '+1', label: 'Canada' },\n { iso2: 'AG', dialCode: '+1268', label: 'Antigua and Barbuda' },\n { iso2: 'AI', dialCode: '+1264', label: 'Anguilla' },\n { iso2: 'AS', dialCode: '+1684', label: 'American Samoa' },\n { iso2: 'BB', dialCode: '+1246', label: 'Barbados' },\n { iso2: 'BM', dialCode: '+1441', label: 'Bermuda' },\n { iso2: 'BS', dialCode: '+1242', label: 'Bahamas' },\n { iso2: 'DM', dialCode: '+1767', label: 'Dominica' },\n { iso2: 'DO', dialCode: '+1809', label: 'Dominican Republic' },\n { iso2: 'GD', dialCode: '+1473', label: 'Grenada' },\n { iso2: 'GU', dialCode: '+1671', label: 'Guam' },\n { iso2: 'JM', dialCode: '+1876', label: 'Jamaica' },\n { iso2: 'KN', dialCode: '+1869', label: 'Saint Kitts and Nevis' },\n { iso2: 'KY', dialCode: '+1345', label: 'Cayman Islands' },\n { iso2: 'LC', dialCode: '+1758', label: 'Saint Lucia' },\n { iso2: 'MP', dialCode: '+1670', label: 'Northern Mariana Islands' },\n { iso2: 'MS', dialCode: '+1664', label: 'Montserrat' },\n { iso2: 'PR', dialCode: '+1787', label: 'Puerto Rico' },\n { iso2: 'SX', dialCode: '+1721', label: 'Sint Maarten' },\n { iso2: 'TC', dialCode: '+1649', label: 'Turks and Caicos Islands' },\n { iso2: 'TT', dialCode: '+1868', label: 'Trinidad and Tobago' },\n { iso2: 'VC', dialCode: '+1784', label: 'Saint Vincent and the Grenadines' },\n { iso2: 'VG', dialCode: '+1284', label: 'British Virgin Islands' },\n { iso2: 'VI', dialCode: '+1340', label: 'U.S. Virgin Islands' },\n { iso2: 'EG', dialCode: '+20', label: 'Egypt' },\n { iso2: 'SS', dialCode: '+211', label: 'South Sudan' },\n { iso2: 'MA', dialCode: '+212', label: 'Morocco' },\n { iso2: 'EH', dialCode: '+212', label: 'Western Sahara' },\n { iso2: 'DZ', dialCode: '+213', label: 'Algeria' },\n { iso2: 'TN', dialCode: '+216', label: 'Tunisia' },\n { iso2: 'LY', dialCode: '+218', label: 'Libya' },\n { iso2: 'GM', dialCode: '+220', label: 'Gambia' },\n { iso2: 'SN', dialCode: '+221', label: 'Senegal' },\n { iso2: 'MR', dialCode: '+222', label: 'Mauritania' },\n { iso2: 'ML', dialCode: '+223', label: 'Mali' },\n { iso2: 'GN', dialCode: '+224', label: 'Guinea' },\n { iso2: 'CI', dialCode: '+225', label: \"C\u00F4te d'Ivoire\" },\n { iso2: 'BF', dialCode: '+226', label: 'Burkina Faso' },\n { iso2: 'NE', dialCode: '+227', label: 'Niger' },\n { iso2: 'TG', dialCode: '+228', label: 'Togo' },\n { iso2: 'BJ', dialCode: '+229', label: 'Benin' },\n { iso2: 'MU', dialCode: '+230', label: 'Mauritius' },\n { iso2: 'LR', dialCode: '+231', label: 'Liberia' },\n { iso2: 'SL', dialCode: '+232', label: 'Sierra Leone' },\n { iso2: 'GH', dialCode: '+233', label: 'Ghana' },\n { iso2: 'NG', dialCode: '+234', label: 'Nigeria' },\n { iso2: 'TD', dialCode: '+235', label: 'Chad' },\n { iso2: 'CF', dialCode: '+236', label: 'Central African Republic' },\n { iso2: 'CM', dialCode: '+237', label: 'Cameroon' },\n { iso2: 'CV', dialCode: '+238', label: 'Cape Verde' },\n { iso2: 'ST', dialCode: '+239', label: 'S\u00E3o Tom\u00E9 and Pr\u00EDncipe' },\n { iso2: 'GQ', dialCode: '+240', label: 'Equatorial Guinea' },\n { iso2: 'GA', dialCode: '+241', label: 'Gabon' },\n { iso2: 'CG', dialCode: '+242', label: 'Republic of the Congo' },\n { iso2: 'CD', dialCode: '+243', label: 'DR Congo' },\n { iso2: 'AO', dialCode: '+244', label: 'Angola' },\n { iso2: 'GW', dialCode: '+245', label: 'Guinea-Bissau' },\n { iso2: 'IO', dialCode: '+246', label: 'British Indian Ocean Territory' },\n { iso2: 'SC', dialCode: '+248', label: 'Seychelles' },\n { iso2: 'SD', dialCode: '+249', label: 'Sudan' },\n { iso2: 'RW', dialCode: '+250', label: 'Rwanda' },\n { iso2: 'ET', dialCode: '+251', label: 'Ethiopia' },\n { iso2: 'SO', dialCode: '+252', label: 'Somalia' },\n { iso2: 'DJ', dialCode: '+253', label: 'Djibouti' },\n { iso2: 'KE', dialCode: '+254', label: 'Kenya' },\n { iso2: 'TZ', dialCode: '+255', label: 'Tanzania' },\n { iso2: 'UG', dialCode: '+256', label: 'Uganda' },\n { iso2: 'BI', dialCode: '+257', label: 'Burundi' },\n { iso2: 'MZ', dialCode: '+258', label: 'Mozambique' },\n { iso2: 'ZM', dialCode: '+260', label: 'Zambia' },\n { iso2: 'MG', dialCode: '+261', label: 'Madagascar' },\n { iso2: 'RE', dialCode: '+262', label: 'R\u00E9union' },\n { iso2: 'YT', dialCode: '+262', label: 'Mayotte' },\n { iso2: 'ZW', dialCode: '+263', label: 'Zimbabwe' },\n { iso2: 'NA', dialCode: '+264', label: 'Namibia' },\n { iso2: 'MW', dialCode: '+265', label: 'Malawi' },\n { iso2: 'LS', dialCode: '+266', label: 'Lesotho' },\n { iso2: 'BW', dialCode: '+267', label: 'Botswana' },\n { iso2: 'SZ', dialCode: '+268', label: 'Eswatini' },\n { iso2: 'KM', dialCode: '+269', label: 'Comoros' },\n { iso2: 'ZA', dialCode: '+27', label: 'South Africa' },\n { iso2: 'SH', dialCode: '+290', label: 'Saint Helena' },\n { iso2: 'ER', dialCode: '+291', label: 'Eritrea' },\n { iso2: 'AW', dialCode: '+297', label: 'Aruba' },\n { iso2: 'FO', dialCode: '+298', label: 'Faroe Islands' },\n { iso2: 'GL', dialCode: '+299', label: 'Greenland' },\n { iso2: 'GR', dialCode: '+30', label: 'Greece' },\n { iso2: 'NL', dialCode: '+31', label: 'Netherlands' },\n { iso2: 'BE', dialCode: '+32', label: 'Belgium' },\n { iso2: 'FR', dialCode: '+33', label: 'France' },\n { iso2: 'ES', dialCode: '+34', label: 'Spain' },\n { iso2: 'GI', dialCode: '+350', label: 'Gibraltar' },\n { iso2: 'PT', dialCode: '+351', label: 'Portugal' },\n { iso2: 'LU', dialCode: '+352', label: 'Luxembourg' },\n { iso2: 'IE', dialCode: '+353', label: 'Ireland' },\n { iso2: 'IS', dialCode: '+354', label: 'Iceland' },\n { iso2: 'AL', dialCode: '+355', label: 'Albania' },\n { iso2: 'MT', dialCode: '+356', label: 'Malta' },\n { iso2: 'CY', dialCode: '+357', label: 'Cyprus' },\n { iso2: 'FI', dialCode: '+358', label: 'Finland' },\n { iso2: 'AX', dialCode: '+358', label: '\u00C5land Islands' },\n { iso2: 'BG', dialCode: '+359', label: 'Bulgaria' },\n { iso2: 'HU', dialCode: '+36', label: 'Hungary' },\n { iso2: 'LT', dialCode: '+370', label: 'Lithuania' },\n { iso2: 'LV', dialCode: '+371', label: 'Latvia' },\n { iso2: 'EE', dialCode: '+372', label: 'Estonia' },\n { iso2: 'MD', dialCode: '+373', label: 'Moldova' },\n { iso2: 'AM', dialCode: '+374', label: 'Armenia' },\n { iso2: 'BY', dialCode: '+375', label: 'Belarus' },\n { iso2: 'AD', dialCode: '+376', label: 'Andorra' },\n { iso2: 'MC', dialCode: '+377', label: 'Monaco' },\n { iso2: 'SM', dialCode: '+378', label: 'San Marino' },\n { iso2: 'VA', dialCode: '+379', label: 'Vatican City' },\n { iso2: 'UA', dialCode: '+380', label: 'Ukraine' },\n { iso2: 'RS', dialCode: '+381', label: 'Serbia' },\n { iso2: 'ME', dialCode: '+382', label: 'Montenegro' },\n { iso2: 'XK', dialCode: '+383', label: 'Kosovo' },\n { iso2: 'HR', dialCode: '+385', label: 'Croatia' },\n { iso2: 'SI', dialCode: '+386', label: 'Slovenia' },\n { iso2: 'BA', dialCode: '+387', label: 'Bosnia and Herzegovina' },\n { iso2: 'MK', dialCode: '+389', label: 'North Macedonia' },\n { iso2: 'IT', dialCode: '+39', label: 'Italy' },\n { iso2: 'RO', dialCode: '+40', label: 'Romania' },\n { iso2: 'CH', dialCode: '+41', label: 'Switzerland' },\n { iso2: 'CZ', dialCode: '+420', label: 'Czechia' },\n { iso2: 'SK', dialCode: '+421', label: 'Slovakia' },\n { iso2: 'LI', dialCode: '+423', label: 'Liechtenstein' },\n { iso2: 'AT', dialCode: '+43', label: 'Austria' },\n { iso2: 'GB', dialCode: '+44', label: 'United Kingdom' },\n { iso2: 'GG', dialCode: '+44', label: 'Guernsey' },\n { iso2: 'JE', dialCode: '+44', label: 'Jersey' },\n { iso2: 'IM', dialCode: '+44', label: 'Isle of Man' },\n { iso2: 'DK', dialCode: '+45', label: 'Denmark' },\n { iso2: 'SE', dialCode: '+46', label: 'Sweden' },\n { iso2: 'NO', dialCode: '+47', label: 'Norway' },\n { iso2: 'SJ', dialCode: '+47', label: 'Svalbard and Jan Mayen' },\n { iso2: 'PL', dialCode: '+48', label: 'Poland' },\n { iso2: 'DE', dialCode: '+49', label: 'Germany' },\n { iso2: 'FK', dialCode: '+500', label: 'Falkland Islands' },\n { iso2: 'BZ', dialCode: '+501', label: 'Belize' },\n { iso2: 'GT', dialCode: '+502', label: 'Guatemala' },\n { iso2: 'SV', dialCode: '+503', label: 'El Salvador' },\n { iso2: 'HN', dialCode: '+504', label: 'Honduras' },\n { iso2: 'NI', dialCode: '+505', label: 'Nicaragua' },\n { iso2: 'CR', dialCode: '+506', label: 'Costa Rica' },\n { iso2: 'PA', dialCode: '+507', label: 'Panama' },\n { iso2: 'PM', dialCode: '+508', label: 'Saint Pierre and Miquelon' },\n { iso2: 'HT', dialCode: '+509', label: 'Haiti' },\n { iso2: 'PE', dialCode: '+51', label: 'Peru' },\n { iso2: 'MX', dialCode: '+52', label: 'Mexico' },\n { iso2: 'CU', dialCode: '+53', label: 'Cuba' },\n { iso2: 'AR', dialCode: '+54', label: 'Argentina' },\n { iso2: 'BR', dialCode: '+55', label: 'Brazil' },\n { iso2: 'CL', dialCode: '+56', label: 'Chile' },\n { iso2: 'CO', dialCode: '+57', label: 'Colombia' },\n { iso2: 'VE', dialCode: '+58', label: 'Venezuela' },\n { iso2: 'GP', dialCode: '+590', label: 'Guadeloupe' },\n { iso2: 'BL', dialCode: '+590', label: 'Saint Barth\u00E9lemy' },\n { iso2: 'MF', dialCode: '+590', label: 'Saint Martin' },\n { iso2: 'BO', dialCode: '+591', label: 'Bolivia' },\n { iso2: 'GY', dialCode: '+592', label: 'Guyana' },\n { iso2: 'EC', dialCode: '+593', label: 'Ecuador' },\n { iso2: 'GF', dialCode: '+594', label: 'French Guiana' },\n { iso2: 'PY', dialCode: '+595', label: 'Paraguay' },\n { iso2: 'MQ', dialCode: '+596', label: 'Martinique' },\n { iso2: 'SR', dialCode: '+597', label: 'Suriname' },\n { iso2: 'UY', dialCode: '+598', label: 'Uruguay' },\n { iso2: 'CW', dialCode: '+599', label: 'Cura\u00E7ao' },\n { iso2: 'BQ', dialCode: '+599', label: 'Caribbean Netherlands' },\n { iso2: 'MY', dialCode: '+60', label: 'Malaysia' },\n { iso2: 'AU', dialCode: '+61', label: 'Australia' },\n { iso2: 'CX', dialCode: '+61', label: 'Christmas Island' },\n { iso2: 'CC', dialCode: '+61', label: 'Cocos (Keeling) Islands' },\n { iso2: 'ID', dialCode: '+62', label: 'Indonesia' },\n { iso2: 'PH', dialCode: '+63', label: 'Philippines' },\n { iso2: 'NZ', dialCode: '+64', label: 'New Zealand' },\n { iso2: 'SG', dialCode: '+65', label: 'Singapore' },\n { iso2: 'TH', dialCode: '+66', label: 'Thailand' },\n { iso2: 'TL', dialCode: '+670', label: 'Timor-Leste' },\n { iso2: 'NF', dialCode: '+672', label: 'Norfolk Island' },\n { iso2: 'BN', dialCode: '+673', label: 'Brunei' },\n { iso2: 'NR', dialCode: '+674', label: 'Nauru' },\n { iso2: 'PG', dialCode: '+675', label: 'Papua New Guinea' },\n { iso2: 'TO', dialCode: '+676', label: 'Tonga' },\n { iso2: 'SB', dialCode: '+677', label: 'Solomon Islands' },\n { iso2: 'VU', dialCode: '+678', label: 'Vanuatu' },\n { iso2: 'FJ', dialCode: '+679', label: 'Fiji' },\n { iso2: 'PW', dialCode: '+680', label: 'Palau' },\n { iso2: 'WF', dialCode: '+681', label: 'Wallis and Futuna' },\n { iso2: 'CK', dialCode: '+682', label: 'Cook Islands' },\n { iso2: 'NU', dialCode: '+683', label: 'Niue' },\n { iso2: 'WS', dialCode: '+685', label: 'Samoa' },\n { iso2: 'KI', dialCode: '+686', label: 'Kiribati' },\n { iso2: 'NC', dialCode: '+687', label: 'New Caledonia' },\n { iso2: 'TV', dialCode: '+688', label: 'Tuvalu' },\n { iso2: 'PF', dialCode: '+689', label: 'French Polynesia' },\n { iso2: 'TK', dialCode: '+690', label: 'Tokelau' },\n { iso2: 'FM', dialCode: '+691', label: 'Micronesia' },\n { iso2: 'MH', dialCode: '+692', label: 'Marshall Islands' },\n { iso2: 'RU', dialCode: '+7', label: 'Russia' },\n { iso2: 'KZ', dialCode: '+7', label: 'Kazakhstan' },\n { iso2: 'JP', dialCode: '+81', label: 'Japan' },\n { iso2: 'KR', dialCode: '+82', label: 'South Korea' },\n { iso2: 'VN', dialCode: '+84', label: 'Vietnam' },\n { iso2: 'KP', dialCode: '+850', label: 'North Korea' },\n { iso2: 'HK', dialCode: '+852', label: 'Hong Kong' },\n { iso2: 'MO', dialCode: '+853', label: 'Macau' },\n { iso2: 'KH', dialCode: '+855', label: 'Cambodia' },\n { iso2: 'LA', dialCode: '+856', label: 'Laos' },\n { iso2: 'CN', dialCode: '+86', label: 'China' },\n { iso2: 'BD', dialCode: '+880', label: 'Bangladesh' },\n { iso2: 'TW', dialCode: '+886', label: 'Taiwan' },\n { iso2: 'TR', dialCode: '+90', label: 'Turkey' },\n { iso2: 'IN', dialCode: '+91', label: 'India' },\n { iso2: 'PK', dialCode: '+92', label: 'Pakistan' },\n { iso2: 'AF', dialCode: '+93', label: 'Afghanistan' },\n { iso2: 'LK', dialCode: '+94', label: 'Sri Lanka' },\n { iso2: 'MM', dialCode: '+95', label: 'Myanmar' },\n { iso2: 'MV', dialCode: '+960', label: 'Maldives' },\n { iso2: 'LB', dialCode: '+961', label: 'Lebanon' },\n { iso2: 'JO', dialCode: '+962', label: 'Jordan' },\n { iso2: 'SY', dialCode: '+963', label: 'Syria' },\n { iso2: 'IQ', dialCode: '+964', label: 'Iraq' },\n { iso2: 'KW', dialCode: '+965', label: 'Kuwait' },\n { iso2: 'SA', dialCode: '+966', label: 'Saudi Arabia' },\n { iso2: 'YE', dialCode: '+967', label: 'Yemen' },\n { iso2: 'OM', dialCode: '+968', label: 'Oman' },\n { iso2: 'PS', dialCode: '+970', label: 'Palestine' },\n { iso2: 'AE', dialCode: '+971', label: 'United Arab Emirates' },\n { iso2: 'IL', dialCode: '+972', label: 'Israel' },\n { iso2: 'BH', dialCode: '+973', label: 'Bahrain' },\n { iso2: 'QA', dialCode: '+974', label: 'Qatar' },\n { iso2: 'BT', dialCode: '+975', label: 'Bhutan' },\n { iso2: 'MN', dialCode: '+976', label: 'Mongolia' },\n { iso2: 'NP', dialCode: '+977', label: 'Nepal' },\n { iso2: 'TJ', dialCode: '+992', label: 'Tajikistan' },\n { iso2: 'TM', dialCode: '+993', label: 'Turkmenistan' },\n { iso2: 'AZ', dialCode: '+994', label: 'Azerbaijan' },\n { iso2: 'GE', dialCode: '+995', label: 'Georgia' },\n { iso2: 'KG', dialCode: '+996', label: 'Kyrgyzstan' },\n { iso2: 'UZ', dialCode: '+998', label: 'Uzbekistan' },\n { iso2: 'IR', dialCode: '+98', label: 'Iran' },\n]\n\nexport const PHONE_COUNTRIES: PhoneCountry[] = RAW_PHONE_COUNTRIES\n .map((country) => ({ ...country, flag: iso2ToFlagEmoji(country.iso2) }))\n .sort((a, b) => a.label.localeCompare(b.label, 'en', { sensitivity: 'base' }))\n\n/**\n * Translation key holding a country's display name, e.g.\n * `ui.inputs.phoneNumberField.countryName.PL`. Locale files only need entries\n * for the countries whose platform-provided name a deployment wants to\n * change. This is a distinct namespace from\n * `ui.inputs.phoneNumberField.country` (the picker's trigger label) so a\n * nested locale file can hold both.\n */\nexport function phoneCountryLabelKey(iso2: string): string {\n return `ui.inputs.phoneNumberField.countryName.${iso2.toUpperCase()}`\n}\n\nconst regionDisplayNamesByLocale = new Map<string, Intl.DisplayNames | null>()\n\nfunction getRegionDisplayNames(locale: string): Intl.DisplayNames | null {\n const cached = regionDisplayNamesByLocale.get(locale)\n if (cached !== undefined) return cached\n let displayNames: Intl.DisplayNames | null = null\n try {\n displayNames = new Intl.DisplayNames([locale], { type: 'region' })\n } catch {\n displayNames = null\n }\n regionDisplayNamesByLocale.set(locale, displayNames)\n return displayNames\n}\n\n/**\n * Country name in `locale` from the platform's own region data, or `null` when\n * the runtime cannot name that region (unknown code, trimmed ICU data).\n */\nfunction regionDisplayName(iso2: string, locale: string | undefined): string | null {\n if (!locale) return null\n const code = iso2.toUpperCase()\n if (!/^[A-Z]{2}$/.test(code)) return null\n const displayNames = getRegionDisplayNames(locale)\n if (!displayNames) return null\n try {\n const name = displayNames.of(code)\n return name && name !== code ? name : null\n } catch {\n return null\n }\n}\n\nfunction isEnglishLocale(locale: string | undefined): boolean {\n return !locale || locale.toLowerCase().split(/[-_]/)[0] === 'en'\n}\n\n/**\n * Display name for a built-in country in the active locale. A locale-file entry\n * wins so a deployment can correct or override any name; otherwise the\n * platform's region data localizes it; the English label is the last resort.\n *\n * English deliberately skips the region data: the dictionary already holds\n * curated English names, and CLDR spells several of them differently\n * (\"Antigua & Barbuda\" for \"Antigua and Barbuda\"), so consulting it would\n * silently rewrite existing English copy for no gain.\n */\nexport function resolvePhoneCountryLabel(\n country: PhoneCountry,\n t: TranslateFn,\n locale: string | undefined,\n): string {\n const translated = t(phoneCountryLabelKey(country.iso2), '')\n if (translated) return translated\n if (isEnglishLocale(locale)) return country.label\n return regionDisplayName(country.iso2, locale) ?? country.label\n}\n\nexport type PhoneCountryOption = {\n country: PhoneCountry\n label: string\n}\n\n/**\n * Locale safe to hand to `localeCompare`. A tag `Intl` cannot construct would\n * throw there just as it does in `getRegionDisplayNames`, so both fall back to\n * English together.\n */\nfunction resolveCollationLocale(locale: string | undefined): string {\n if (!locale) return 'en'\n return getRegionDisplayNames(locale) ? locale : 'en'\n}\n\n/**\n * Options rendered in the country dropdown. A caller-supplied list is\n * authoritative \u2014 its labels and its order are preserved verbatim \u2014 while the\n * built-in dictionary is localized and re-sorted for the active locale, since\n * its module-level ordering is alphabetical by the English name.\n */\nexport function buildPhoneCountryOptions(\n countries: PhoneCountry[] | undefined,\n t: TranslateFn,\n locale: string | undefined,\n): PhoneCountryOption[] {\n if (countries) return countries.map((country) => ({ country, label: country.label }))\n const collationLocale = resolveCollationLocale(locale)\n return PHONE_COUNTRIES\n .map((country) => ({ country, label: resolvePhoneCountryLabel(country, t, locale) }))\n .sort((a, b) => a.label.localeCompare(b.label, collationLocale, { sensitivity: 'base' }))\n}\n\n/**\n * Sovereign/primary country that wins auto-detection for a calling code shared\n * by several territories. US vs. Canada is the one irreducible ambiguity \u2014 both\n * are `+1` \u2014 and it resolves to the US.\n */\nconst PRIMARY_DIAL_OWNERS: Record<string, string> = {\n '+1': 'US',\n '+7': 'RU',\n '+44': 'GB',\n '+47': 'NO',\n '+61': 'AU',\n '+212': 'MA',\n '+262': 'RE',\n '+358': 'FI',\n '+590': 'GP',\n '+599': 'CW',\n}\n\nconst DEFAULT_COUNTRY =\n PHONE_COUNTRIES.find((country) => country.iso2 === 'US') ?? PHONE_COUNTRIES[0]\n\n// Match longer prefixes first (e.g. `+1242` before `+1`); for equal-length codes\n// shared by several territories, prefer the sovereign in `PRIMARY_DIAL_OWNERS`.\nconst COUNTRIES_BY_DIAL_LENGTH = [...PHONE_COUNTRIES].sort((a, b) => {\n if (b.dialCode.length !== a.dialCode.length) return b.dialCode.length - a.dialCode.length\n const aPrimary = PRIMARY_DIAL_OWNERS[a.dialCode] === a.iso2 ? 0 : 1\n const bPrimary = PRIMARY_DIAL_OWNERS[b.dialCode] === b.iso2 ? 0 : 1\n return aPrimary - bPrimary\n})\n\nfunction findCountryByIso(iso2: string): PhoneCountry | undefined {\n return PHONE_COUNTRIES.find((c) => c.iso2 === iso2)\n}\n\nfunction parseCountryFromValue(value: string | null | undefined): PhoneCountry | null {\n if (!value) return null\n const trimmed = value.trim()\n if (!trimmed.startsWith('+')) return null\n for (const country of COUNTRIES_BY_DIAL_LENGTH) {\n if (trimmed.startsWith(country.dialCode)) return country\n }\n return null\n}\n\nfunction extractLocalNumber(value: string | null | undefined, dialCode: string): string {\n if (!value) return ''\n const trimmed = value.trim()\n if (!trimmed.startsWith(dialCode)) return trimmed\n return trimmed.slice(dialCode.length).trim()\n}\n\nfunction composeValue(country: PhoneCountry, localNumber: string): string {\n const trimmed = localNumber.trim()\n if (!trimmed) return ''\n if (trimmed.startsWith('+')) return trimmed\n return `${country.dialCode} ${trimmed}`\n}\n\nexport type PhoneNumberFieldProps = {\n id?: string\n value?: string | null\n onValueChange: (next: string | undefined) => void\n onDigitsChange?: (digits: string | null) => void\n externalError?: string | null\n disabled?: boolean\n autoFocus?: boolean\n ariaLabel?: string\n ariaDescribedBy?: string\n placeholder?: string\n minDigits?: number\n checkingLabel?: string\n duplicateLabel?: (match: PhoneDuplicateMatch) => string\n duplicateLinkLabel?: string\n invalidLabel?: string\n onDuplicateLookup?: (normalizedValue: string) => Promise<PhoneDuplicateMatch | null>\n /**\n * Override the static country list (e.g. limit to specific markets, or supply\n * names already translated by the host). Both the labels and the order of the\n * supplied list are rendered verbatim.\n */\n countries?: PhoneCountry[]\n /** Initial country shown when `value` is empty / unparseable. Defaults to US. */\n defaultCountryIso2?: string\n size?: 32 | 36 | 40\n countryLabel?: string\n renderCountryIcon?: (country: PhoneCountry) => React.ReactNode\n}\n\nconst DEFAULT_MIN_DIGITS = 6\nconst DEFAULT_PLACEHOLDER = '(555) 000-0000'\n\nexport function PhoneNumberField({\n id,\n value,\n onValueChange,\n onDigitsChange,\n externalError,\n disabled = false,\n autoFocus,\n ariaLabel,\n ariaDescribedBy,\n placeholder,\n minDigits = DEFAULT_MIN_DIGITS,\n checkingLabel,\n duplicateLabel,\n duplicateLinkLabel,\n invalidLabel,\n onDuplicateLookup,\n countries: countriesProp,\n defaultCountryIso2,\n size,\n countryLabel,\n renderCountryIcon,\n}: PhoneNumberFieldProps) {\n const t = useT()\n const locale = useOptionalLocale()\n const resolvedInvalidLabel = invalidLabel ?? t(\n 'ui.inputs.phoneNumberField.invalid',\n 'Enter a valid phone number with country code (e.g. +1 212 555 1234)'\n )\n const resolvedCheckingLabel = checkingLabel ?? t(\n 'ui.inputs.phoneNumberField.checking',\n 'Checking for duplicates\u2026'\n )\n const resolvedDuplicateLinkLabel = duplicateLinkLabel ?? t(\n 'ui.inputs.phoneNumberField.duplicateLink',\n 'Open record'\n )\n const resolvedPlaceholder = placeholder ?? DEFAULT_PLACEHOLDER\n const countryOptions = React.useMemo(\n () => buildPhoneCountryOptions(countriesProp, t, locale),\n [countriesProp, t, locale],\n )\n const countryItems = React.useMemo(\n () => countryOptions.map(({ country: optionCountry, label }) => (\n <SelectItem\n key={`${optionCountry.iso2}-${optionCountry.dialCode}`}\n value={optionCountry.iso2}\n textValue={label}\n >\n <SelectItemLeading>\n <span className=\"text-base leading-none\">{optionCountry.flag}</span>\n </SelectItemLeading>\n <span className=\"flex-1 truncate\">{label}</span>\n <span className=\"ml-2 text-xs text-muted-foreground tabular-nums\">{optionCountry.dialCode}</span>\n </SelectItem>\n )),\n [countryOptions],\n )\n const fallbackCountry = React.useMemo(\n () => (defaultCountryIso2 && findCountryByIso(defaultCountryIso2)) || DEFAULT_COUNTRY,\n [defaultCountryIso2],\n )\n\n const initialCountry = React.useMemo(\n () => parseCountryFromValue(value) ?? fallbackCountry,\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [],\n )\n const [country, setCountry] = React.useState<PhoneCountry>(initialCountry)\n const [localNumber, setLocalNumber] = React.useState<string>(() =>\n extractLocalNumber(value, initialCountry.dialCode),\n )\n const [duplicate, setDuplicate] = React.useState<PhoneDuplicateMatch | null>(null)\n const [checking, setChecking] = React.useState(false)\n const [validationHint, setValidationHint] = React.useState<string | null>(null)\n const [focused, setFocused] = React.useState(false)\n const userEditingRef = React.useRef(false)\n\n const externalFieldError = externalError && externalError.trim().length > 0 ? externalError : null\n const errorMessage = externalFieldError ?? validationHint\n const errorId = errorMessage && id ? `${id}-error` : undefined\n const describedBy = [ariaDescribedBy, errorId].filter((part): part is string => Boolean(part)).join(' ') || undefined\n const composedValue = composeValue(country, localNumber)\n\n // Sync local state when `value` updates externally and the user is not editing.\n React.useEffect(() => {\n if (userEditingRef.current) return\n if (value == null || value === '') {\n setLocalNumber('')\n onDigitsChange?.(null)\n return\n }\n const parsed = parseCountryFromValue(value)\n if (parsed) setCountry(parsed)\n const next = extractLocalNumber(value, parsed?.dialCode ?? country.dialCode)\n setLocalNumber(next)\n onDigitsChange?.(extractPhoneDigits(String(value)) || null)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [value])\n\n // Debounced duplicate lookup.\n React.useEffect(() => {\n if (!onDuplicateLookup || disabled) {\n setDuplicate(null)\n setChecking(false)\n return\n }\n const digits = extractPhoneDigits(composedValue)\n if (!digits || digits.length < minDigits) {\n setDuplicate(null)\n setChecking(false)\n return\n }\n\n let cancelled = false\n setChecking(true)\n const handle = window.setTimeout(async () => {\n try {\n const match = await onDuplicateLookup(digits)\n if (!cancelled) setDuplicate(match)\n } catch {\n if (!cancelled) setDuplicate(null)\n } finally {\n if (!cancelled) setChecking(false)\n }\n }, 350)\n\n return () => {\n cancelled = true\n window.clearTimeout(handle)\n }\n }, [composedValue, disabled, minDigits, onDuplicateLookup])\n\n const emit = React.useCallback(\n (nextCountry: PhoneCountry, nextLocal: string) => {\n const composed = composeValue(nextCountry, nextLocal)\n onValueChange(composed.length ? composed : undefined)\n onDigitsChange?.(extractPhoneDigits(composed) || null)\n },\n [onDigitsChange, onValueChange],\n )\n\n const handleCountryChange = React.useCallback(\n (iso2: string) => {\n const next = findCountryByIso(iso2)\n if (!next) return\n userEditingRef.current = true\n setCountry(next)\n setValidationHint(null)\n emit(next, localNumber)\n },\n [emit, localNumber],\n )\n\n const handleLocalChange = React.useCallback(\n (event: React.ChangeEvent<HTMLInputElement>) => {\n const next = event.target.value\n userEditingRef.current = true\n setLocalNumber(next)\n setValidationHint(null)\n emit(country, next)\n },\n [country, emit],\n )\n\n const handleBlur = React.useCallback(() => {\n userEditingRef.current = false\n setFocused(false)\n const trimmed = localNumber.trim()\n if (!trimmed) {\n setLocalNumber('')\n setValidationHint(null)\n onValueChange(undefined)\n onDigitsChange?.(null)\n return\n }\n const composed = composeValue(country, trimmed)\n const result = validatePhoneNumber(composed)\n if (result.valid) {\n const normalizedLocal = extractLocalNumber(result.normalized ?? composed, country.dialCode)\n setLocalNumber(normalizedLocal)\n setValidationHint(null)\n onValueChange(result.normalized || undefined)\n onDigitsChange?.(result.digits || null)\n } else {\n setValidationHint(resolvedInvalidLabel)\n onValueChange(composed)\n onDigitsChange?.(result.digits || null)\n }\n }, [country, localNumber, onDigitsChange, onValueChange, resolvedInvalidLabel])\n\n const containerErrorBorder = errorMessage ? 'border-status-error-icon' : 'border-input'\n const containerFocusBorder = errorMessage\n ? 'border-status-error-icon shadow-focus'\n : 'border-brand-violet shadow-focus'\n\n return (\n <div className=\"space-y-2\">\n <div\n className={cn(\n 'flex items-stretch w-full rounded-md border bg-background shadow-xs transition-colors',\n size === 32 && 'h-8',\n size === 36 && 'h-9',\n size === 40 && 'h-10 rounded-lg',\n disabled\n ? 'bg-bg-disabled border-border-disabled cursor-not-allowed'\n : focused\n ? containerFocusBorder\n : `${containerErrorBorder} hover:border-foreground/30`,\n )}\n aria-invalid={errorMessage ? 'true' : undefined}\n data-slot=\"phone-input-wrapper\"\n >\n <Select value={country.iso2} onValueChange={handleCountryChange} disabled={disabled}>\n <SelectTrigger\n aria-label={countryLabel ?? (ariaLabel ? `${ariaLabel} country` : t('ui.inputs.phoneNumberField.country', 'Country code'))}\n size={size}\n className={cn(\n 'h-auto w-auto shrink-0 gap-1.5 rounded-none rounded-l-md border-0 bg-transparent px-2.5 py-2 shadow-none',\n 'hover:bg-muted/40 focus:bg-muted/40 focus-visible:shadow-none focus-visible:border-0',\n 'disabled:bg-transparent disabled:hover:bg-transparent',\n size && 'h-full gap-2 rounded-l-none py-0 pl-2.5 pr-2 [&>svg]:size-5',\n size === 32 && 'pl-1.5 pr-1',\n )}\n onFocus={() => setFocused(true)}\n onBlur={() => setFocused(false)}\n >\n <span className={cn('text-base leading-none', size && 'inline-flex size-5 shrink-0 items-center justify-center text-xl [&_img]:size-full')} aria-hidden=\"true\">{renderCountryIcon ? renderCountryIcon(country) : country.flag}</span>\n <span className={cn(\"text-sm text-foreground tabular-nums\", disabled && \"text-text-disabled\")}>{country.dialCode}</span>\n </SelectTrigger>\n <SelectContent align=\"start\">{countryItems}</SelectContent>\n </Select>\n <div aria-hidden=\"true\" className=\"w-px self-stretch bg-input\" />\n <input\n type=\"tel\"\n inputMode=\"tel\"\n autoComplete=\"tel-national\"\n value={localNumber}\n onChange={handleLocalChange}\n onBlur={handleBlur}\n onFocus={() => setFocused(true)}\n placeholder={resolvedPlaceholder}\n autoFocus={autoFocus}\n disabled={disabled}\n id={id}\n aria-label={ariaLabel}\n aria-describedby={describedBy}\n aria-invalid={errorMessage ? 'true' : undefined}\n data-crud-focus-target=\"\"\n className={cn(\n 'flex-1 min-w-0 bg-transparent px-3 py-2 text-sm leading-5 outline-none',\n 'placeholder:text-muted-foreground',\n 'disabled:cursor-not-allowed disabled:text-text-disabled disabled:placeholder:text-text-disabled',\n size && 'h-full py-0 pr-2.5',\n size === 32 && 'pl-2 pr-1.5',\n )}\n />\n </div>\n {errorMessage ? (\n <p id={errorId} role=\"alert\" className=\"text-xs text-status-error-text\">{errorMessage}</p>\n ) : null}\n {!disabled && duplicate && duplicateLabel ? (\n <p className=\"text-xs text-status-warning-text\">\n {duplicateLabel(duplicate)}{' '}\n <a className=\"font-medium text-brand-violet underline underline-offset-2\" href={duplicate.href}>\n {resolvedDuplicateLinkLabel}\n </a>\n </p>\n ) : null}\n {!disabled && !duplicate && checking ? (\n <p className=\"text-xs text-muted-foreground\">{resolvedCheckingLabel}</p>\n ) : null}\n </div>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|