@open-mercato/ui 0.8.1-develop.7452.1.5e211edd51 → 0.8.1-develop.7455.1.8f7e53badb

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.
@@ -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": "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",
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: countryOptions.map(({ country: c, label }) => /* @__PURE__ */ jsxs(SelectItem, { value: c.iso2, textValue: label, 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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/ui",
3
- "version": "0.8.1-develop.7452.1.5e211edd51",
3
+ "version": "0.8.1-develop.7455.1.8f7e53badb",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -155,14 +155,14 @@
155
155
  "remark-gfm": "^4.0.1"
156
156
  },
157
157
  "peerDependencies": {
158
- "@open-mercato/shared": "0.8.1-develop.7452.1.5e211edd51",
158
+ "@open-mercato/shared": "0.8.1-develop.7455.1.8f7e53badb",
159
159
  "react": ">=18.0.0",
160
160
  "react-dom": ">=18.0.0",
161
161
  "react-is": ">=18.0.0"
162
162
  },
163
163
  "devDependencies": {
164
164
  "@figma/code-connect": "^1.3.4",
165
- "@open-mercato/shared": "0.8.1-develop.7452.1.5e211edd51",
165
+ "@open-mercato/shared": "0.8.1-develop.7455.1.8f7e53badb",
166
166
  "@testing-library/dom": "^10.4.1",
167
167
  "@testing-library/jest-dom": "^7.0.1",
168
168
  "@testing-library/react": "^16.3.3",
@@ -1008,7 +1008,16 @@ export function CrudForm<TValues extends Record<string, unknown>>({
1008
1008
  const navigationConfirmPendingRef = React.useRef(false)
1009
1009
  const submitNavigationBypassRef = React.useRef(false)
1010
1010
  const submitNavigationBypassTimeoutRef = React.useRef<number | null>(null)
1011
- const [hasUnsavedChanges, setHasUnsavedChanges] = React.useState(false)
1011
+ const [hasUnsavedChanges, setHasUnsavedChangesState] = React.useState(false)
1012
+ const hasUnsavedChangesRef = React.useRef(false)
1013
+ // Writing a state hook the value it already holds still re-runs this whole
1014
+ // component once before React bails out. The dirty check runs on every edit,
1015
+ // so the flag is only written when it actually flips.
1016
+ const setHasUnsavedChanges = React.useCallback((next: boolean) => {
1017
+ if (hasUnsavedChangesRef.current === next) return
1018
+ hasUnsavedChangesRef.current = next
1019
+ setHasUnsavedChangesState(next)
1020
+ }, [])
1012
1021
  const popStateRollbackRef = React.useRef(false)
1013
1022
  const shouldBypassUnsavedChangesGuardRef = React.useRef(shouldBypassUnsavedChangesGuard)
1014
1023
  React.useEffect(() => {
@@ -1033,7 +1042,7 @@ export function CrudForm<TValues extends Record<string, unknown>>({
1033
1042
  const dirty = currentSnapshot !== snapshot
1034
1043
  isDirtyRef.current = dirty
1035
1044
  setHasUnsavedChanges(dirty)
1036
- }, [embedded, trackDirtyWhenEmbedded, values])
1045
+ }, [embedded, trackDirtyWhenEmbedded, values, setHasUnsavedChanges])
1037
1046
 
1038
1047
  React.useEffect(() => {
1039
1048
  onDirtyChange?.(hasUnsavedChanges)
@@ -1083,7 +1092,7 @@ export function CrudForm<TValues extends Record<string, unknown>>({
1083
1092
  everEditedFieldIdsRef.current.clear()
1084
1093
  isDirtyRef.current = false
1085
1094
  setHasUnsavedChanges(false)
1086
- }, [])
1095
+ }, [setHasUnsavedChanges])
1087
1096
 
1088
1097
  const confirmUnsavedChanges = React.useCallback(async (): Promise<boolean> => {
1089
1098
  if (!isDirtyRef.current || typeof window === 'undefined') return true
@@ -1201,7 +1210,7 @@ export function CrudForm<TValues extends Record<string, unknown>>({
1201
1210
  window.history.pushState = originalPushState
1202
1211
  window.history.replaceState = originalReplaceState
1203
1212
  }
1204
- }, [allowNextNavigation, clearDirtyState, confirmUnsavedChanges, embedded, hasUnsavedChanges, router, trackDirtyWhenEmbedded])
1213
+ }, [allowNextNavigation, clearDirtyState, confirmUnsavedChanges, embedded, hasUnsavedChanges, router, trackDirtyWhenEmbedded, setHasUnsavedChanges])
1205
1214
 
1206
1215
  const { widgets: primaryInjectionWidgets } = useInjectionWidgets(resolvedInjectionSpotId, {
1207
1216
  context: injectionContext,
@@ -2699,18 +2708,29 @@ export function CrudForm<TValues extends Record<string, unknown>>({
2699
2708
  ) {
2700
2709
  activeFieldChangeDispatchRef.current = null
2701
2710
  }
2711
+ // Re-run the dispatcher only when an edit queued behind this dispatch is
2712
+ // still waiting. Bumping unconditionally re-rendered the whole form a
2713
+ // second time for every keystroke, even with no widget listening.
2702
2714
  if (
2703
2715
  fieldChangeDispatcherMountedRef.current &&
2704
- fieldChangeFormGenerationRef.current === dispatchToken.formGeneration
2716
+ fieldChangeFormGenerationRef.current === dispatchToken.formGeneration &&
2717
+ pendingFieldChangeEventsRef.current.length > 0
2705
2718
  ) {
2706
2719
  setFieldChangeDispatchVersion((version) => version + 1)
2707
2720
  }
2708
2721
  })
2709
2722
  }, [extendedInjectionEventsEnabled, fieldChangeDispatchVersion, triggerInjectionEvent, values])
2710
2723
 
2711
- const onBlurRequest = React.useCallback((fieldId: string) => {
2712
- void validateFieldOnBlur(fieldId)
2724
+ // `validateFieldOnBlur` is rebuilt whenever the form values change. Passing
2725
+ // that identity down would invalidate every memoized field control on each
2726
+ // keystroke, so the fields get a stable callback that reads the latest one.
2727
+ const validateFieldOnBlurRef = React.useRef(validateFieldOnBlur)
2728
+ React.useLayoutEffect(() => {
2729
+ validateFieldOnBlurRef.current = validateFieldOnBlur
2713
2730
  }, [validateFieldOnBlur])
2731
+ const onBlurRequest = React.useCallback((fieldId: string) => {
2732
+ void validateFieldOnBlurRef.current(fieldId)
2733
+ }, [])
2714
2734
 
2715
2735
  const handleFieldsetSelectionChange = React.useCallback(
2716
2736
  (entityId: string, nextCode: string | null) => {