import{n as e}from"./rolldown-runtime-C0FnF6B9.js";import{n as t}from"./iframe-GrlyTB2d.js";import{i as n,r}from"./react-qN2cStNd.js";import{l as i,m as a}from"./blocks-DkLPipTQ.js";function o(e){let t={code:`code`,h1:`h1`,h2:`h2`,h3:`h3`,p:`p`,pre:`pre`,table:`table`,tbody:`tbody`,td:`td`,th:`th`,thead:`thead`,tr:`tr`,...n(),...e.components};return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(i,{title:`Foundation Lib/Formatters`}),`
`,(0,c.jsx)(t.h1,{id:`форматтеры`,children:`Форматтеры`}),`
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`@ryuzaki13/react-foundation-lib/formatters`}),` — единая публичная точка входа для
преобразования значений в host-проекте. Она покрывает даты, числа, строки,
логические значения, ФИО, телефон и числовые идентификаторы. Импортировать
внутренние файлы пакета и корневой пакет не нужно: все показанные ниже имена
доступны из опубликованного subpath.`]}),`
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`import { formatDate, formatNumber, normalizeText, parseBoolean } from "@ryuzaki13/react-foundation-lib/formatters";

import type { DateFormatPreset, NumberFormatPresetConfig } from "@ryuzaki13/react-foundation-lib/formatters";
`})}),`
`,(0,c.jsx)(t.h2,{id:`выбор-api`,children:`Выбор API`}),`
`,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`Задача`}),(0,c.jsx)(t.th,{children:`Используйте`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Отобразить или разобрать дату без неявного timezone-сдвига`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`formatDate`}),`, `,(0,c.jsx)(t.code,{children:`parseDate`}),`, `,(0,c.jsx)(t.code,{children:`parseDateTZ`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Получить календарные границы или безопасный диапазон`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`getCalendarPeriod`}),`, `,(0,c.jsx)(t.code,{children:`normalizeDateRange`}),`, `,(0,c.jsx)(t.code,{children:`requireDateRange`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Отобразить число или разобрать SAP-подобную строку`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`formatNumber`}),`, `,(0,c.jsx)(t.code,{children:`toFiniteNumber`}),`, `,(0,c.jsx)(t.code,{children:`parseNumber`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Привести текст к безопасной строке или нормализовать пробелы`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`toSafeString`}),`, `,(0,c.jsx)(t.code,{children:`normalizeText`}),`, `,(0,c.jsx)(t.code,{children:`normalizeTextSpaces`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Склонить русское существительное по количеству`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`selectRussianPluralForm`}),`, `,(0,c.jsx)(t.code,{children:`formatRussianPlural`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Преобразовать ABAP boolean`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`parseAbapBoolean`}),`, `,(0,c.jsx)(t.code,{children:`toAbapBoolean`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Показать ФИО, российский номер или код с ведущими нулями`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`formatFullName`}),`, `,(0,c.jsx)(t.code,{children:`formatPhone`}),`, `,(0,c.jsx)(t.code,{children:`normalizeLeadingZerosStrict`})]})]})]})]}),`
`,(0,c.jsx)(t.h2,{id:`даты`,children:`Даты`}),`
`,(0,c.jsx)(t.h3,{id:`основной-форматтер`,children:`Основной форматтер`}),`
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`import { formatDate, formatDateAsDateTime, formatDateAsODataDate } from "@ryuzaki13/react-foundation-lib/formatters";

formatDate("2026-03-05T14:30:00", "date");
// "05.03.2026"

formatDateAsDateTime("/Date(1772713800000+0500)/");
// строка даты и времени в локальной календарной семантике

formatDateAsODataDate(new Date(2026, 2, 5));
// "2026-03-05"
`})}),`
`,(0,c.jsx)(t.p,{children:`Сигнатура универсального вызова:`}),`
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`formatDate(
	value: unknown,
	presetOrName?: string | DateFormatPreset,
	options?: FormatDateOptions
): string;
`})}),`
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`value`}),` может быть `,(0,c.jsx)(t.code,{children:`Date`}),`, Unix timestamp, OData ticks вида
`,(0,c.jsx)(t.code,{children:`/Date(…)/`}),`, OData literal, ABAP-дата/временная метка, ISO-строка,
ISO-длительность и несколько распространённых человекочитаемых форматов.
Неподходящее значение не выбрасывает исключение: результатом будет
`,(0,c.jsx)(t.code,{children:`options.fallback`}),`, либо `,(0,c.jsx)(t.code,{children:`invalidFallback`}),` выбранного пресета, либо пустая
строка по умолчанию.`]}),`
`,(0,c.jsxs)(t.p,{children:[`Исключение — неизвестное строковое имя пресета: `,(0,c.jsx)(t.code,{children:`formatDate`}),` выбросит
`,(0,c.jsx)(t.code,{children:`Error`}),`. Если формат получен из внешней конфигурации, сначала разрешите его
через `,(0,c.jsx)(t.code,{children:`resolveDateFormatPreset`}),` или проверьте через `,(0,c.jsx)(t.code,{children:`getDatePreset`}),`.`]}),`
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`FormatDateOptions`}),`:`]}),`
`,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`Поле`}),(0,c.jsx)(t.th,{children:`Назначение`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`fallback?: string`})}),(0,c.jsx)(t.td,{children:`Результат для нераспознанного входа; имеет приоритет над fallback пресета.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`precision?: "day" | "month" | "year"`})}),(0,c.jsx)(t.td,{children:`Скрывает календарные части ниже выбранной точности.`})]})]})]}),`
`,(0,c.jsx)(t.h3,{id:`готовые-форматтеры`,children:`Готовые форматтеры`}),`
`,(0,c.jsxs)(t.p,{children:[`Все функции принимают `,(0,c.jsx)(t.code,{children:`value: unknown`}),` и необязательный `,(0,c.jsx)(t.code,{children:`FormatDateOptions`}),`,
возвращают строку и используют соответствующий встроенный пресет.`]}),`
`,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`API`}),(0,c.jsx)(t.th,{children:`Результат / назначение`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`formatDateAsDate`})}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`dd.MM.yyyy`}),`.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`formatDateAsDateTime`})}),(0,c.jsx)(t.td,{children:`Дата и время до минут.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`formatDateAsTime`}),`, `,(0,c.jsx)(t.code,{children:`formatDateAsTimeSeconds`})]}),(0,c.jsx)(t.td,{children:`Время до минут или секунд.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`formatDateAsDateShort`}),`, `,(0,c.jsx)(t.code,{children:`formatDateAsDateMedium`}),`, `,(0,c.jsx)(t.code,{children:`formatDateAsDateLong`})]}),(0,c.jsx)(t.td,{children:`Числовая, сокращённая и полная русская дата.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`formatDateAsMonthShort`}),`, `,(0,c.jsx)(t.code,{children:`formatDateAsMonthMedium`}),`, `,(0,c.jsx)(t.code,{children:`formatDateAsMonthLong`})]}),(0,c.jsx)(t.td,{children:`День и месяц без года: числовой, сокращённый или полный вид.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`formatDateAsMonthYearMedium`}),`, `,(0,c.jsx)(t.code,{children:`formatDateAsMonthYearLong`})]}),(0,c.jsx)(t.td,{children:`Месяц и год в сокращённом или полном виде.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`formatDateAsTimeShort`}),`, `,(0,c.jsx)(t.code,{children:`formatDateAsTimeMedium`}),`, `,(0,c.jsx)(t.code,{children:`formatDateAsTimeLong`})]}),(0,c.jsx)(t.td,{children:`Короткое или секундное время без вывода timezone.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`formatDateAsDatetimeShort`}),`, `,(0,c.jsx)(t.code,{children:`formatDateAsDatetimeMedium`}),`, `,(0,c.jsx)(t.code,{children:`formatDateAsDatetimeLong`})]}),(0,c.jsx)(t.td,{children:`Дата и время с разной детализацией.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`formatDateAsAbapYear`}),`, `,(0,c.jsx)(t.code,{children:`formatDateAsAbapMonth`}),`, `,(0,c.jsx)(t.code,{children:`formatDateAsAbapDate`}),`, `,(0,c.jsx)(t.code,{children:`formatDateAsAbapDatetime`})]}),(0,c.jsxs)(t.td,{children:[`Машинные строки `,(0,c.jsx)(t.code,{children:`yyyy`}),`, `,(0,c.jsx)(t.code,{children:`yyyyMM`}),`, `,(0,c.jsx)(t.code,{children:`yyyyMMdd`}),`, `,(0,c.jsx)(t.code,{children:`yyyyMMddHHmmss`}),`.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`formatDateAsODataDate`}),`, `,(0,c.jsx)(t.code,{children:`formatDateAsODataDatetime`})]}),(0,c.jsxs)(t.td,{children:[`Машинные строки `,(0,c.jsx)(t.code,{children:`yyyy-MM-dd`}),`, `,(0,c.jsx)(t.code,{children:`yyyy-MM-ddTHH:mm:ss`}),`.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`formatDateAsODataTime`})}),(0,c.jsxs)(t.td,{children:[`Время как OData duration `,(0,c.jsx)(t.code,{children:`PT00H00M00S`}),`; для ISO-длительности форматирует её как время.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`formatDateRange(startValue, endValue, presetOrName?, options?)`})}),(0,c.jsxs)(t.td,{children:[`Две валидные даты через `,(0,c.jsx)(t.code,{children:`-`}),`; если любая невалидна, возвращает fallback.`]})]})]})]}),`
`,(0,c.jsx)(t.h3,{id:`разбор-даты-и-timezone-семантика`,children:`Разбор даты и timezone-семантика`}),`
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`import { parseDate, parseDateTZ, parseDateByPattern, parseDateValue } from "@ryuzaki13/react-foundation-lib/formatters";

parseDate("20260305");
// Date | null

parseDateTZ("2026-03-05T10:00:00+05:00");
// Date | null, сохраняет абсолютный instant

parseDateByPattern("05/03/2026", "dd/MM/yyyy");
// { kind: "date-time", source: "iso-local", date: Date } | null

parseDateValue("PT01H30M");
// { kind: "duration", source: "iso-duration", durationMs: 5_400_000 } | null
`})}),`
`,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`API`}),(0,c.jsx)(t.th,{children:`Вход и результат`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`parseDateValue(value)`})}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`ParsedDateValue | null`}),`. Обычный режим: сохраняет видимые календарные компоненты без применения timezone.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`parseDateValueTZ(value)`})}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`ParsedDateValue | null`}),`. Для Unix timestamp и ISO/OData со смещением сохраняет абсолютный момент времени.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`parseDate(value)`})}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`Date | null`}),`; в том числе приводит duration к `,(0,c.jsx)(t.code,{children:`Date`}),` в «плавающей» календарной семантике.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`parseDateTZ(value)`})}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`Date | null`}),` с timezone-aware трактовкой абсолютного времени.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`parseDateByPattern(value, pattern?, { precision? })`})}),(0,c.jsxs)(t.td,{children:[`Строго разбирает токены `,(0,c.jsx)(t.code,{children:`dd`}),`, `,(0,c.jsx)(t.code,{children:`MM`}),`, `,(0,c.jsx)(t.code,{children:`yyyy`}),`, `,(0,c.jsx)(t.code,{children:`yy`}),`, `,(0,c.jsx)(t.code,{children:`HH`}),`, `,(0,c.jsx)(t.code,{children:`mm`}),`, `,(0,c.jsx)(t.code,{children:`ss`}),`; невалидные компоненты дают `,(0,c.jsx)(t.code,{children:`null`}),`. Двузначный год `,(0,c.jsx)(t.code,{children:`00–69`}),` — это `,(0,c.jsx)(t.code,{children:`2000–2069`}),`, `,(0,c.jsx)(t.code,{children:`70–99`}),` — `,(0,c.jsx)(t.code,{children:`1970–1999`}),`.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`parseDateByFormat(value, dateFormat?, options?)`})}),(0,c.jsxs)(t.td,{children:[`Разбирает зарегистрированное имя пресета, style-алиас или ручной шаблон. `,(0,c.jsx)(t.code,{children:`options`}),`: `,(0,c.jsx)(t.code,{children:`defaultFormat`}),`, `,(0,c.jsx)(t.code,{children:`locale`}),`, `,(0,c.jsx)(t.code,{children:`precision`}),`, `,(0,c.jsx)(t.code,{children:`referenceDate`}),`.`]})]})]})]}),`
`,(0,c.jsxs)(t.p,{children:[`Публичные типы для результатов и контракта: `,(0,c.jsx)(t.code,{children:`DateInputSource`}),`,
`,(0,c.jsx)(t.code,{children:`ParsedDateValue`}),`, `,(0,c.jsx)(t.code,{children:`DateFormatPattern`}),`, `,(0,c.jsx)(t.code,{children:`DateFormatStyle`}),`,
`,(0,c.jsx)(t.code,{children:`DateFormatPrecision`}),`, `,(0,c.jsx)(t.code,{children:`DateFormatPreset`}),`, `,(0,c.jsx)(t.code,{children:`DateFormatPresetConfig`}),`,
`,(0,c.jsx)(t.code,{children:`FormatDateOptions`}),`, `,(0,c.jsx)(t.code,{children:`ParseDateByPatternOptions`}),`, `,(0,c.jsx)(t.code,{children:`ParseDateByFormatOptions`}),`.`]}),`
`,(0,c.jsxs)(t.p,{children:[`Не заменяйте `,(0,c.jsx)(t.code,{children:`parseDate`}),` на `,(0,c.jsx)(t.code,{children:`new Date("YYYY-MM-DD")`}),`, если значение является
календарной датой: native parsing может изменить отображаемый день из-за
timezone.`]}),`
`,(0,c.jsx)(t.h3,{id:`пресеты-дат`,children:`Пресеты дат`}),`
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`import {
	DEFAULT_DATE_PRESET_NAMES,
	getDatePreset,
	registerDatePreset,
	resolveDateFormatPreset
} from "@ryuzaki13/react-foundation-lib/formatters";

registerDatePreset({
	name: "report-date",
	pattern: "dd.MM.yyyy",
	invalidFallback: "—"
});

formatDate("2026-03-05", "report-date"); // "05.03.2026"

const safePreset = resolveDateFormatPreset("dd/MM/yyyy");
formatDate("05/03/2026", safePreset); // "05/03/2026"
`})}),`
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`DEFAULT_DATE_PRESET_NAMES`}),` содержит: `,(0,c.jsx)(t.code,{children:`date`}),`, `,(0,c.jsx)(t.code,{children:`date-short`}),`, `,(0,c.jsx)(t.code,{children:`date-medium`}),`,
`,(0,c.jsx)(t.code,{children:`date-long`}),`, `,(0,c.jsx)(t.code,{children:`month-short`}),`, `,(0,c.jsx)(t.code,{children:`month-medium`}),`, `,(0,c.jsx)(t.code,{children:`month-long`}),`,
`,(0,c.jsx)(t.code,{children:`month-year-medium`}),`, `,(0,c.jsx)(t.code,{children:`month-year-long`}),`, `,(0,c.jsx)(t.code,{children:`datetime`}),`, `,(0,c.jsx)(t.code,{children:`datetime-seconds`}),`,
`,(0,c.jsx)(t.code,{children:`datetime-short`}),`, `,(0,c.jsx)(t.code,{children:`datetime-medium`}),`, `,(0,c.jsx)(t.code,{children:`datetime-long`}),`, `,(0,c.jsx)(t.code,{children:`time`}),`,
`,(0,c.jsx)(t.code,{children:`time-seconds`}),`, `,(0,c.jsx)(t.code,{children:`time-short`}),`, `,(0,c.jsx)(t.code,{children:`time-medium`}),`, `,(0,c.jsx)(t.code,{children:`time-long`}),`, `,(0,c.jsx)(t.code,{children:`odata-date`}),`,
`,(0,c.jsx)(t.code,{children:`odata-datetime`}),`, `,(0,c.jsx)(t.code,{children:`abap-datetime`}),`, `,(0,c.jsx)(t.code,{children:`abap-date`}),`, `,(0,c.jsx)(t.code,{children:`abap-month`}),`, `,(0,c.jsx)(t.code,{children:`abap-year`}),`.`]}),`
`,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`API`}),(0,c.jsx)(t.th,{children:`Поведение`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`DATE_FORMAT_DEFAULTS`})}),(0,c.jsxs)(t.td,{children:[`Значения по умолчанию: `,(0,c.jsx)(t.code,{children:`ru-RU`}),`, числовая дата и пустой `,(0,c.jsx)(t.code,{children:`invalidFallback`}),`.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`DATE_FORMAT_STYLE_PRESET_NAMES`})}),(0,c.jsxs)(t.td,{children:[`Соответствие `,(0,c.jsx)(t.code,{children:`short`}),`, `,(0,c.jsx)(t.code,{children:`medium`}),`, `,(0,c.jsx)(t.code,{children:`long`}),` встроенным date-пресетам.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`getDatePreset(name)`}),`, `,(0,c.jsx)(t.code,{children:`getDatePresetNames()`})]}),(0,c.jsxs)(t.td,{children:[`Возвращают пресет или `,(0,c.jsx)(t.code,{children:`undefined`}),`, список имён.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`registerDatePreset(config)`})}),(0,c.jsxs)(t.td,{children:[`Компилирует и регистрирует/перезаписывает пресет, возвращает готовый `,(0,c.jsx)(t.code,{children:`DateFormatPreset`}),`. Реестр module-scoped.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`resetDatePresets()`})}),(0,c.jsx)(t.td,{children:`Сбрасывает реестр к встроенным пресетам; используйте для изолированных тестов, не в обычном runtime.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`isDateFormatStyle(value)`}),`, `,(0,c.jsx)(t.code,{children:`isDateFormatPrecision(value)`})]}),(0,c.jsx)(t.td,{children:`Type guard для style и precision.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`resolveDateFormatName(value?, defaultFormat?)`})}),(0,c.jsxs)(t.td,{children:[`Обрезает пробелы и переводит `,(0,c.jsx)(t.code,{children:`short`}),` / `,(0,c.jsx)(t.code,{children:`medium`}),` / `,(0,c.jsx)(t.code,{children:`long`}),` в имя date-пресета.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`resolveDateFormatPreset(value?, options?)`})}),(0,c.jsx)(t.td,{children:`Возвращает имя зарегистрированного пресета или кешируемый объектный пресет для ручного шаблона.`})]})]})]}),`
`,(0,c.jsxs)(t.p,{children:[`Для ручных шаблонов доступны константы `,(0,c.jsx)(t.code,{children:`DATE_PATTERN_DATE_TOKENS`}),`,
`,(0,c.jsx)(t.code,{children:`DATE_PATTERN_TIME_TOKENS`}),`, `,(0,c.jsx)(t.code,{children:`DATE_PATTERN_TOKENS`}),` и `,(0,c.jsx)(t.code,{children:`DATE_PATTERN_TOKEN_RE`}),`.
Поддерживаются только перечисленные токены; остальные фрагменты шаблона —
литеральный текст.`]}),`
`,(0,c.jsx)(t.h3,{id:`календарные-значения-и-диапазоны`,children:`Календарные значения и диапазоны`}),`
`,(0,c.jsxs)(t.p,{children:[`Эти функции работают с локальными компонентами `,(0,c.jsx)(t.code,{children:`Date`}),` и не добавляют UTC- или
timezone-семантику.`]}),`
`,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`API`}),(0,c.jsx)(t.th,{children:`Результат / fallback`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`createCalendarDate(year, monthIndex, day, hour?, minute?, second?, millisecond?)`})}),(0,c.jsxs)(t.td,{children:[`Новый локальный `,(0,c.jsx)(t.code,{children:`Date`}),`; `,(0,c.jsx)(t.code,{children:`monthIndex`}),` соответствует `,(0,c.jsx)(t.code,{children:`Date#getMonth()`}),`.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`getStartOfDay`}),`, `,(0,c.jsx)(t.code,{children:`getEndOfDay`}),`, `,(0,c.jsx)(t.code,{children:`getStartOfMonth`}),`, `,(0,c.jsx)(t.code,{children:`getStartOfYear`}),`, `,(0,c.jsx)(t.code,{children:`getStartOfWeek(date, weekStartsOn?)`})]}),(0,c.jsx)(t.td,{children:`Новая дата с календарной границей; по умолчанию неделя начинается в понедельник.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`addCalendarDays`}),`, `,(0,c.jsx)(t.code,{children:`addCalendarMonths`}),`, `,(0,c.jsx)(t.code,{children:`addCalendarYears`})]}),(0,c.jsxs)(t.td,{children:[`Новый `,(0,c.jsx)(t.code,{children:`Date`}),`, сдвинутый в календарной семантике.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`isSameCalendarDay(left, right)`})}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`false`}),`, если любой аргумент не является `,(0,c.jsx)(t.code,{children:`Date`}),`; иначе сравнивает год, месяц, день.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`getCalendarPeriod(value, { selectionMode?, weekEndDay? })`})}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`{ start, end } | null`}),`; режимы `,(0,c.jsx)(t.code,{children:`day`}),`, `,(0,c.jsx)(t.code,{children:`week`}),`, `,(0,c.jsx)(t.code,{children:`month`}),`, `,(0,c.jsx)(t.code,{children:`year`}),`, конец недели — `,(0,c.jsx)(t.code,{children:`friday`}),`, `,(0,c.jsx)(t.code,{children:`saturday`}),` или `,(0,c.jsx)(t.code,{children:`sunday`}),`.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`isDateInsideCalendarPeriod`}),`, `,(0,c.jsx)(t.code,{children:`isCalendarPeriodWithinDateBounds`})]}),(0,c.jsxs)(t.td,{children:[`Проверяют включительные границы; при отсутствующих/невалидных данных возвращают `,(0,c.jsx)(t.code,{children:`false`}),`.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`resolveDateRangePair(value)`})}),(0,c.jsxs)(t.td,{children:[`Упорядоченная пара дат или `,(0,c.jsx)(t.code,{children:`null`}),`; одиночная дата становится диапазоном из неё самой.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`normalizeDateRange(value, { timeMode? })`})}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`DateRange | null`}),`; по умолчанию расширяет до границ суток, `,(0,c.jsx)(t.code,{children:`preserve`}),` сохраняет время и создаёт копии.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`requireDateRange(value, options?)`})}),(0,c.jsxs)(t.td,{children:[`Как `,(0,c.jsx)(t.code,{children:`normalizeDateRange`}),`, но при отсутствии диапазона выбрасывает `,(0,c.jsx)(t.code,{children:`Error`}),`.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`countCalendarDaysInDateRange(value)`})}),(0,c.jsxs)(t.td,{children:[`Количество дней включительно или `,(0,c.jsx)(t.code,{children:`null`}),`.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`isValidDate`}),`, `,(0,c.jsx)(t.code,{children:`isDateRangeTuple`}),`, `,(0,c.jsx)(t.code,{children:`cloneDate`}),`, `,(0,c.jsx)(t.code,{children:`orderDates`})]}),(0,c.jsx)(t.td,{children:`Низкоуровневые guards и операции диапазона.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`normalizeDateRangeReferenceDate`}),`, `,(0,c.jsx)(t.code,{children:`resolveTodayRange`}),`, `,(0,c.jsx)(t.code,{children:`resolveYesterdayRange`}),`, `,(0,c.jsx)(t.code,{children:`resolveMonthAgoRange`}),`, `,(0,c.jsx)(t.code,{children:`resolveMonthStartToTodayRange`}),`, `,(0,c.jsx)(t.code,{children:`resolveMonthStartToYesterdayRange`})]}),(0,c.jsxs)(t.td,{children:[`Относительные диапазоны от `,(0,c.jsx)(t.code,{children:`{ referenceDate }`}),`; на первом дне месяца «по вчера» не создаёт инверсию.`]})]})]})]}),`
`,(0,c.jsxs)(t.p,{children:[`Публичные типы диапазонов: `,(0,c.jsx)(t.code,{children:`CalendarPeriod`}),`, `,(0,c.jsx)(t.code,{children:`CalendarPeriodOptions`}),`,
`,(0,c.jsx)(t.code,{children:`CalendarPeriodDateBounds`}),`, `,(0,c.jsx)(t.code,{children:`CalendarPeriodSelectionMode`}),`,
`,(0,c.jsx)(t.code,{children:`CalendarWeekEndDay`}),`, `,(0,c.jsx)(t.code,{children:`DateRange`}),`, `,(0,c.jsx)(t.code,{children:`NullableDateRange`}),`, `,(0,c.jsx)(t.code,{children:`DateRangeInput`}),`,
`,(0,c.jsx)(t.code,{children:`DateRangeTimeMode`}),`, `,(0,c.jsx)(t.code,{children:`NormalizeDateRangeOptions`}),`, `,(0,c.jsx)(t.code,{children:`DateRangeReferenceContext`}),`.`]}),`
`,(0,c.jsx)(t.h3,{id:`учебный-календарь`,children:`Учебный календарь`}),`
`,(0,c.jsxs)(t.p,{children:[`Для образовательной модели доступны `,(0,c.jsx)(t.code,{children:`EducationDateKey`}),` (`,(0,c.jsx)(t.code,{children:`YYYY-MM-DD`}),`),
`,(0,c.jsx)(t.code,{children:`EducationYearRange`}),` и `,(0,c.jsx)(t.code,{children:`EducationWeekRange`}),`.`]}),`
`,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`API`}),(0,c.jsx)(t.th,{children:`Поведение`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`parseEducationDateKey`}),`, `,(0,c.jsx)(t.code,{children:`createEducationDateTime`})]}),(0,c.jsxs)(t.td,{children:[`Возвращают `,(0,c.jsx)(t.code,{children:`Date | null`}),` при неверном ключе или времени.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`formatEducationDateKey`}),`, `,(0,c.jsx)(t.code,{children:`formatEducationTimeKey`})]}),(0,c.jsxs)(t.td,{children:[`Создают стабильные локальные ключи `,(0,c.jsx)(t.code,{children:`YYYY-MM-DD`}),` и `,(0,c.jsx)(t.code,{children:`HH:mm`}),`.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`getEducationYear`}),`, `,(0,c.jsx)(t.code,{children:`getEducationYearRange`}),`, `,(0,c.jsx)(t.code,{children:`isEducationDateInCurrentYear`})]}),(0,c.jsx)(t.td,{children:`Учебный год: 1 сентября — 31 августа.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`getEducationWeekStartDate`}),`, `,(0,c.jsx)(t.code,{children:`getEducationWeekRange`}),`, `,(0,c.jsx)(t.code,{children:`getEducationWeekDays`}),`, `,(0,c.jsx)(t.code,{children:`getCurrentEducationWeekKey`})]}),(0,c.jsx)(t.td,{children:`Учебная неделя: понедельник — суббота; воскресенье относится к следующей.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`normalizeEducationWeekKey`}),`, `,(0,c.jsx)(t.code,{children:`resolveEducationWeekKey`}),`, `,(0,c.jsx)(t.code,{children:`isCurrentEducationWeek`})]}),(0,c.jsxs)(t.td,{children:[`Невалидный или вне текущего учебного года ключ даёт `,(0,c.jsx)(t.code,{children:`undefined`}),`; `,(0,c.jsx)(t.code,{children:`resolve…`}),` вместо этого возвращает текущую неделю.`]})]})]})]}),`
`,(0,c.jsx)(t.h2,{id:`числа`,children:`Числа`}),`
`,(0,c.jsx)(t.h3,{id:`форматирование-и-пресеты`,children:`Форматирование и пресеты`}),`
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`import {
	formatNumber,
	formatNumberAsDecimal2,
	formatNumberAsIntegerOrEmpty,
	registerNumberPreset
} from "@ryuzaki13/react-foundation-lib/formatters";

formatNumberAsDecimal2(12345.6); // "12\xA0345,60" в ru-RU
formatNumberAsIntegerOrEmpty("0"); // ""

registerNumberPreset({
	name: "quantity-4",
	decimals: 4,
	grouping: false
});

formatNumber(12.5, "quantity-4"); // "12,5000"
`})}),`
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`formatNumber(value: unknown, presetOrName: string | NumberFormatPreset): string;
`})}),`
`,(0,c.jsxs)(t.p,{children:[`Форматирование использует `,(0,c.jsx)(t.code,{children:`Intl.NumberFormat("ru-RU")`}),`. Пустая строка,
`,(0,c.jsx)(t.code,{children:`NaN`}),`, `,(0,c.jsx)(t.code,{children:`Infinity`}),` и значения, которые `,(0,c.jsx)(t.code,{children:`Number(value)`}),` не может привести к
конечному числу, возвращают строку `,(0,c.jsx)(t.code,{children:`"0"`}),`. Неизвестное строковое имя пресета
выбрасывает `,(0,c.jsx)(t.code,{children:`Error`}),`.`]}),`
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`formatNumber`}),` не является SAP-парсером: переданная строка `,(0,c.jsx)(t.code,{children:`"1 234,5"`}),` не
обязана быть принята `,(0,c.jsx)(t.code,{children:`Number`}),`. Для такого входа сначала используйте
`,(0,c.jsx)(t.code,{children:`toFiniteNumber`}),` или `,(0,c.jsx)(t.code,{children:`parseNumber`}),`.`]}),`
`,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`API`}),(0,c.jsx)(t.th,{children:`Поведение`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`formatNumberAsInteger`}),`, `,(0,c.jsx)(t.code,{children:`formatNumberAsCurrency`}),`, `,(0,c.jsx)(t.code,{children:`formatNumberAsPrice`})]}),(0,c.jsx)(t.td,{children:`Встроенные пресеты с нулевой дробной частью. Валютный знак не добавляется.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`formatNumberAsDecimal`}),`, `,(0,c.jsx)(t.code,{children:`formatNumberAsDecimal2`}),`, `,(0,c.jsx)(t.code,{children:`formatNumberAsDecimal3`})]}),(0,c.jsx)(t.td,{children:`Один, два или три знака после запятой.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`formatNumberAsPercent`}),`, `,(0,c.jsx)(t.code,{children:`formatNumberAsTonnage`})]}),(0,c.jsxs)(t.td,{children:[`Встроенные пресеты с двумя и одним знаком соответственно; знак `,(0,c.jsx)(t.code,{children:`%`}),` не добавляется.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`formatNumberAsIntegerOrEmpty`}),`, `,(0,c.jsx)(t.code,{children:`formatNumberAsCurrencyOrEmpty`}),`, `,(0,c.jsx)(t.code,{children:`formatNumberAsDecimalOrEmpty`}),`, `,(0,c.jsx)(t.code,{children:`formatNumberAsDecimal2OrEmpty`}),`, `,(0,c.jsx)(t.code,{children:`formatNumberAsDecimal3OrEmpty`}),`, `,(0,c.jsx)(t.code,{children:`formatNumberAsPercentOrEmpty`}),`, `,(0,c.jsx)(t.code,{children:`formatNumberAsPriceOrEmpty`}),`, `,(0,c.jsx)(t.code,{children:`formatNumberAsTonnageOrEmpty`})]}),(0,c.jsxs)(t.td,{children:[`Сначала проверяют семантический ноль; для него возвращают `,(0,c.jsx)(t.code,{children:`""`}),`, иначе используют одноимённый форматтер.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`truncateNumber(number, decimals)`})}),(0,c.jsx)(t.td,{children:`Усечение дробной части математически, без форматирования и без проверки аргументов.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`clearFormatCache()`})}),(0,c.jsxs)(t.td,{children:[`Очищает module-scoped кеш `,(0,c.jsx)(t.code,{children:`Intl.NumberFormat`}),`; обычно нужен только для тестов или смены изолированного окружения.`]})]})]})]}),`
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`DEFAULT_NUMBER_PRESET_NAMES`}),` содержит: `,(0,c.jsx)(t.code,{children:`integer`}),`, `,(0,c.jsx)(t.code,{children:`decimal`}),`, `,(0,c.jsx)(t.code,{children:`decimal-2`}),`,
`,(0,c.jsx)(t.code,{children:`decimal-3`}),`, `,(0,c.jsx)(t.code,{children:`currency`}),`, `,(0,c.jsx)(t.code,{children:`price`}),`, `,(0,c.jsx)(t.code,{children:`percent`}),`, `,(0,c.jsx)(t.code,{children:`tonnage`}),`,
`,(0,c.jsx)(t.code,{children:`compact-currency`}),`, `,(0,c.jsx)(t.code,{children:`compact-currency-round`}),`, `,(0,c.jsx)(t.code,{children:`compact-percent`}),`,
`,(0,c.jsx)(t.code,{children:`compact-percent-round`}),`, `,(0,c.jsx)(t.code,{children:`compact-tonnage`}),`, `,(0,c.jsx)(t.code,{children:`compact-tonnage-round`}),`.
Компактность задаётся через поле `,(0,c.jsx)(t.code,{children:`compact`}),` самого пресета: при значении от
1000 по умолчанию используются суффиксы `,(0,c.jsx)(t.code,{children:`тыс`}),`, `,(0,c.jsx)(t.code,{children:`млн`}),`, `,(0,c.jsx)(t.code,{children:`млрд`}),`, `,(0,c.jsx)(t.code,{children:`трлн`}),`.`]}),`
`,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`API / тип`}),(0,c.jsx)(t.th,{children:`Назначение`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`NUMBER_FORMAT_DEFAULTS`})}),(0,c.jsxs)(t.td,{children:[`Базовые значения: один знак, `,(0,c.jsx)(t.code,{children:`,`}),`, группировка ru-RU, размер группы 3.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`NumberFormatPreset`}),`, `,(0,c.jsx)(t.code,{children:`NumberFormatPresetConfig`})]}),(0,c.jsx)(t.td,{children:`Контракт пресета и конфигурации регистрации.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`NumberFormatCompactOptions`}),`, `,(0,c.jsx)(t.code,{children:`NumberFormatCompactUnit`}),`, `,(0,c.jsx)(t.code,{children:`NumberFormatCompactRoundingMode`})]}),(0,c.jsxs)(t.td,{children:[`Настройки compact-представления: минимум, дробная часть, режим `,(0,c.jsx)(t.code,{children:`round`}),` / `,(0,c.jsx)(t.code,{children:`floor`}),` / `,(0,c.jsx)(t.code,{children:`ceil`}),` / `,(0,c.jsx)(t.code,{children:`trunc`}),`, суффиксы и единицы.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`getNumberPreset(name)`}),`, `,(0,c.jsx)(t.code,{children:`getNumberPresetNames()`})]}),(0,c.jsxs)(t.td,{children:[`Чтение пресета или `,(0,c.jsx)(t.code,{children:`undefined`}),`, список имён.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`registerNumberPreset(config)`})}),(0,c.jsxs)(t.td,{children:[`Регистрирует или перезаписывает пресет, дополняя отсутствующие поля `,(0,c.jsx)(t.code,{children:`NUMBER_FORMAT_DEFAULTS`}),`.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`resetNumberPresets()`})}),(0,c.jsx)(t.td,{children:`Возвращает только встроенные пресеты; не вызывайте в работающем приложении.`})]})]})]}),`
`,(0,c.jsx)(t.h3,{id:`разбор-и-проверки`,children:`Разбор и проверки`}),`
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`import { isPositiveValue, parseNumber, toFiniteNumber, toPositiveInteger } from "@ryuzaki13/react-foundation-lib/formatters";

toFiniteNumber("1\xA0234,50"); // 1234.5
parseNumber("не число"); // 0
toPositiveInteger("12"); // 12
isPositiveValue("0"); // false
`})}),`
`,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`API`}),(0,c.jsx)(t.th,{children:`Fallback`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`toFiniteNumber(value)`})}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`number | undefined`}),`. Поддерживает пробелы, NBSP, узкий NBSP и `,(0,c.jsx)(t.code,{children:`'`}),` как группировку; запятую как десятичный разделитель.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`parseNumber(value)`})}),(0,c.jsxs)(t.td,{children:[`Как `,(0,c.jsx)(t.code,{children:`toFiniteNumber`}),`, но возвращает `,(0,c.jsx)(t.code,{children:`0`}),` вместо `,(0,c.jsx)(t.code,{children:`undefined`}),`.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`toPositiveInteger(value)`})}),(0,c.jsxs)(t.td,{children:[`Положительное целое или `,(0,c.jsx)(t.code,{children:`undefined`}),`.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`isPositiveValue(value)`})}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`true`}),` только для конечного значения строго больше нуля.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`isZeroValue(value)`})}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`true`}),` для значений, семантически равных нулю; используется вариантами `,(0,c.jsx)(t.code,{children:`…OrEmpty`}),`.`]})]})]})]}),`
`,(0,c.jsx)(t.h2,{id:`строки`,children:`Строки`}),`
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`import { formatRussianPlural } from "@ryuzaki13/react-foundation-lib/formatters";

