@cloud-ru/ds-uikit-product-fields-predefined 2.0.30-preview-20b4671f.0 → 2.0.30-preview-a22f149a.0

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/README.md CHANGED
@@ -206,16 +206,13 @@ export function FieldMaskControlled() {
206
206
 
207
207
  Маска ввода определяется выбранной страной (`country.mask`) и меняется при смене страны. Префикс с кодом страны добавляется к итоговому значению.
208
208
 
209
- #### options — список стран
209
+ #### options — настройка списка стран
210
210
 
211
- Проп `options` (`CountrySettings`) обязателен, поля взаимоисключающие:
211
+ Проп `options` (`CountrySettings`) ограничивает или переопределяет список (взаимоисключающие поля):
212
212
 
213
- - `includedCountries` — страны селектора (`RUSSIA_COUNTRY_CODE`, `BELARUS_COUNTRY_CODE`, …) в порядке передачи.
214
- - `overriddenOptions` — собственные элементы списка вместо встроенных стран.
215
-
216
- В бандл попадают флаги только переданных стран. Весь встроенный перечень — `ALL_COUNTRY_CODES`: с ним в бандл попадают все флаги (около 500 КБ в gzip), поэтому список стоит передавать явно.
217
-
218
- Миграция с 2.x: поле без `options` — `options={{ includedCountries: ALL_COUNTRY_CODES }}`; `excludedCountries` — `includedCountries: ALL_COUNTRY_CODES.filter(...)`.
213
+ - `includedCountries` — оставить только перечисленные страны.
214
+ - `excludedCountries` — исключить перечисленные из встроенного списка.
215
+ - `overriddenOptions` — полностью заменить список собственными опциями.
219
216
 
220
217
  #### Size (default `m`)
221
218
 
@@ -225,11 +222,11 @@ export function FieldMaskControlled() {
225
222
 
226
223
  #### Базовый
227
224
 
228
- Телефон с полным списком стран (ALL_COUNTRY_CODES) и поиском.
225
+ Телефон с полным списком стран и поиском.
229
226
 
230
227
  ```tsx
231
228
  import { PortalContextProvider } from '@cloud-ru/ds-portal-context';
232
- import { ALL_COUNTRY_CODES, FieldPhone } from '@cloud-ru/ds-uikit-product-fields-predefined';
229
+ import { FieldPhone } from '@cloud-ru/ds-uikit-product-fields-predefined';
233
230
  import { useRef, useState } from 'react';
234
231
 
235
232
  export function FieldPhoneBasic() {
@@ -239,13 +236,7 @@ export function FieldPhoneBasic() {
239
236
  return (
240
237
  <PortalContextProvider root={hostRef}>
241
238
  <div ref={hostRef} style={{ position: 'relative', width: 320 }}>
242
- <FieldPhone
243
- label='Телефон'
244
- value={value}
245
- onChange={setValue}
246
- searchPlaceholder='Поиск страны'
247
- options={{ includedCountries: ALL_COUNTRY_CODES }}
248
- />
239
+ <FieldPhone label='Телефон' value={value} onChange={setValue} searchPlaceholder='Поиск страны' />
249
240
  </div>
250
241
  </PortalContextProvider>
251
242
  );
@@ -334,7 +325,7 @@ export function FieldPhoneCountrySettings() {
334
325
  | `onKeyDown` | `KeyboardEventHandler<HTMLInputElement>` | — | Колбек обработки начала нажатия клавиши клавиатуры |
335
326
  | `onMouseDown` | `MouseEventHandler<HTMLInputElement>` | — | Колбек обработки нажатия кнопки мыши |
336
327
  | `onPaste` | `ClipboardEventHandler<HTMLInputElement>` | — | Колбек обработки вставки значения |
337
- | `options` | `CountrySettings` | — | Список стран селектора: встроенные страны (`includedCountries`) или собственные элементы (`overriddenOptions`) |
328
+ | `options` | `CountrySettings` | — | Конфигурация для изменения стандартного списка стран |
338
329
  | `outline` | `boolean` | `true` | Разделитель между основным полем и слотами `elementBefore` / `elementAfter` |
339
330
  | `pattern` | `string` | — | Регулярное выражение валидного инпута |
340
331
  | `readonly` | `boolean` | `false` | Только для чтения <br/> Является ли поле доступным только для чтения |
@@ -354,7 +345,7 @@ export function FieldPhoneCountrySettings() {
354
345
 
355
346
  ##### Related types
356
347
 
357
- - `CountrySettings` = `({ includedCountries: readonly Country[]; } & { overriddenOptions?: undefined; }) | ({ overriddenOptions: FieldPhoneOptionsProps[]; } & { includedCountries?: undefined; })`
348
+ - `CountrySettings` = `({ overriddenOptions: FieldPhoneOptionsProps[]; } & { includedCountries?: undefined; excludedCountries?: undefined; }) | ({ includedCountries: Country[]; } & { overriddenOptions?: undefined; excludedCountries?: undefined; }) | ({ excludedCountries: Country[]; } & { overriddenOptions?: undefined; includedCountries?: undefined; })`
358
349
 
359
350
  ### Адаптивность
360
351
 
@@ -7,7 +7,7 @@ export type FieldPhoneProps = Omit<FieldComboProps, 'prefix' | 'prefixIcon' | 'p
7
7
  /** Плейсхолдер поля поиска в выпадающем списке стран */
8
8
  searchPlaceholder?: string;
9
9
  onChangeCountry?(country: FieldPhoneOptionsProps): void;
10
- /** Список стран селектора: встроенные страны (`includedCountries`) или собственные элементы (`overriddenOptions`) */
11
- options: CountrySettings;
10
+ /** Конфигурация для изменения стандартного списка стран */
11
+ options?: CountrySettings;
12
12
  };
13
13
  export declare const FieldPhone: import("react").ForwardRefExoticComponent<Omit<FieldPhoneProps, "ref"> & import("react").RefAttributes<HTMLInputElement>>;
@@ -1,2 +1,2 @@
1
1
  import { CountrySettings, FieldPhoneOptionsProps } from '../types';
2
- export declare function useCountries(optionsSettings: CountrySettings): FieldPhoneOptionsProps[];
2
+ export declare function useCountries(optionsSettings?: CountrySettings): FieldPhoneOptionsProps[];
@@ -2,19 +2,35 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useCountries = useCountries;
4
4
  const react_1 = require("react");
5
+ const countries_1 = require("../countries");
6
+ const utils_1 = require("../utils");
5
7
  const useMapCountryToOptions_1 = require("./useMapCountryToOptions");
6
- function getOptionsKey({ includedCountries, overriddenOptions }) {
7
- if (overriddenOptions) {
8
- return overriddenOptions
9
- .map(({ id, iso2, mask, content }) => [id, iso2, mask, content.label, content.caption].join(':'))
10
- .join();
11
- }
12
- return includedCountries.map(({ value }) => value).join();
13
- }
14
8
  function useCountries(optionsSettings) {
15
9
  const mapCountryToOption = (0, useMapCountryToOptions_1.useMapCountryToOptions)();
16
- const optionsKey = getOptionsKey(optionsSettings);
17
- return (0, react_1.useMemo)(() => optionsSettings.overriddenOptions ?? optionsSettings.includedCountries.map(mapCountryToOption),
18
- // eslint-disable-next-line react-hooks/exhaustive-deps
19
- [optionsKey, mapCountryToOption]);
10
+ const filterCountries = (0, react_1.useMemo)(() => {
11
+ if (!optionsSettings) {
12
+ return () => true;
13
+ }
14
+ const { includedCountries, excludedCountries } = optionsSettings;
15
+ const uniqueKey = 'value';
16
+ if (includedCountries) {
17
+ const includedSet = (0, utils_1.uniqueSet)(includedCountries, uniqueKey);
18
+ return (country) => includedSet.has(country[uniqueKey]);
19
+ }
20
+ if (excludedCountries) {
21
+ const excludedSet = (0, utils_1.uniqueSet)(excludedCountries, uniqueKey);
22
+ return (country) => !excludedSet.has(country[uniqueKey]);
23
+ }
24
+ return () => true;
25
+ }, [optionsSettings]);
26
+ return (0, react_1.useMemo)(() => {
27
+ if (optionsSettings?.overriddenOptions)
28
+ return optionsSettings.overriddenOptions;
29
+ return countries_1.ALL_COUNTRY_CODES.reduce((result, country) => {
30
+ if (filterCountries(country)) {
31
+ result.push(mapCountryToOption(country));
32
+ }
33
+ return result;
34
+ }, []);
35
+ }, [optionsSettings, filterCountries, mapCountryToOption]);
20
36
  }
@@ -21,12 +21,11 @@ type OneOf<T extends object> = {
21
21
  };
22
22
  }[keyof T];
23
23
  export type CountrySettings = OneOf<{
24
- /**
25
- * Страны селектора в порядке передачи. В бандл попадают флаги только переданных стран;
26
- * весь встроенный перечень — `ALL_COUNTRY_CODES`.
27
- */
28
- includedCountries: readonly Country[];
29
- /** Собственные элементы выпадающего списка вместо встроенных стран */
24
+ /** Список элементов выпадающего списка со странами; переопределяет встроенный список пакета */
30
25
  overriddenOptions: FieldPhoneOptionsProps[];
26
+ /** Список стран, которые должны отображаться в селекторе (из встроенного перечня пакета) */
27
+ includedCountries: Country[];
28
+ /** Список стран, которые будут исключены из встроенного перечня пакета */
29
+ excludedCountries: Country[];
31
30
  }>;
32
31
  export {};
@@ -1,4 +1,5 @@
1
1
  import { FieldPhoneOptionsProps } from './types';
2
+ export declare const uniqueSet: <T, K extends keyof T>(arr: T[], key: K) => Set<T[K]>;
2
3
  export declare const formatPhoneNumber: <T extends {
3
4
  caption: string;
4
5
  mask: string;
@@ -1,9 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.handleAutoInsert = exports.formatPhoneNumber = void 0;
3
+ exports.handleAutoInsert = exports.formatPhoneNumber = exports.uniqueSet = void 0;
4
4
  exports.detectCountryByPhone = detectCountryByPhone;
5
5
  const awesome_phonenumber_1 = require("awesome-phonenumber");
6
6
  const countries_1 = require("./countries");
7
+ const uniqueSet = (arr, key) => new Set(arr.map(obj => obj[key]));
8
+ exports.uniqueSet = uniqueSet;
7
9
  /* Приходит +79878887879/+7987****875, на основании mask возвращается +7 987-888-78-79/+7 987-***-*8-75 */
8
10
  const formatPhoneNumber = (phone, countries) => {
9
11
  const digits = phone.replace(/[^\d*]/g, '');
@@ -7,7 +7,7 @@ export type FieldPhoneProps = Omit<FieldComboProps, 'prefix' | 'prefixIcon' | 'p
7
7
  /** Плейсхолдер поля поиска в выпадающем списке стран */
8
8
  searchPlaceholder?: string;
9
9
  onChangeCountry?(country: FieldPhoneOptionsProps): void;
10
- /** Список стран селектора: встроенные страны (`includedCountries`) или собственные элементы (`overriddenOptions`) */
11
- options: CountrySettings;
10
+ /** Конфигурация для изменения стандартного списка стран */
11
+ options?: CountrySettings;
12
12
  };
13
13
  export declare const FieldPhone: import("react").ForwardRefExoticComponent<Omit<FieldPhoneProps, "ref"> & import("react").RefAttributes<HTMLInputElement>>;
@@ -1432,4 +1432,4 @@ export const ALL_COUNTRY_CODES = [
1432
1432
  SOUTH_SUDAN_COUNTRY_CODE,
1433
1433
  JAPAN_COUNTRY_CODE,
1434
1434
  ];
1435
- export const ENABLED_COUNTRY_CODES = /* @__PURE__ */ ALL_COUNTRY_CODES.filter(({ enabled }) => enabled);
1435
+ export const ENABLED_COUNTRY_CODES = ALL_COUNTRY_CODES.filter(({ enabled }) => enabled);
@@ -1,2 +1,2 @@
1
1
  import { CountrySettings, FieldPhoneOptionsProps } from '../types.js';
2
- export declare function useCountries(optionsSettings: CountrySettings): FieldPhoneOptionsProps[];
2
+ export declare function useCountries(optionsSettings?: CountrySettings): FieldPhoneOptionsProps[];
@@ -1,17 +1,33 @@
1
1
  import { useMemo } from 'react';
2
+ import { ALL_COUNTRY_CODES } from '../countries.js';
3
+ import { uniqueSet } from '../utils.js';
2
4
  import { useMapCountryToOptions } from './useMapCountryToOptions.js';
3
- function getOptionsKey({ includedCountries, overriddenOptions }) {
4
- if (overriddenOptions) {
5
- return overriddenOptions
6
- .map(({ id, iso2, mask, content }) => [id, iso2, mask, content.label, content.caption].join(':'))
7
- .join();
8
- }
9
- return includedCountries.map(({ value }) => value).join();
10
- }
11
5
  export function useCountries(optionsSettings) {
12
6
  const mapCountryToOption = useMapCountryToOptions();
13
- const optionsKey = getOptionsKey(optionsSettings);
14
- return useMemo(() => optionsSettings.overriddenOptions ?? optionsSettings.includedCountries.map(mapCountryToOption),
15
- // eslint-disable-next-line react-hooks/exhaustive-deps
16
- [optionsKey, mapCountryToOption]);
7
+ const filterCountries = useMemo(() => {
8
+ if (!optionsSettings) {
9
+ return () => true;
10
+ }
11
+ const { includedCountries, excludedCountries } = optionsSettings;
12
+ const uniqueKey = 'value';
13
+ if (includedCountries) {
14
+ const includedSet = uniqueSet(includedCountries, uniqueKey);
15
+ return (country) => includedSet.has(country[uniqueKey]);
16
+ }
17
+ if (excludedCountries) {
18
+ const excludedSet = uniqueSet(excludedCountries, uniqueKey);
19
+ return (country) => !excludedSet.has(country[uniqueKey]);
20
+ }
21
+ return () => true;
22
+ }, [optionsSettings]);
23
+ return useMemo(() => {
24
+ if (optionsSettings?.overriddenOptions)
25
+ return optionsSettings.overriddenOptions;
26
+ return ALL_COUNTRY_CODES.reduce((result, country) => {
27
+ if (filterCountries(country)) {
28
+ result.push(mapCountryToOption(country));
29
+ }
30
+ return result;
31
+ }, []);
32
+ }, [optionsSettings, filterCountries, mapCountryToOption]);
17
33
  }
@@ -21,12 +21,11 @@ type OneOf<T extends object> = {
21
21
  };
22
22
  }[keyof T];
23
23
  export type CountrySettings = OneOf<{
24
- /**
25
- * Страны селектора в порядке передачи. В бандл попадают флаги только переданных стран;
26
- * весь встроенный перечень — `ALL_COUNTRY_CODES`.
27
- */
28
- includedCountries: readonly Country[];
29
- /** Собственные элементы выпадающего списка вместо встроенных стран */
24
+ /** Список элементов выпадающего списка со странами; переопределяет встроенный список пакета */
30
25
  overriddenOptions: FieldPhoneOptionsProps[];
26
+ /** Список стран, которые должны отображаться в селекторе (из встроенного перечня пакета) */
27
+ includedCountries: Country[];
28
+ /** Список стран, которые будут исключены из встроенного перечня пакета */
29
+ excludedCountries: Country[];
31
30
  }>;
32
31
  export {};
@@ -1,4 +1,5 @@
1
1
  import { FieldPhoneOptionsProps } from './types.js';
2
+ export declare const uniqueSet: <T, K extends keyof T>(arr: T[], key: K) => Set<T[K]>;
2
3
  export declare const formatPhoneNumber: <T extends {
3
4
  caption: string;
4
5
  mask: string;
@@ -1,5 +1,6 @@
1
1
  import { parsePhoneNumber } from 'awesome-phonenumber';
2
2
  import { ABKHAZIA_COUNTRY_CODE, RUSSIA_COUNTRY_CODE } from './countries.js';
3
+ export const uniqueSet = (arr, key) => new Set(arr.map(obj => obj[key]));
3
4
  /* Приходит +79878887879/+7987****875, на основании mask возвращается +7 987-888-78-79/+7 987-***-*8-75 */
4
5
  export const formatPhoneNumber = (phone, countries) => {
5
6
  const digits = phone.replace(/[^\d*]/g, '');