> ## Documentation Index
> Fetch the complete documentation index at: https://docs.twenty.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Выбор страны

> Полный выбор страны и общие части для подготовленных вариантов, стабильных идентификаторов и очистки значения null.

## Обзор

`CountrySelect` предоставляет полный выбор страны с триггером с подписью, декоративными флагами, поиском и вариантом без выбора страны. `CountrySelect.Root`, `CountrySelect.Trigger` и `CountrySelect.Options` предоставляют одну и ту же реализацию для композиции с [Dropdown](https://docs.twenty.com/ru/ui/components/navigation/dropdown.md). Ваше приложение предоставляет данные о странах и переведённый текст, а также определяет, как выбранные идентификаторы сопоставляются с сохраняемыми значениями.

**Light**

[Выбор страны (light)](https://storybook.twenty.com/iframe.html?id=ui-input-countryselect--display\&viewMode=story\&globals=colorScheme:light)

**Dark**

[Выбор страны (dark)](https://storybook.twenty.com/iframe.html?id=ui-input-countryselect--display\&viewMode=story\&globals=colorScheme:dark)

[Open in Storybook](https://storybook.twenty.com/?path=/story/ui-input-countryselect--display)

## Использование

Предоставьте подготовленные варианты с уникальными стабильными строковыми идентификаторами и отображаемыми подписями. Средство выбора передаёт идентификаторы без изменений, независимо от отображаемого языка. Флаги — необязательные декоративные React-узлы. Для варианта можно задать `disabled: true`, чтобы он оставался видимым без возможности выбора.

```tsx theme={null}
import { CountrySelect } from 'twenty-ui/components/input';

const COUNTRIES = [
  { value: 'FR', label: 'France', flag: '🇫🇷' },
  { value: 'DE', label: 'Germany', flag: '🇩🇪' },
  { value: 'JP', label: 'Japan', flag: '🇯🇵' },
];

export const ShippingCountry = () => (
  <CountrySelect
    label="Shipping country"
    countries={COUNTRIES}
    defaultValue="FR"
    searchLabel="Search countries"
    noCountryLabel="No country"
    noResultsLabel="No countries found"
  />
);
```

`defaultValue` инициализирует неконтролируемый выбор. Используйте `value` и `onValueChange` для контролируемого выбора. Внешнее обновление `value` обновляет и триггер, и выбранный вариант, в том числе когда всплывающее окно открыто.

```tsx theme={null}
import { useState } from 'react';
import { CountrySelect, type CountryChoice } from 'twenty-ui/components/input';

export const ControlledCountry = ({
  countries,
}: {
  countries: readonly CountryChoice[];
}) => {
  const [country, setCountry] = useState<string | null>('FR');

  return (
    <CountrySelect
      label="Country"
      countries={countries}
      value={country}
      onValueChange={setCountry}
    />
  );
};
```

## Общие части

`Root` управляет подготовленными вариантами и выбранным идентификатором. Он не добавляет элемент DOM. `Trigger` считывает этот выбор и отображает его метку и флаг. `Options` считывает те же данные и отображает строки с поиском внутри `Dropdown.SelectionGroup`. Dropdown управляет открытием, размещением всплывающего окна, страницами, навигацией и фокусом.

```tsx theme={null}
import { CountrySelect, type CountryChoice } from 'twenty-ui/components/input';
import { Dropdown } from 'twenty-ui/components/navigation';

export const ShippingCountryParts = ({
  countries,
}: {
  countries: readonly CountryChoice[];
}) => (
  <CountrySelect.Root countries={countries} defaultValue="FR">
    <Dropdown.Root type="picker">
      <CountrySelect.Trigger label="Shipping country" />
      <Dropdown.Content>
        <CountrySelect.Options
          aria-label="Shipping country"
          searchLabel="Search countries"
        />
      </Dropdown.Content>
    </Dropdown.Root>
  </CountrySelect.Root>
);
```

Сокращённая форма внутренне собирает эти части. Обе формы поддерживают выбор, очистку, отключённое состояние, сопоставление при поиске и представление выбранного варианта. Значение `closeOnSelect` по умолчанию — `true`. Задайте для него `false` в сокращённой форме или в `Options`, если после выбора всплывающее окно должно оставаться открытым.

## Очистка и отмена

`null` означает отсутствие страны. При выборе строки без страны передаётся `null`; передача `value={null}` очищает контролируемый селектор. Пустая строка (`''`) — допустимый предоставленный идентификатор варианта, отличный от `null`.

`onValueChange` получает следующий идентификатор или `null`, а также сведения о событии выбора Dropdown: `event`, `reason`, `trigger`, `cancel` и `isCanceled`. Вызовите `details.cancel()` перед обновлением контролируемого состояния, чтобы сохранить текущий выбор и оставить всплывающее окно открытым. Повторный выбор текущего идентификатора не вызывает ещё одного изменения значения.

Для идентификатора, отсутствующего в `countries`, отображаются `noCountryLabel` и значок отсутствия страны. Его отображение не вызывает изменения и не перезаписывает значение хоста. Приложение само решает, как обрабатывать сохранённые значения, отсутствующие среди текущих вариантов.

## Поиск и взаимодействие

Поиск сопоставляет подготовленные отображаемые метки. Он игнорирует регистр букв, необязательные диакритические знаки в латинском, греческом, арабском и еврейском тексте, а также знаки ударения в кириллице, считает кириллическую `ё` буквой `е` и преобразует такие буквы, как `ø`, `æ` и `ß`, в `o`, `ae` и `ss`. Он также игнорирует отдельные символы диакритических знаков, такие как `^`, `` ` ``, `´`, `¨` и `ˇ`, поэтому ожидающая мертвая клавиша не скрывает совпадения. Знаки, образующие отдельные буквы, остаются значимыми, например японские знаки озвончения, индийские знаки гласных и кириллическая `й`. Частично введенный корейский слог, например ㅎ или 하, соответствует слогам, которые начинаются с него, например 한. `noCountryLabel` участвует в том же поиске. Запрос без соответствующих вариантов отображает `noResultsLabel`.

Клавиши со стрелками, Home и End перемещают фокус, не изменяя выбранный идентификатор. Enter или Space на доступном варианте подтверждает выбор через его группу выбора. Escape и взаимодействие вне элемента используют механизмы закрытия и обработки фокуса Dropdown. У каждого селектора независимые состояние выбора и всплывающего окна.

Активация поиска Dropdown и защита IME по-прежнему требуют интеграционной работы, как и сеансы ленивой загрузки страниц и поведение неактивных страниц. Обе формы селектора при повторном открытии сбрасывают собственный поиск, в том числе во всплывающих окнах, которые остаются смонтированными. Их общая реализация ещё не завершает жизненный цикл страниц и просмотра Dropdown.

`disabled` на `Root` или в сокращённой форме предотвращает открытие и выбор. Средство выбора без предоставленных стран также отключено. Если любое из этих условий возникает, когда всплывающее окно открыто, селектор запрашивает закрытие. При закрытии фокус возвращается триггеру. Контролируемые хосты должны принять этот запрос на закрытие через `onOpenChange`; сокращённая форма также скрывает всплывающее окно, пока оно отключено. После принятия запроса на закрытие повторное включение селектора не открывает его автоматически. Триггер остаётся доступным для фокуса и предоставляет `aria-disabled`. Отключённые триггеры пропускают обработчики активации потребителя. Функциональные формы `className`, `style` и `render` получают `disabled: true` в состоянии триггера.

## Метки и настройка

Укажите видимый `label` или используйте `aria-label` либо `aria-labelledby` на триггере. Метки по ссылке имеют приоритет над непустым `aria-label`, который имеет приоритет над видимой меткой. При наличии одного из этих имён выбранная страна описывает триггер. В противном случае его именует выбранная страна. Всплывающее окно наследует имя триггера, если метки всплывающего окна, заданные вызывающим кодом, или заголовок Dropdown не задают ему имя. Сокращённая форма также именует свой список вариантов на основе этих меток триггера, если только `optionsProps` не задаёт собственное доступное имя. При составном использовании задайте для `Options` `aria-label` или `aria-labelledby`, чтобы явно указать имя списка вариантов. В противном случае он ссылается на зарегистрированный заголовок Dropdown или содержимое триггера. Подсказка показывает полную выбранную метку, если она обрезана.

`searchLabel` задает заполнитель и доступное имя поля поиска, `noCountryLabel` — текст отсутствия страны, а `noResultsLabel` — текст пустого результата. По умолчанию используются `Search`, `No country` и `No results`. Передавайте переведенные строки, когда ваше приложение локализовано. Пользовательские дочерние элементы `Trigger` заменяют отображение выбранной страны; вызывающий код управляет этим содержимым и его доступным представлением.

Нативные атрибуты триггера, обработчики событий, `className`, `style`, `ref` и `render` применяются к кнопке триггера. `wrapperProps` применяется к окружающему div, который также содержит видимую метку. Нативные свойства `Options`, `ref` и `render` применяются к его div группы выбора. Его функция `render` получает `{ value, multiple: false }`, где `value` — общедоступный идентификатор страны или `null`, а не внутренний идентификатор варианта. `searchProps` применяется к полю ввода поиска; значение поиска и обработка изменений остаются в управлении селектора. Сокращённая форма принимает те же свойства поиска напрямую, а атрибуты группы — через `optionsProps`. Передавайте предоставленные свойства и ссылки при замене элемента через `render`.

## Интеграция с хостом и хранение

Сокращённая форма принимает `open`, `defaultOpen`, `onOpenChange`, `onEscapeKeyDown`, `onInteractOutside` и `defaultPage` из Dropdown. При составном использовании задавайте их в `Dropdown.Root`. Сейчас `onOpenChange` передаёт только логическое значение в соответствии с публичным контрактом Dropdown. Сведения о событии открытия и общая отмена открытия по-прежнему недоступны на верхнем уровне. Колбэки закрытия по Escape и при взаимодействии вне элемента могут вызвать `event.preventDefault()`, чтобы оставить всплывающее окно открытым.

`popupProps` принимает все свойства `Dropdown.Content`, кроме `children`, включая нативные атрибуты всплывающего окна, `ref`, `render`, позиционирование, место назначения портала, доступные имена и `keepMounted`. При составном использовании передавайте их непосредственно в `Dropdown.Content`.

Храните идентификаторы выпадающего списка, стеки фокуса, метаданные полей, сохранение и жизненный цикл редактирования в адаптере хоста. Фронтенд-адаптер Twenty использует стабильные коды стран для идентификаторов селектора и преобразует явные выборы обратно в существующие значения названий стран исходного источника. Сохранённая пустая строка сопоставляется с `null` селектора; несовпадающие устаревшие значения остаются сохранёнными, пока явный выбор не изменит их. Переведённые отображаемые метки не становятся сохранёнными названиями стран. Приложения с другим форматом хранения также должны выполнять преобразование в своём адаптере.

Отправка нативной формы, сброс, `required`, `readOnly` и интеграция Field для этого пользовательского селектора пока отложены.

## Средство рендеринга компонента Front

Фикстуры фронтенд-компонентов React и Preact проверяют открытие указателем, фильтрацию и выбор через сокращённый и составной API, включая контролируемые и неконтролируемые значения, очистку и повторный выбор null, отменённые изменения, внешние контролируемые обновления, отключённое взаимодействие, переведённые метки и декоративные флаги. Они также проверяют нативные свойства и ссылки триггера и поля ввода поиска, а также цели рендеринга и ссылки триггера и группы вариантов. Активация поиска с клавиатуры и обработка IME, время жизни сеанса страниц, а также полное принятие портала, геометрии, прокрутки, закрытия по взаимодействию вне элемента и восстановления фокуса средством рендеринга остаются открытыми вопросами.

## Миграция

Замените прежний маркер отсутствия страны в виде пустой строки на `null` в контролируемых значениях и состоянии выбора. Пустая строка (`''`) теперь является допустимым идентификатором варианта, поэтому `value=""` больше не означает отсутствие страны. Сохраняйте неизменным каждое значение `CountryChoice.value`; существующие строковые идентификаторы могут остаться без изменений, а отображаемые метки можно переводить независимо.

Обновите обработчики `onValueChange`, чтобы они принимали `string | null`. Теперь колбэк также получает `eventDetails` вторым аргументом, включая `cancel()` для отклонения выбора. Обработчики, которым не нужны сведения о событии, могут продолжать использовать только первый аргумент.

Если ваше хранилище использует `''` для отсутствия страны, преобразуйте его в `null` перед передачей в селектор и преобразуйте полученный `null` обратно в `''` при сохранении. Сохраняйте это преобразование совместимости в адаптере приложения и не применяйте его, когда `''` является преднамеренным идентификатором варианта.

## Свойства

**children** `ReactNode`

Custom trigger content. Replaces the selected country presentation while retaining shared trigger behavior.

**className** `string | ((state: PopoverTriggerState) =\> string | undefined)`

Class applied to the trigger.

**closeDelay** `number` (default: 0)

How long to wait before closing the popover that was opened on hover.
Specified in milliseconds.

Requires the `openOnHover` prop.

**closeOnSelect** `boolean`

Closes the popup after a selection. Defaults to true. Cancelled selection keeps it open.

**countries** `readonly CountryChoice[]` *required*

Prepared country choices with unique stable string values, caller-owned labels, and optional decorative flags and disabled states. An empty string is a valid choice value.

**defaultOpen** `boolean`

Whether the uncontrolled popup is initially open.

**defaultPage** `string`

Dropdown page shown when the popup opens. Defaults to root.

**defaultValue** `string | null`

Initial uncontrolled selected identifier. Defaults to null.

**delay** `number` (default: 300)

How long to wait before the popover may be opened on hover. Specified in milliseconds.

Requires the `openOnHover` prop.

**disabled** `boolean`

Prevents opening and selection while the trigger stays focusable. An empty country list is also disabled.

**id** `string`

ID of the trigger. Generated when omitted.

**label** `string`

Optional visible label that names the trigger.

**nativeButton** `boolean` (default: true)

Whether the component renders a native `<button>` element when replacing it
via the `render` prop.
Set to `false` if the rendered element is not a button (e.g. `<div>`).

**noCountryLabel** `string`

Text of the no-country choice, also displayed when no country is selected.

**noResultsLabel** `string`

Text displayed when no choice matches the search.

**onEscapeKeyDown** `((event: DropdownDismissEvent) =\> void)`

Called before Escape dismisses the popup. Call event.preventDefault() to keep it open.

**onInteractOutside** `((event: DropdownDismissEvent) =\> void)`

Called before outside interaction or Tab dismisses the popup. Call event.preventDefault() to keep it open.

**onOpenChange** `((open: boolean) =\> void)`

Reports popup opening and closing with the next boolean state, matching Dropdown.Root.

**onValueChange** `((value: string | null, eventDetails: DropdownSelectionGroupChangeEventDetails) =\> void)`

Reports the selected identifier or null with cancellable event details. Call details.cancel() to preserve selection and keep the popup open.

**open** `boolean`

Controls whether the country popup is open.

**openOnHover** `boolean` (default: false)

Whether the popover should also open when the trigger is hovered.

**optionsProps** `Omit\<CountrySelectOptionsProps, "closeOnSelect" | "searchLabel" | "noResultsLabel" | "searchProps"\>`

Native props, ref, and render for the selection group div rendered by CountrySelect.Options.

**popupProps** `Omit\<DropdownContentProps, "children"\>`

Dropdown.Content props, including native popup attributes, ref, render, positioning, portal destination, and keepMounted. Explicit popup accessible names override the trigger name. Children are owned by the picker.

**ref** `Ref\<HTMLButtonElement\>`

Ref to the trigger element.

**render** `ReactElement\<unknown, string | JSXElementConstructor\<any\>\> | ComponentRenderFn\<HTMLProps, PopoverTriggerState\>`

Replaces the trigger element while preserving its behavior and props.

**searchLabel** `string`

Placeholder and accessible name of the search input.

**searchProps** `Omit\<DropdownSearchProps, "defaultValue" | "value" | "onValueChange"\>`

Native search input props, ref, and render. Search value and change handling are owned by the picker.

**style** `CSSProperties | ((state: PopoverTriggerState) =\> CSSProperties | undefined)`

Style applied to the element, or a function that
returns a style object based on the component's state.

**value** `string | null`

Controlled selected identifier. Null selects no country; undefined leaves selection uncontrolled.

**wrapperProps** `Omit\<DetailedHTMLProps\<HTMLAttributes\<HTMLDivElement\>, HTMLDivElement\>, "children"\>`

Native props and ref for the div around the trigger and its visible label. Children are owned by the picker.

### CountrySelect.Root

**Root.children** `ReactNode` *required*

Picker composition containing Dropdown.Root, CountrySelect.Trigger, and CountrySelect.Options. Root adds no DOM element.

**Root.countries** `readonly CountryChoice[]` *required*

Prepared country choices with unique stable string values, caller-owned labels, and optional decorative flags and disabled states. An empty string is a valid choice value.

**Root.defaultValue** `string | null` (default: null)

Initial uncontrolled selected identifier. Defaults to null.

**Root.disabled** `boolean` (default: false)

Prevents opening and selection. An empty country list is also disabled. The trigger stays focusable with aria-disabled.

**Root.noCountryLabel** `string` (default: No country)

Text for the null selection and its option. Defaults to No country.

**Root.onValueChange** `((value: string | null, eventDetails: DropdownSelectionGroupChangeEventDetails) =\> void)`

Reports the selected identifier or null with event, reason, trigger, cancel and isCanceled details. Call cancel() to preserve selection and keep the popup open.

**Root.value** `string | null`

Controlled selected identifier. Null selects no country; undefined leaves selection uncontrolled.

### CountrySelect.Trigger

**Trigger.children** `ReactNode`

Custom trigger content. Replaces the selected country presentation while retaining shared trigger behavior.

**Trigger.className** `string | ((state: PopoverTriggerState) =\> string | undefined)`

Class applied to the trigger button.

**Trigger.closeDelay** `number` (default: 0)

How long to wait before closing the popover that was opened on hover.
Specified in milliseconds.

Requires the `openOnHover` prop.

**Trigger.delay** `number` (default: 300)

How long to wait before the popover may be opened on hover. Specified in milliseconds.

Requires the `openOnHover` prop.

**Trigger.id** `string`

ID of the trigger. In addition to being forwarded to the rendered element,
it is also used to specify the active trigger for the popover in controlled mode (with the PopoverRoot `triggerId` prop).

**Trigger.label** `string`

Optional visible label that names the trigger.

**Trigger.nativeButton** `boolean` (default: true)

Whether the component renders a native `<button>` element when replacing it
via the `render` prop.
Set to `false` if the rendered element is not a button (e.g. `<div>`).

**Trigger.openOnHover** `boolean` (default: false)

Whether the popover should also open when the trigger is hovered.

**Trigger.ref** `Ref\<HTMLButtonElement\>`

Ref to the trigger element.

**Trigger.render** `ReactElement\<unknown, string | JSXElementConstructor\<any\>\> | ComponentRenderFn\<HTMLProps, PopoverTriggerState\>`

Replaces the trigger element. Custom components must forward the supplied props and ref.

**Trigger.style** `CSSProperties | ((state: PopoverTriggerState) =\> CSSProperties | undefined)`

Style applied to the element, or a function that
returns a style object based on the component's state.

**Trigger.wrapperProps** `Omit\<DetailedHTMLProps\<HTMLAttributes\<HTMLDivElement\>, HTMLDivElement\>, "children"\>`

Native props and ref for the div around the trigger and its visible label. Children are owned by the picker.

### CountrySelect.Options

**Options.aria-label** `string`

Accessible name for the selection listbox. Overrides its default name.

**Options.aria-labelledby** `string`

Accessible name references for the selection listbox. Defaults to the registered Dropdown title or trigger element.

**Options.className** `string`

Class applied to the selection group div.

**Options.closeOnSelect** `boolean`

Closes the popup after a selection. Defaults to true. Cancelled selection keeps it open.

**Options.noResultsLabel** `string`

Text displayed when no choice matches the search. Defaults to No results.

**Options.ref** `Ref\<HTMLDivElement\>`

Ref to the selection group element.

**Options.render** `ReactElement\<unknown, string | JSXElementConstructor\<any\>\> | ComponentRenderFn\<HTMLProps, CountrySelectOptionsState\>`

Replaces the selection group div. Functions receive supplied props and \{ value, multiple: false } state, with the public string or null selection. Custom components must forward the supplied props and ref.

**Options.searchLabel** `string`

Search placeholder and accessible name. Defaults to Search.

**Options.searchProps** `Omit\<DropdownSearchProps, "defaultValue" | "value" | "onValueChange"\>`

Native search input props, ref, and render. Search value and change handling are owned by the picker.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.