const elementForms = {
	one: "элемент",
	few: "элемента",
	many: "элементов"
};

formatRussianPlural(1, elementForms); // "1 элемент"
formatRussianPlural(2, elementForms); // "2 элемента"
formatRussianPlural(7, elementForms); // "7 элементов"
`})}),`
`,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`API`}),(0,c.jsx)(t.th,{children:`Вход, результат и fallback`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`selectRussianPluralForm(value, forms)`})}),(0,c.jsxs)(t.td,{children:[`Выбирает полную русскую форму `,(0,c.jsx)(t.code,{children:`one`}),`, `,(0,c.jsx)(t.code,{children:`few`}),`, `,(0,c.jsx)(t.code,{children:`many`}),` или `,(0,c.jsx)(t.code,{children:`other`}),`; для дробного значения без `,(0,c.jsx)(t.code,{children:`other`}),` использует `,(0,c.jsx)(t.code,{children:`few`}),`.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`formatRussianPlural(value, forms)`})}),(0,c.jsx)(t.td,{children:`Возвращает исходное количество и выбранную форму через пробел; не округляет и не форматирует число отдельно.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`normalizeText(value)`})}),(0,c.jsxs)(t.td,{children:[`Обрезанная непустая строка или `,(0,c.jsx)(t.code,{children:`undefined`}),` для нестрокового/пустого значения.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`normalizeTextWithFallback(value, fallback = "")`})}),(0,c.jsx)(t.td,{children:`Нормализованный текст или указанный fallback.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`normalizeRequiredText(value)`})}),(0,c.jsxs)(t.td,{children:[`Нормализованный текст или `,(0,c.jsx)(t.code,{children:`""`}),`.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`normalizeTextToLower(value)`})}),(0,c.jsxs)(t.td,{children:[`Нормализованный текст в нижнем регистре или `,(0,c.jsx)(t.code,{children:`""`}),`.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`normalizeTextSpaces(value)`})}),(0,c.jsx)(t.td,{children:`Убирает пробелы по краям и сворачивает пробельные символы, NBSP и узкие NBSP в один обычный пробел.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`toSafeString(value)`})}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`""`}),` для `,(0,c.jsx)(t.code,{children:`null`}),`/`,(0,c.jsx)(t.code,{children:`undefined`}),`, иначе `,(0,c.jsx)(t.code,{children:`String(value)`}),`.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`stripInnerSpaces(value)`})}),(0,c.jsx)(t.td,{children:`Удаляет только обычные, неразрывные и узкие неразрывные пробелы внутри строки.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`stripLeadingZeros(value)`})}),(0,c.jsx)(t.td,{children:`Для целых цифровых строк удаляет ведущие нули, оставляя один ноль; поддерживает минус. Нечисловая строка возвращается с обрезанными краями.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`startsWithIgnoringZeros(value, searchText)`})}),(0,c.jsx)(t.td,{children:`Case-insensitive проверка префикса после удаления ведущих нулей у обеих строк.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`truncateText(value, maxLength)`})}),(0,c.jsxs)(t.td,{children:[`Обрезает нормализованный текст и добавляет `,(0,c.jsx)(t.code,{children:`...`}),`; пустой/невалидный текст даёт `,(0,c.jsx)(t.code,{children:`undefined`}),`.`]})]})]})]}),`
`,(0,c.jsx)(t.h2,{id:`логические-значения-abap`,children:`Логические значения ABAP`}),`
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`import { parseAbapBoolean, parseBoolean, toAbapBoolean } from "@ryuzaki13/react-foundation-lib/formatters";

