@open-mercato/ui 0.9.1-develop.7574.1.837288eec1 → 0.10.1-develop.7576.1.21d5b50435
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/dist/ai/parts/MutationResultCard.js +1 -14
- package/dist/ai/parts/MutationResultCard.js.map +2 -2
- package/dist/backend/CrudForm.js +52 -96
- package/dist/backend/CrudForm.js.map +2 -2
- package/dist/backend/DataTable.js +14 -40
- package/dist/backend/DataTable.js.map +2 -2
- package/dist/backend/FlashMessages.js +1 -25
- package/dist/backend/FlashMessages.js.map +2 -2
- package/dist/backend/columns/ColumnChooserPanel.js +3 -4
- package/dist/backend/columns/ColumnChooserPanel.js.map +2 -2
- package/dist/backend/confirm-dialog/ConfirmDialog.js +0 -11
- package/dist/backend/confirm-dialog/ConfirmDialog.js.map +2 -2
- package/dist/backend/detail/InlineEditors.js +6 -17
- package/dist/backend/detail/InlineEditors.js.map +2 -2
- package/dist/backend/filters/FilterFieldPicker.js +2 -3
- package/dist/backend/filters/FilterFieldPicker.js.map +2 -2
- package/dist/backend/forms/ActionsDropdown.js +2 -52
- package/dist/backend/forms/ActionsDropdown.js.map +2 -2
- package/dist/backend/inputs/PhoneNumberField.js +5 -17
- package/dist/backend/inputs/PhoneNumberField.js.map +2 -2
- package/dist/backend/inputs/TagsInput.js +1 -4
- package/dist/backend/inputs/TagsInput.js.map +2 -2
- package/dist/backend/inputs/index.js +0 -2
- package/dist/backend/inputs/index.js.map +2 -2
- package/dist/backend/messages/useMessageCompose.js +10 -29
- package/dist/backend/messages/useMessageCompose.js.map +2 -2
- package/dist/backend/notifications/NotificationDispatcher.js +0 -5
- package/dist/backend/notifications/NotificationDispatcher.js.map +2 -2
- package/dist/backend/notifications/useNotificationActions.js +2 -13
- package/dist/backend/notifications/useNotificationActions.js.map +2 -2
- package/dist/backend/utils/api.js +4 -25
- package/dist/backend/utils/api.js.map +2 -2
- package/dist/backend/version-history/VersionHistoryPanel.js +2 -18
- package/dist/backend/version-history/VersionHistoryPanel.js.map +2 -2
- package/dist/theme/QueryProvider.js +1 -7
- package/dist/theme/QueryProvider.js.map +2 -2
- package/package.json +4 -4
- package/src/ai/parts/MutationResultCard.tsx +1 -30
- package/src/ai/parts/__tests__/MutationResultCard.test.tsx +0 -48
- package/src/backend/CrudForm.tsx +60 -121
- package/src/backend/DataTable.tsx +14 -54
- package/src/backend/FlashMessages.tsx +1 -34
- package/src/backend/__tests__/ActionsDropdown.test.tsx +0 -105
- package/src/backend/__tests__/CrudForm.fieldInjection.test.tsx +4 -85
- package/src/backend/__tests__/FlashMessages.test.tsx +0 -65
- package/src/backend/__tests__/VersionHistoryPanel.test.tsx +1 -81
- package/src/backend/columns/ColumnChooserPanel.tsx +3 -4
- package/src/backend/confirm-dialog/ConfirmDialog.tsx +0 -16
- package/src/backend/confirm-dialog/__tests__/ConfirmDialog.test.tsx +0 -29
- package/src/backend/detail/InlineEditors.tsx +6 -28
- package/src/backend/detail/__tests__/InlineEditors.test.tsx +6 -121
- package/src/backend/filters/FilterFieldPicker.tsx +2 -3
- package/src/backend/forms/ActionsDropdown.tsx +2 -71
- package/src/backend/inputs/PhoneNumberField.tsx +11 -17
- package/src/backend/inputs/TagsInput.tsx +0 -4
- package/src/backend/inputs/__tests__/TagsInput.test.tsx +0 -41
- package/src/backend/inputs/index.ts +0 -2
- package/src/backend/messages/__tests__/useMessageCompose.test.tsx +1 -106
- package/src/backend/messages/message-composer.types.ts +0 -2
- package/src/backend/messages/useMessageCompose.ts +13 -34
- package/src/backend/notifications/NotificationDispatcher.ts +0 -5
- package/src/backend/notifications/__tests__/useNotificationActions.test.tsx +1 -86
- package/src/backend/notifications/useNotificationActions.ts +4 -19
- package/src/backend/utils/__tests__/api.test.ts +0 -67
- package/src/backend/utils/api.ts +4 -33
- package/src/backend/version-history/VersionHistoryPanel.tsx +2 -24
- package/src/theme/QueryProvider.tsx +1 -7
- package/dist/backend/crud/injectedFieldGroups.js +0 -50
- package/dist/backend/crud/injectedFieldGroups.js.map +0 -7
- package/dist/backend/inputs/LookupPickers.js +0 -149
- package/dist/backend/inputs/LookupPickers.js.map +0 -7
- package/dist/backend/inputs/lookupSources.js +0 -84
- package/dist/backend/inputs/lookupSources.js.map +0 -7
- package/dist/backend/utils/groupLabels.js +0 -16
- package/dist/backend/utils/groupLabels.js.map +0 -7
- package/src/backend/__tests__/CrudForm.disabledFields.test.tsx +0 -57
- package/src/backend/__tests__/CrudForm.embeddedExtraActions.test.tsx +0 -114
- package/src/backend/__tests__/CrudForm.fieldChangeRenders.test.tsx +0 -127
- package/src/backend/__tests__/DataTable.injectedColumnPlacement.test.tsx +0 -146
- package/src/backend/__tests__/next-dynamic-specifier.test.ts +0 -23
- package/src/backend/columns/__tests__/ColumnChooserPanel.groupLabels.test.tsx +0 -72
- package/src/backend/crud/__tests__/injectedFieldGroups.test.ts +0 -90
- package/src/backend/crud/injectedFieldGroups.ts +0 -75
- package/src/backend/filters/__tests__/FilterFieldPicker.groupLabels.test.tsx +0 -77
- package/src/backend/inputs/LookupPickers.tsx +0 -181
- package/src/backend/inputs/__tests__/LookupPickers.test.tsx +0 -120
- package/src/backend/inputs/__tests__/PhoneNumberField.renders.test.tsx +0 -35
- package/src/backend/inputs/__tests__/lookupSources.test.ts +0 -87
- package/src/backend/inputs/lookupSources.ts +0 -114
- package/src/backend/notifications/__tests__/NotificationDispatcher.navigate.test.ts +0 -76
- package/src/backend/utils/groupLabels.ts +0 -26
- package/src/theme/__tests__/QueryProvider.i18n.test.tsx +0 -40
|
@@ -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 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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",
|
|
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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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -34,8 +34,7 @@ function TagsInput({
|
|
|
34
34
|
disabled = false,
|
|
35
35
|
allowCustomValues = true,
|
|
36
36
|
showSuggestionsOnFocus = true,
|
|
37
|
-
suppressInitialSuggestionsOnFocus = false
|
|
38
|
-
closeSuggestionsOnSelect = false
|
|
37
|
+
suppressInitialSuggestionsOnFocus = false
|
|
39
38
|
}) {
|
|
40
39
|
const t = useT();
|
|
41
40
|
const [input, setInput] = React.useState("");
|
|
@@ -233,7 +232,6 @@ function TagsInput({
|
|
|
233
232
|
event.preventDefault();
|
|
234
233
|
addTag(input);
|
|
235
234
|
setInput("");
|
|
236
|
-
if (closeSuggestionsOnSelect) setSuggestionsDismissed(true);
|
|
237
235
|
} else if (event.key === "Backspace" && input === "" && value.length > 0) {
|
|
238
236
|
removeTag(value[value.length - 1]);
|
|
239
237
|
}
|
|
@@ -266,7 +264,6 @@ function TagsInput({
|
|
|
266
264
|
suppressBlurCommitRef.current = false;
|
|
267
265
|
addValue(option.value);
|
|
268
266
|
setInput("");
|
|
269
|
-
if (closeSuggestionsOnSelect) setSuggestionsDismissed(true);
|
|
270
267
|
},
|
|
271
268
|
children: [
|
|
272
269
|
/* @__PURE__ */ jsx("span", { children: option.label }),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/backend/inputs/TagsInput.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { Button } from '../../primitives/button'\nimport { Tag } from '../../primitives/tag'\n\nexport type TagsInputOption = {\n value: string\n label: string\n description?: string | null\n}\n\nexport type TagsInputProps = {\n value: string[]\n onChange: (next: string[]) => void\n placeholder?: string\n suggestions?: Array<string | TagsInputOption>\n loadSuggestions?: (query?: string) => Promise<Array<string | TagsInputOption>>\n selectedOptions?: TagsInputOption[]\n resolveLabel?: (value: string) => string\n resolveDescription?: (value: string) => string | null | undefined\n autoFocus?: boolean\n disabled?: boolean\n allowCustomValues?: boolean\n showSuggestionsOnFocus?: boolean\n suppressInitialSuggestionsOnFocus?: boolean\n closeSuggestionsOnSelect?: boolean\n}\n\nfunction normalizeOptions(input?: Array<string | TagsInputOption>): TagsInputOption[] {\n if (!Array.isArray(input)) return []\n return input\n .map((option) => {\n if (typeof option === 'string') {\n const trimmed = option.trim()\n if (!trimmed) return null\n return { value: trimmed, label: trimmed }\n }\n const value = typeof option.value === 'string' ? option.value.trim() : ''\n if (!value) return null\n return {\n value,\n label: option.label?.trim() || value,\n description: option.description ?? null,\n }\n })\n .filter((option): option is TagsInputOption => !!option)\n}\n\nexport function TagsInput({\n value,\n onChange,\n placeholder,\n suggestions,\n loadSuggestions,\n selectedOptions,\n resolveLabel,\n resolveDescription,\n autoFocus,\n disabled = false,\n allowCustomValues = true,\n showSuggestionsOnFocus = true,\n suppressInitialSuggestionsOnFocus = false,\n closeSuggestionsOnSelect = false,\n}: TagsInputProps) {\n const t = useT()\n const [input, setInput] = React.useState('')\n const [asyncOptions, setAsyncOptions] = React.useState<TagsInputOption[]>([])\n const [loading, setLoading] = React.useState(false)\n const [touched, setTouched] = React.useState(false)\n const [suggestionsDismissed, setSuggestionsDismissed] = React.useState(false)\n const inputRef = React.useRef<HTMLInputElement>(null)\n const suppressBlurCommitRef = React.useRef(false)\n const suppressSuggestionsOnFocusRef = React.useRef(Boolean(autoFocus && suppressInitialSuggestionsOnFocus && !disabled))\n const valueRef = React.useRef(value)\n\n React.useEffect(() => {\n valueRef.current = value\n }, [value])\n\n React.useEffect(() => {\n suppressSuggestionsOnFocusRef.current = Boolean(autoFocus && suppressInitialSuggestionsOnFocus && !disabled)\n }, [autoFocus, disabled, suppressInitialSuggestionsOnFocus])\n\n const staticOptions = React.useMemo(() => normalizeOptions(suggestions), [suggestions])\n const selectedOptionList = React.useMemo(\n () => normalizeOptions(selectedOptions),\n [selectedOptions]\n )\n\n const optionMap = React.useMemo(() => {\n const map = new Map<string, TagsInputOption>()\n const register = (option: TagsInputOption) => {\n if (!map.has(option.value)) {\n map.set(option.value, option)\n }\n }\n staticOptions.forEach(register)\n asyncOptions.forEach(register)\n selectedOptionList.forEach(register)\n value.forEach((val) => {\n if (map.has(val)) return\n map.set(val, {\n value: val,\n label: resolveLabel?.(val) ?? val,\n description: resolveDescription?.(val) ?? null,\n })\n })\n return map\n }, [asyncOptions, resolveDescription, resolveLabel, selectedOptionList, staticOptions, value])\n\n const availableOptions = React.useMemo(() => {\n return Array.from(optionMap.values()).filter((option) => !value.includes(option.value))\n }, [optionMap, value])\n\n const filteredSuggestions = React.useMemo(() => {\n const query = input.toLowerCase().trim()\n if (!query) return availableOptions.slice(0, 8)\n return availableOptions.filter((option) => {\n const labelMatch = option.label.toLowerCase().includes(query)\n const descMatch = option.description?.toLowerCase().includes(query)\n return labelMatch || Boolean(descMatch)\n })\n }, [availableOptions, input])\n\n React.useEffect(() => {\n if (!loadSuggestions || !touched || disabled) return\n const query = input.trim()\n let cancelled = false\n const handle = window.setTimeout(async () => {\n setLoading(true)\n try {\n const items = await loadSuggestions(query)\n if (!cancelled) {\n setAsyncOptions(normalizeOptions(items))\n }\n } finally {\n if (!cancelled) setLoading(false)\n }\n }, 200)\n return () => {\n cancelled = true\n window.clearTimeout(handle)\n }\n }, [disabled, input, loadSuggestions, touched])\n\n const suggestionsOpen = !suggestionsDismissed\n && ((loading && touched) || (!loading && filteredSuggestions.length > 0))\n\n React.useEffect(() => {\n if (!suggestionsOpen) return\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key !== 'Escape' || event.target !== inputRef.current) return\n event.preventDefault()\n event.stopPropagation()\n setSuggestionsDismissed(true)\n }\n window.addEventListener('keydown', handleEscape, { capture: true })\n return () => window.removeEventListener('keydown', handleEscape, { capture: true })\n }, [suggestionsOpen])\n\n const addValue = React.useCallback(\n (nextValue: string) => {\n if (disabled) return\n const trimmed = nextValue.trim()\n if (!trimmed) return\n const currentValue = valueRef.current\n if (currentValue.includes(trimmed)) return\n const next = [...currentValue, trimmed]\n valueRef.current = next\n onChange(next)\n },\n [disabled, onChange]\n )\n\n const findOptionForInput = React.useCallback(\n (raw: string): TagsInputOption | null => {\n const query = raw.trim().toLowerCase()\n if (!query) return null\n for (const option of optionMap.values()) {\n if (option.value === raw.trim()) return option\n if (option.label.toLowerCase() === query) return option\n }\n return null\n },\n [optionMap]\n )\n\n const addTag = React.useCallback(\n (raw: string) => {\n if (disabled) return\n const option = findOptionForInput(raw)\n if (option) {\n addValue(option.value)\n return\n }\n if (!allowCustomValues) return\n addValue(raw)\n },\n [addValue, allowCustomValues, disabled, findOptionForInput]\n )\n\n const removeTag = React.useCallback(\n (tag: string) => {\n if (disabled) return\n const next = valueRef.current.filter((candidate) => candidate !== tag)\n valueRef.current = next\n onChange(next)\n },\n [disabled, onChange]\n )\n\n return (\n <div\n className={[\n 'w-full rounded border px-2 py-1',\n disabled ? 'bg-muted text-muted-foreground/80 cursor-not-allowed' : '',\n ]\n .filter(Boolean)\n .join(' ')}\n aria-disabled={disabled || undefined}\n >\n <div className=\"flex flex-wrap gap-1\">\n {value.map((tag) => {\n const option = optionMap.get(tag)\n const label = option?.label ?? tag\n const description = option?.description\n return (\n <Tag\n key={tag}\n shape=\"square\"\n variant=\"default\"\n disabled={disabled}\n onRemove={() => removeTag(tag)}\n removeAriaLabel={t('ui.inputs.tagsInput.removeTag', 'Remove {label}', { label })}\n >\n <span className=\"flex flex-col items-start leading-tight\">\n <span className=\"whitespace-nowrap\">{label}</span>\n {description ? (\n <span className=\"text-overline text-muted-foreground\">{description}</span>\n ) : null}\n </span>\n </Tag>\n )\n })}\n <input\n ref={inputRef}\n className=\"flex-1 min-w-[80px] sm:min-w-[120px] border-0 py-1 text-sm outline-none disabled:bg-transparent\"\n value={input}\n placeholder={placeholder || t('ui.inputs.tagsInput.placeholder', 'Add tag and press Enter')}\n autoFocus={autoFocus}\n data-crud-focus-target=\"\"\n disabled={disabled}\n onFocus={() => {\n if (suppressSuggestionsOnFocusRef.current) {\n suppressSuggestionsOnFocusRef.current = false\n return\n }\n if (showSuggestionsOnFocus) {\n setTouched(true)\n setSuggestionsDismissed(false)\n }\n }}\n onMouseDown={() => {\n setTouched(true)\n setSuggestionsDismissed(false)\n }}\n onChange={(event) => {\n setTouched(true)\n setSuggestionsDismissed(false)\n setInput(event.target.value)\n }}\n onKeyDown={(event) => {\n if (disabled) return\n if (event.key === 'Enter' || event.key === ',') {\n event.preventDefault()\n addTag(input)\n setInput('')\n if (closeSuggestionsOnSelect) setSuggestionsDismissed(true)\n } else if (event.key === 'Backspace' && input === '' && value.length > 0) {\n removeTag(value[value.length - 1])\n }\n }}\n onBlur={() => {\n if (disabled) return\n if (suppressBlurCommitRef.current) {\n suppressBlurCommitRef.current = false\n setInput('')\n return\n }\n addTag(input)\n setInput('')\n }}\n />\n {suggestionsOpen && loading && touched ? (\n <div className=\"basis-full mt-1 text-xs text-muted-foreground\">{t('ui.inputs.tagsInput.loading', 'Loading suggestions\u2026')}</div>\n ) : null}\n {suggestionsOpen && !loading && filteredSuggestions.length ? (\n <div className=\"basis-full mt-1 flex flex-col gap-1\">\n {filteredSuggestions.map((option) => (\n <Button\n key={option.value}\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"w-full justify-start font-normal flex flex-col items-start text-xs px-1.5 py-1\"\n onMouseDown={(event) => {\n suppressBlurCommitRef.current = true\n event.preventDefault()\n }}\n onClick={() => {\n suppressBlurCommitRef.current = false\n addValue(option.value)\n setInput('')\n if (closeSuggestionsOnSelect) setSuggestionsDismissed(true)\n }}\n >\n <span>{option.label}</span>\n {option.description ? (\n <span className=\"text-overline text-muted-foreground\">{option.description}</span>\n ) : null}\n </Button>\n ))}\n </div>\n ) : null}\n </div>\n </div>\n )\n}\n"],
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { Button } from '../../primitives/button'\nimport { Tag } from '../../primitives/tag'\n\nexport type TagsInputOption = {\n value: string\n label: string\n description?: string | null\n}\n\nexport type TagsInputProps = {\n value: string[]\n onChange: (next: string[]) => void\n placeholder?: string\n suggestions?: Array<string | TagsInputOption>\n loadSuggestions?: (query?: string) => Promise<Array<string | TagsInputOption>>\n selectedOptions?: TagsInputOption[]\n resolveLabel?: (value: string) => string\n resolveDescription?: (value: string) => string | null | undefined\n autoFocus?: boolean\n disabled?: boolean\n allowCustomValues?: boolean\n showSuggestionsOnFocus?: boolean\n suppressInitialSuggestionsOnFocus?: boolean\n}\n\nfunction normalizeOptions(input?: Array<string | TagsInputOption>): TagsInputOption[] {\n if (!Array.isArray(input)) return []\n return input\n .map((option) => {\n if (typeof option === 'string') {\n const trimmed = option.trim()\n if (!trimmed) return null\n return { value: trimmed, label: trimmed }\n }\n const value = typeof option.value === 'string' ? option.value.trim() : ''\n if (!value) return null\n return {\n value,\n label: option.label?.trim() || value,\n description: option.description ?? null,\n }\n })\n .filter((option): option is TagsInputOption => !!option)\n}\n\nexport function TagsInput({\n value,\n onChange,\n placeholder,\n suggestions,\n loadSuggestions,\n selectedOptions,\n resolveLabel,\n resolveDescription,\n autoFocus,\n disabled = false,\n allowCustomValues = true,\n showSuggestionsOnFocus = true,\n suppressInitialSuggestionsOnFocus = false,\n}: TagsInputProps) {\n const t = useT()\n const [input, setInput] = React.useState('')\n const [asyncOptions, setAsyncOptions] = React.useState<TagsInputOption[]>([])\n const [loading, setLoading] = React.useState(false)\n const [touched, setTouched] = React.useState(false)\n const [suggestionsDismissed, setSuggestionsDismissed] = React.useState(false)\n const inputRef = React.useRef<HTMLInputElement>(null)\n const suppressBlurCommitRef = React.useRef(false)\n const suppressSuggestionsOnFocusRef = React.useRef(Boolean(autoFocus && suppressInitialSuggestionsOnFocus && !disabled))\n const valueRef = React.useRef(value)\n\n React.useEffect(() => {\n valueRef.current = value\n }, [value])\n\n React.useEffect(() => {\n suppressSuggestionsOnFocusRef.current = Boolean(autoFocus && suppressInitialSuggestionsOnFocus && !disabled)\n }, [autoFocus, disabled, suppressInitialSuggestionsOnFocus])\n\n const staticOptions = React.useMemo(() => normalizeOptions(suggestions), [suggestions])\n const selectedOptionList = React.useMemo(\n () => normalizeOptions(selectedOptions),\n [selectedOptions]\n )\n\n const optionMap = React.useMemo(() => {\n const map = new Map<string, TagsInputOption>()\n const register = (option: TagsInputOption) => {\n if (!map.has(option.value)) {\n map.set(option.value, option)\n }\n }\n staticOptions.forEach(register)\n asyncOptions.forEach(register)\n selectedOptionList.forEach(register)\n value.forEach((val) => {\n if (map.has(val)) return\n map.set(val, {\n value: val,\n label: resolveLabel?.(val) ?? val,\n description: resolveDescription?.(val) ?? null,\n })\n })\n return map\n }, [asyncOptions, resolveDescription, resolveLabel, selectedOptionList, staticOptions, value])\n\n const availableOptions = React.useMemo(() => {\n return Array.from(optionMap.values()).filter((option) => !value.includes(option.value))\n }, [optionMap, value])\n\n const filteredSuggestions = React.useMemo(() => {\n const query = input.toLowerCase().trim()\n if (!query) return availableOptions.slice(0, 8)\n return availableOptions.filter((option) => {\n const labelMatch = option.label.toLowerCase().includes(query)\n const descMatch = option.description?.toLowerCase().includes(query)\n return labelMatch || Boolean(descMatch)\n })\n }, [availableOptions, input])\n\n React.useEffect(() => {\n if (!loadSuggestions || !touched || disabled) return\n const query = input.trim()\n let cancelled = false\n const handle = window.setTimeout(async () => {\n setLoading(true)\n try {\n const items = await loadSuggestions(query)\n if (!cancelled) {\n setAsyncOptions(normalizeOptions(items))\n }\n } finally {\n if (!cancelled) setLoading(false)\n }\n }, 200)\n return () => {\n cancelled = true\n window.clearTimeout(handle)\n }\n }, [disabled, input, loadSuggestions, touched])\n\n const suggestionsOpen = !suggestionsDismissed\n && ((loading && touched) || (!loading && filteredSuggestions.length > 0))\n\n React.useEffect(() => {\n if (!suggestionsOpen) return\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key !== 'Escape' || event.target !== inputRef.current) return\n event.preventDefault()\n event.stopPropagation()\n setSuggestionsDismissed(true)\n }\n window.addEventListener('keydown', handleEscape, { capture: true })\n return () => window.removeEventListener('keydown', handleEscape, { capture: true })\n }, [suggestionsOpen])\n\n const addValue = React.useCallback(\n (nextValue: string) => {\n if (disabled) return\n const trimmed = nextValue.trim()\n if (!trimmed) return\n const currentValue = valueRef.current\n if (currentValue.includes(trimmed)) return\n const next = [...currentValue, trimmed]\n valueRef.current = next\n onChange(next)\n },\n [disabled, onChange]\n )\n\n const findOptionForInput = React.useCallback(\n (raw: string): TagsInputOption | null => {\n const query = raw.trim().toLowerCase()\n if (!query) return null\n for (const option of optionMap.values()) {\n if (option.value === raw.trim()) return option\n if (option.label.toLowerCase() === query) return option\n }\n return null\n },\n [optionMap]\n )\n\n const addTag = React.useCallback(\n (raw: string) => {\n if (disabled) return\n const option = findOptionForInput(raw)\n if (option) {\n addValue(option.value)\n return\n }\n if (!allowCustomValues) return\n addValue(raw)\n },\n [addValue, allowCustomValues, disabled, findOptionForInput]\n )\n\n const removeTag = React.useCallback(\n (tag: string) => {\n if (disabled) return\n const next = valueRef.current.filter((candidate) => candidate !== tag)\n valueRef.current = next\n onChange(next)\n },\n [disabled, onChange]\n )\n\n return (\n <div\n className={[\n 'w-full rounded border px-2 py-1',\n disabled ? 'bg-muted text-muted-foreground/80 cursor-not-allowed' : '',\n ]\n .filter(Boolean)\n .join(' ')}\n aria-disabled={disabled || undefined}\n >\n <div className=\"flex flex-wrap gap-1\">\n {value.map((tag) => {\n const option = optionMap.get(tag)\n const label = option?.label ?? tag\n const description = option?.description\n return (\n <Tag\n key={tag}\n shape=\"square\"\n variant=\"default\"\n disabled={disabled}\n onRemove={() => removeTag(tag)}\n removeAriaLabel={t('ui.inputs.tagsInput.removeTag', 'Remove {label}', { label })}\n >\n <span className=\"flex flex-col items-start leading-tight\">\n <span className=\"whitespace-nowrap\">{label}</span>\n {description ? (\n <span className=\"text-overline text-muted-foreground\">{description}</span>\n ) : null}\n </span>\n </Tag>\n )\n })}\n <input\n ref={inputRef}\n className=\"flex-1 min-w-[80px] sm:min-w-[120px] border-0 py-1 text-sm outline-none disabled:bg-transparent\"\n value={input}\n placeholder={placeholder || t('ui.inputs.tagsInput.placeholder', 'Add tag and press Enter')}\n autoFocus={autoFocus}\n data-crud-focus-target=\"\"\n disabled={disabled}\n onFocus={() => {\n if (suppressSuggestionsOnFocusRef.current) {\n suppressSuggestionsOnFocusRef.current = false\n return\n }\n if (showSuggestionsOnFocus) {\n setTouched(true)\n setSuggestionsDismissed(false)\n }\n }}\n onMouseDown={() => {\n setTouched(true)\n setSuggestionsDismissed(false)\n }}\n onChange={(event) => {\n setTouched(true)\n setSuggestionsDismissed(false)\n setInput(event.target.value)\n }}\n onKeyDown={(event) => {\n if (disabled) return\n if (event.key === 'Enter' || event.key === ',') {\n event.preventDefault()\n addTag(input)\n setInput('')\n } else if (event.key === 'Backspace' && input === '' && value.length > 0) {\n removeTag(value[value.length - 1])\n }\n }}\n onBlur={() => {\n if (disabled) return\n if (suppressBlurCommitRef.current) {\n suppressBlurCommitRef.current = false\n setInput('')\n return\n }\n addTag(input)\n setInput('')\n }}\n />\n {suggestionsOpen && loading && touched ? (\n <div className=\"basis-full mt-1 text-xs text-muted-foreground\">{t('ui.inputs.tagsInput.loading', 'Loading suggestions\u2026')}</div>\n ) : null}\n {suggestionsOpen && !loading && filteredSuggestions.length ? (\n <div className=\"basis-full mt-1 flex flex-col gap-1\">\n {filteredSuggestions.map((option) => (\n <Button\n key={option.value}\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"w-full justify-start font-normal flex flex-col items-start text-xs px-1.5 py-1\"\n onMouseDown={(event) => {\n suppressBlurCommitRef.current = true\n event.preventDefault()\n }}\n onClick={() => {\n suppressBlurCommitRef.current = false\n addValue(option.value)\n setInput('')\n }}\n >\n <span>{option.label}</span>\n {option.description ? (\n <span className=\"text-overline text-muted-foreground\">{option.description}</span>\n ) : null}\n </Button>\n ))}\n </div>\n ) : null}\n </div>\n </div>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/backend/inputs/index.ts"],
|
|
4
|
-
"sourcesContent": ["export * from './PhoneNumberField'\nexport * from './TagsInput'\nexport * from './LookupSelect'\nexport * from './ComboboxInput'\nexport * from './SwitchableMarkdownInput'\nexport * from './EventSelect'\nexport * from './EventPatternInput'\nexport * from './TimeInput'\nexport * from './TimePicker'\nexport * from './DateTimePicker'\nexport * from './DatePicker'\nexport * from './DurationInput'\
|
|
5
|
-
"mappings": "AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;
|
|
4
|
+
"sourcesContent": ["export * from './PhoneNumberField'\nexport * from './TagsInput'\nexport * from './LookupSelect'\nexport * from './ComboboxInput'\nexport * from './SwitchableMarkdownInput'\nexport * from './EventSelect'\nexport * from './EventPatternInput'\nexport * from './TimeInput'\nexport * from './TimePicker'\nexport * from './DateTimePicker'\nexport * from './DatePicker'\nexport * from './DurationInput'\n"],
|
|
5
|
+
"mappings": "AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -13,7 +13,6 @@ import {
|
|
|
13
13
|
useSendDraftOperation,
|
|
14
14
|
useUpdateDraftOperation
|
|
15
15
|
} from "./useMessageComposeOperations.js";
|
|
16
|
-
const ATTACHMENT_LIST_PAGE_SIZE = 100;
|
|
17
16
|
function toErrorMessage(payload) {
|
|
18
17
|
if (!payload) return null;
|
|
19
18
|
if (typeof payload === "string") return payload;
|
|
@@ -119,35 +118,17 @@ function useMessageCompose({
|
|
|
119
118
|
const attachmentEntityId = variant === "compose" && messageId ? "messages:message" : "attachments:library";
|
|
120
119
|
const attachmentRecordId = variant === "compose" && messageId ? messageId : temporaryAttachmentRecordId;
|
|
121
120
|
const loadAttachmentIds = React.useCallback(async () => {
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
params.set("page", String(page));
|
|
131
|
-
params.set("pageSize", String(ATTACHMENT_LIST_PAGE_SIZE));
|
|
132
|
-
const call = await apiCall(`/api/attachments?${params.toString()}`);
|
|
133
|
-
if (!call.ok) {
|
|
134
|
-
throw new Error(
|
|
135
|
-
toErrorMessage(call.result) ?? t("messages.errors.loadAttachmentOptionsFailed", "Failed to load attachments.")
|
|
136
|
-
);
|
|
137
|
-
}
|
|
138
|
-
const items = Array.isArray(call.result?.items) ? call.result.items : [];
|
|
139
|
-
for (const item of items) {
|
|
140
|
-
if (typeof item?.id === "string" && item.id.length > 0) collectedIds.add(item.id);
|
|
141
|
-
}
|
|
142
|
-
if (page === 1 && typeof call.result?.total === "number") expectedTotal = call.result.total;
|
|
143
|
-
const totalPages = typeof call.result?.totalPages === "number" ? call.result.totalPages : page;
|
|
144
|
-
hasMorePages = items.length === ATTACHMENT_LIST_PAGE_SIZE && page < totalPages;
|
|
145
|
-
page += 1;
|
|
146
|
-
}
|
|
147
|
-
if (expectedTotal !== null && collectedIds.size < expectedTotal) {
|
|
148
|
-
throw new Error(t("messages.errors.loadAttachmentOptionsFailed", "Failed to load attachments."));
|
|
121
|
+
const params = new URLSearchParams();
|
|
122
|
+
params.set("entityId", attachmentEntityId);
|
|
123
|
+
params.set("recordId", attachmentRecordId);
|
|
124
|
+
const call = await apiCall(`/api/attachments?${params.toString()}`);
|
|
125
|
+
if (!call.ok) {
|
|
126
|
+
throw new Error(
|
|
127
|
+
toErrorMessage(call.result) ?? t("messages.errors.loadAttachmentOptionsFailed", "Failed to load attachments.")
|
|
128
|
+
);
|
|
149
129
|
}
|
|
150
|
-
const
|
|
130
|
+
const items = Array.isArray(call.result?.items) ? call.result.items : [];
|
|
131
|
+
const nextIds = items.map((item) => typeof item?.id === "string" ? item.id : "").filter((id) => id.length > 0);
|
|
151
132
|
setAttachmentIds(nextIds);
|
|
152
133
|
return nextIds;
|
|
153
134
|
}, [attachmentEntityId, attachmentRecordId, t]);
|