parseAbapBoolean("X"); // true
parseBoolean("true"); // true
toAbapBoolean(false); // " "
`})}),`
`,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`API`}),(0,c.jsx)(t.th,{children:`Поведение`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`parseAbapBoolean(value)`})}),(0,c.jsxs)(t.td,{children:[`Возвращает `,(0,c.jsx)(t.code,{children:`true`}),` только для строкового точного `,(0,c.jsx)(t.code,{children:`"X"`}),`; всё остальное — `,(0,c.jsx)(t.code,{children:`false`}),`.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`parseBoolean(value)`})}),(0,c.jsxs)(t.td,{children:[`Для строк регистронезависимо принимает `,(0,c.jsx)(t.code,{children:`"true"`}),`, `,(0,c.jsx)(t.code,{children:`"x"`}),`, `,(0,c.jsx)(t.code,{children:`"1"`}),`; для остальных значений использует JS truthiness.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`toAbapBoolean(value)`})}),(0,c.jsxs)(t.td,{children:[`Возвращает ABAP `,(0,c.jsx)(t.code,{children:`"X"`}),` или `,(0,c.jsx)(t.code,{children:`" "`}),`. Строка `,(0,c.jsx)(t.code,{children:`"0"`}),` — ложь; любая другая строка, включая `,(0,c.jsx)(t.code,{children:`""`}),`, — истина.`]})]})]})]}),`
`,(0,c.jsx)(t.h2,{id:`фио-телефон-и-ведущие-нули`,children:`ФИО, телефон и ведущие нули`}),`
`,(0,c.jsx)(t.h3,{id:`фио-и-телефон`,children:`ФИО и телефон`}),`
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`import { clearPhone, formatFullName, formatPhone, formatShortName } from "@ryuzaki13/react-foundation-lib/formatters";

formatFullName("  иванов   иван иванович "); // "Иванов Иван Иванович"
formatShortName("иванов иван иванович"); // "Иванов И.И."
formatPhone("8 (912) 345-67-89"); // "+7 (912) 345-67-89"
`})}),`
`,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`API`}),(0,c.jsx)(t.th,{children:`Ограничения и fallback`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`formatFullName(fullName)`})}),(0,c.jsx)(t.td,{children:`Нормализует пробелы, нижний регистр и регистр первых трёх частей. Это presentation helper, а не валидатор ФИО; дополнительные части игнорируются.`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`formatShortName(fullName)`})}),(0,c.jsxs)(t.td,{children:[`Показывает фамилию и одну/две инициалы. Пустая строка даёт `,(0,c.jsx)(t.code,{children:`""`}),`.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`clearPhone(number)`})}),(0,c.jsxs)(t.td,{children:[`Оставляет цифры, ограничивает ввод первыми 11 цифрами, приводит начальный `,(0,c.jsx)(t.code,{children:`7`}),`/`,(0,c.jsx)(t.code,{children:`8`}),` к `,(0,c.jsx)(t.code,{children:`+7`}),`. Предназначен для российских номеров.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`formatPhone(number)`})}),(0,c.jsxs)(t.td,{children:[`Форматирует только полный нормализованный номер `,(0,c.jsx)(t.code,{children:`+7`}),` и 10 цифр. Если после очистки номер неполный, возвращает исходную строку без изменений.`]})]})]})]}),`
`,(0,c.jsx)(t.h3,{id:`числовые-идентификаторы`,children:`Числовые идентификаторы`}),`
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`import { normalizeLeadingZeros, normalizeLeadingZerosStrict } from "@ryuzaki13/react-foundation-lib/formatters";

normalizeLeadingZeros("0012", 5); // "00012"
normalizeLeadingZerosStrict("0012", -1); // "12"
normalizeLeadingZerosStrict("12,5", 4); // "0012,5"
`})}),`
`,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`API`}),(0,c.jsx)(t.th,{children:`Поведение`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`normalizeLeadingZeros(value, fixed?)`})}),(0,c.jsxs)(t.td,{children:[`Приводит конечное числовое значение через `,(0,c.jsx)(t.code,{children:`Number`}),` к строке; при `,(0,c.jsx)(t.code,{children:`fixed > 0`}),` дополняет целую часть нулями. Нечисловое/бесконечное значение возвращает как есть. Поэтому этот вариант может изменить строковое представление и тип результата.`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`normalizeLeadingZerosStrict(value, fixed?)`})}),(0,c.jsxs)(t.td,{children:[`Сохраняет тип `,(0,c.jsx)(t.code,{children:`T`}),`: при `,(0,c.jsx)(t.code,{children:`fixed`}),` отсутствующем, нулевом или не конечном — no-op; при `,(0,c.jsx)(t.code,{children:`fixed < 0`}),` удаляет нули в целой части строки, при `,(0,c.jsx)(t.code,{children:`fixed > 0`}),` дополняет. Не распознанная числовая строка возвращается без изменений. Для `,(0,c.jsx)(t.code,{children:`number`}),` ведущие нули представить невозможно, поэтому результат остаётся числом.`]})]})]})]}),`
`,(0,c.jsxs)(t.p,{children:[`Для пользовательского draft не вызывайте нормализацию во время ввода. Храните
буквальное значение, а `,(0,c.jsx)(t.code,{children:`normalizeLeadingZerosStrict`}),` применяйте только на
явной границе сохранения или восстановления, если это действительно часть
контракта данных.`]})]})}function s(e={}){let{wrapper:t}={...n(),...e.components};return t?(0,c.jsx)(t,{...e,children:(0,c.jsx)(o,{...e})}):o(e)}var c;function l(){return(l=e((()=>{c=t(),r(),a()})))()}l();export{s as default};