@ryuzaki13/react-foundation-lib 1.2.5 → 1.2.7

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.
Files changed (47) hide show
  1. package/dist/array/index.js +1 -1
  2. package/dist/chunks/{array-BBSjoTRy.js → array-D-_yMMUK.js} +2 -2
  3. package/dist/chunks/{array-BBSjoTRy.js.map → array-D-_yMMUK.js.map} +1 -1
  4. package/dist/chunks/{formatters--mhLir82.js → formatters-ShRrKmg6.js} +67 -71
  5. package/dist/chunks/{formatters--mhLir82.js.map → formatters-ShRrKmg6.js.map} +1 -1
  6. package/dist/chunks/{odata-service-DnPlNGpU.js → odata-service-B5w4YBao.js} +13 -17
  7. package/dist/chunks/{odata-service-DnPlNGpU.js.map → odata-service-B5w4YBao.js.map} +1 -1
  8. package/dist/chunks/{validate-nWY_Mla5.js → validate-BzjCBUqb.js} +14 -18
  9. package/dist/chunks/{validate-nWY_Mla5.js.map → validate-BzjCBUqb.js.map} +1 -1
  10. package/dist/error-report/index.js +2 -2
  11. package/dist/excel/index.js +3 -3
  12. package/dist/excel/index.js.map +1 -1
  13. package/dist/formatters/index.js +4 -4
  14. package/dist/hooks/index.js +82 -81
  15. package/dist/hooks/index.js.map +1 -1
  16. package/dist/media/index.js +2 -1
  17. package/dist/media/index.js.map +1 -1
  18. package/dist/number-scale/index.js +1 -1
  19. package/dist/number-scale/index.js.map +1 -1
  20. package/dist/odata-service/index.js +1 -1
  21. package/dist/pwa/index.js +1 -1
  22. package/dist/pwa/index.js.map +1 -1
  23. package/dist/pwa/sw-cache-policy.js +3 -3
  24. package/dist/pwa/sw-cache-policy.js.map +1 -1
  25. package/dist/query-client/index.js +5 -5
  26. package/dist/query-client/index.js.map +1 -1
  27. package/dist/range-output/index.js +1 -1
  28. package/dist/range-output/index.js.map +1 -1
  29. package/dist/table/index.js +3 -3
  30. package/dist/table/index.js.map +1 -1
  31. package/dist/tree-table/index.js +1 -1
  32. package/package.json +33 -33
  33. package/src/docs/browserAndReact.mdx +150 -0
  34. package/src/docs/filesAndExcel.mdx +163 -0
  35. package/src/docs/formatters-runtime.mdx +455 -0
  36. package/src/docs/formatters.mdx +363 -0
  37. package/src/docs/odataAndTables.mdx +178 -0
  38. package/src/docs/pureUtilities.mdx +96 -0
  39. package/src/docs/runtimeAndState.mdx +155 -0
  40. package/src/foundationLib.mdx +105 -0
  41. package/src/file/file.mdx +0 -6
  42. package/src/formatters/date/date.mdx +0 -6
  43. package/src/formatters/number/number.mdx +0 -6
  44. package/src/formatters/valueState/valueState.mdx +0 -6
  45. package/src/formulas/formulas.mdx +0 -6
  46. package/src/pwa/pwa.mdx +0 -6
  47. package/src/query-client/queryClient.mdx +0 -6
@@ -0,0 +1,96 @@
1
+ import { Meta } from "@storybook/addon-docs/blocks";
2
+
3
+ <Meta title="Foundation Lib/Чистые utilities и contracts" />
4
+
5
+ # Чистые utilities и contracts
6
+
7
+ Эти API не создают global state и обычно не требуют React. Они полезны в entity/feature code, если задача остаётся предметно-независимой. Не переносите в них доменные правила только ради повторного использования.
8
+
9
+ ## Коллекции, порядок и ограниченная история
10
+
11
+ ```ts
12
+ import { arrayGroupBy, arrayUniqueBy, moveArrayItem } from "@ryuzaki13/react-foundation-lib/array";
13
+ import { pushBoundedCopyStackItem } from "@ryuzaki13/react-foundation-lib/bounded-copy-stack";
14
+ ```
15
+
16
+ | API | Поведение |
17
+ | ---------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
18
+ | `arrayGroupBy`, `arrayGroupByToArray`, `arrayToMap` | Группируют/индексируют по полю объекта. `arrayToMap` оставляет первое значение ключа. |
19
+ | `arrayUniqueBy`, `arrayDeduplicate` | Immutable deduplication с сохранением первого встретившегося значения/порядка. |
20
+ | `filterAndDeduplicateIds`, `appendMissingIds`, `pickExistingMapValues` | Helpers для stable id lists и ordered Map values. |
21
+ | `arraysEqual` | Строго сравнивает длину, порядок и значения по `===`. |
22
+ | `moveItem`, `moveArrayItem`, `moveArrayItemByIndex` | Возвращают новую переставленную коллекцию; invalid indices не мутируют input. |
23
+ | `normalizeObjects`, `normalizeStringArray`, `addUnique` | Explicit canonicalization для внешней/сохранённой структуры — не вызывайте её внутри literal draft setter. |
24
+
25
+ `pushBoundedCopyStackItem(stack, input, options?)` добавляет/поднимает item по `fingerprint` и ограничивает размер (default `DEFAULT_BOUNDED_COPY_STACK_SIZE = 3`). `getBoundedCopyStackCandidates` фильтрует готовый stack predicate-ом. `BoundedCopyStackItem`, `BoundedCopyStackPushInput`, `BoundedCopyStackOptions` и `BoundedCopyStackPushResult` описывают его serializable contract.
26
+
27
+ ## Значения, шкалы и календарные сегменты
28
+
29
+ ```ts
30
+ import { parseDateSegmentMask, indexedSegmentsToDate } from "@ryuzaki13/react-foundation-lib/date-segments";
31
+ import { snapNumberScaleValue } from "@ryuzaki13/react-foundation-lib/number-scale";
32
+ import { resolveRangeOutputValue } from "@ryuzaki13/react-foundation-lib/range-output";
33
+ ```
34
+
35
+ | Entry point | Основной API |
36
+ | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
37
+ | `date-segments` | `parseDateSegmentMask`, `isEditableDateSegment`, `dateToIndexedSegmentValues`, `areAllDateSegmentsEmpty`, `indexedSegmentsToDate`. `indexedSegmentsToDate` строго отвергает невозможную дату/время; `DateMaskSegment` описывает editable/literal segments. |
38
+ | `number-scale` | `resolveNumberScaleBounds`, `clampNumberScaleValue`, `normalizeNumberScaleStep`, `prepareNumberScaleMarks`, `snapNumberScaleValueToStep`, `snapNumberScaleValueToMarks`, `snapNumberScaleValue`, `valueToNumberScalePercent`, `percentToNumberScaleValue`, `percentToSnappedNumberScaleValue`, `offsetNumberScaleValue`. |
39
+ | `currency` | `resolveCurrencyModeFromODataParameters` и `resolveCurrencyAwareLabel`; это label policy по wrapped OData parameters, не currency formatter. |
40
+ | `range-output` | `readRangeOutputValueFallback` и `resolveRangeOutputValue`; подставляет fallback только для `null` открытой границы и не меняет исходный UI range. |
41
+ | `presets` | `normalizePresetIds`, `resolvePresetOptionsByIds`, `getPresetOption`, `PresetOption`; помогает на save/restore boundary для известного набора IDs. |
42
+ | `string-comparison` | `compareStrings(left, right)` использует fixed Russian numeric/case-insensitive collation с deterministic fallback. |
43
+
44
+ Для date/number UI formatting используйте `formatters`, а не `number-scale`/`currency`.
45
+
46
+ ## Clone, строки, keyboard и trees
47
+
48
+ ```ts
49
+ import { cn, deepCloneWithoutFunctions, deepCopyWithoutFunctions, stableStringify } from "@ryuzaki13/react-foundation-lib/utils";
50
+ ```
51
+
52
+ | API | Контракт |
53
+ | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
54
+ | `cn(...args)` | Собирает className из строк и conditional object. `classNames` — deprecated alias; новый код использует `cn`. |
55
+ | `stableStringify(value)` | JSON-like stable serialization с сортировкой object keys — для key/comparison, не как универсальный persistence format. |
56
+ | `deepCopyWithoutFunctions(value, options?)` | Копирует Date, arrays и plain objects, поддерживает cycles; функции пропускает. Unsupported object бросает `TypeError`. Предназначен для serializable plain config. |
57
+ | `deepCloneWithoutFunctions(value, options?)` | Расширенный clone: Date, RegExp, Map, Set, cycles, sparse arrays и optional prototype. Функции пропускает. |
58
+ | `createLazyComponent`, `childrenCount` | React-adjacent helpers для stable lazy component и correct children count. |
59
+ | `keyboardActivationKeys`, `isKeyboardActivationKey`, `handleKeyboardActivation` | Keyboard activation contract для custom control. |
60
+ | `getRovingFocusTargetIndex`, `findFirstEnabledIndex`, `findLastEnabledIndex`, `findNextEnabledIndex` | Pure navigation для listbox/select с disabled/wrap. |
61
+ | `deepCopyNodes`, `deepCopyTree` | Копирование tree nodes с standard/custom children field. |
62
+ | `toBase64`, `encodeBase64`, `logError` | Unicode-safe base64 и centralised error logging. |
63
+
64
+ Clone не является нормализацией: он создаёт независимую структуру в пределах собственного contract и не должен применять trim, defaults, deduplication или reorder к пользовательскому draft. Для plain serializable config используйте `deepCopyWithoutFunctions`, а не `structuredClone`.
65
+
66
+ ## Runtime guards и базовые типы
67
+
68
+ ```ts
69
+ import { asRecord, isRecord, isSafe, readPositiveInteger } from "@ryuzaki13/react-foundation-lib/validators";
70
+ import type { BaseType, RangeType, RowRecord, State } from "@ryuzaki13/react-foundation-lib/types";
71
+ ```
72
+
73
+ | API | Когда использовать |
74
+ | --------------------------------------------------- | -------------------------------------------------------------------------- |
75
+ | `isSafe` | Убирает только `null`/`undefined` из union. |
76
+ | `isObject`, `isRecord`, `asRecord`, `isPlainObject` | Narrow unknown external value до object/record; array не считается record. |
77
+ | `readPositiveInteger` | Возвращает positive integer или `undefined` без unsafe cast. |
78
+ | `validateUrl` | Возвращает validation result для строки URL. |
79
+ | `IMAGE_EXTENSIONS`, `isImageExtension` | Проверка расширения без учёта регистра; не MIME/security validation. |
80
+ | `isDomReference` | Floating UI reference → DOM `Element` guard. |
81
+
82
+ `State`, `AbapBoolean`, `Primitive`, `BaseType`, `ArrayType`, `ObjectType`, `InputType`, `RangeType`, `RowRecord`, `isBaseType` — общие low-level contracts. Не используйте `RowRecord` как модель конкретной доменной сущности.
83
+
84
+ ## Идентификаторы, HTTP, XML, SEO и form errors
85
+
86
+ | Entry point | API |
87
+ | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
88
+ | `crypto` | `hashString`, `hashString128`, `hashString128Base64Url`, `stringToElementId`, `uuidv4`. Hash служит для stable client key, не криптографической защиты. |
89
+ | `session-storage` | `getSessionStorageId(key, createId?)` — scoped browser-tab id; не authentication token. |
90
+ | `http` | `createNoStoreHeaders(init?)` создаёт Headers с no-store; `createTextHttpResponse(options)` создаёт text `Response`. |
91
+ | `xml` | `escapeXmlValue`, `buildXmlFields`, `getXmlTagText` для небольших XML fragments. Не применяйте regex helper как универсальный XML parser для untrusted complex XML. |
92
+ | `seo` | `createSeoHead(options)`, `createRouteHead(type, path, params)` создают `meta`, `links`, JSON-LD `scripts`; host router/head owner решает, как применить результат. |
93
+ | `form` | `readFirstFormError(errors?)` выбирает первое readable error message из unknown error array. |
94
+ | `error` | `createMissingContextErrorMessage`, `createMissingContextError` формируют единообразную ошибку отсутствующего React Provider. |
95
+
96
+ `fingerprint` и `notifications` описаны на странице Runtime/state, потому что имеют browser/global lifecycle.
@@ -0,0 +1,155 @@
1
+ import { Meta } from "@storybook/addon-docs/blocks";
2
+
3
+ <Meta title="Foundation Lib/Runtime, state и diagnostics" />
4
+
5
+ # Runtime, state и diagnostics
6
+
7
+ Этот раздел содержит инфраструктурные API, которые создаются в composition root host-приложения. Они не должны подключаться из каждой feature: persistence, BroadcastChannel, notifications и error reporting имеют глобальный lifecycle и приватные данные.
8
+
9
+ ## `query-client`: TanStack Query инфраструктура
10
+
11
+ ```ts
12
+ import {
13
+ configureQueryPersistenceProjectAdapter,
14
+ createQueryClient,
15
+ installReactQueryBroadcast,
16
+ installSessionScopedQueryReset,
17
+ persistedQueryMeta,
18
+ resetSessionScopedQueries,
19
+ sessionScopedQueryMeta
20
+ } from "@ryuzaki13/react-foundation-lib/query-client";
21
+ ```
22
+
23
+ ### Composition root
24
+
25
+ 1. До создания `QueryClient` вызовите `configureQueryPersistenceProjectAdapter` при необходимости задать application-specific `persistenceBuster` и `resolveSystemIdentifier`.
26
+ 2. Создайте один `QueryClient` через `createQueryClient({ onQueryError?, onMutationError? })`.
27
+ 3. В browser bootstrap установите sync/reset channels и обязательно сохраните их `cleanup` для shutdown/tests.
28
+
29
+ ```ts
30
+ configureQueryPersistenceProjectAdapter({
31
+ persistenceBuster: "host-v1",
32
+ resolveSystemIdentifier: () => "host-production"
33
+ });
34
+
35
+ const queryClient = createQueryClient({
36
+ onQueryError: (error, query) => reportQueryError(error, query)
37
+ });
38
+
39
+ const broadcast = installReactQueryBroadcast(queryClient, {
40
+ queriesChannel: "host-query-cache",
41
+ eventsChannel: "host-query-events"
42
+ });
43
+ const sessionReset = installSessionScopedQueryReset(queryClient, {
44
+ channelName: "host-session-reset"
45
+ });
46
+
47
+ // teardown: broadcast.cleanup(); sessionReset.cleanup();
48
+ ```
49
+
50
+ ### Persistence, session scope и broadcast
51
+
52
+ | API | Когда использовать |
53
+ | -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
54
+ | `persistedQueryMeta` | `meta` query только для публичных, serializable данных, которым разрешено переживать restart. |
55
+ | `sessionScopedQueryMeta` | `meta` query, чей результат зависит от текущей server session/role. Такой query никогда не сохраняется. |
56
+ | `shouldPersistQuery(query)` | Predicate persistence: true лишь для `persist: true` без `sessionScoped`. |
57
+ | `createIndexedDbQueryStorage(options?)` | Создаёт async IndexedDB storage либо `undefined`, если API недоступен. |
58
+ | `createReactQueryPersister()` | Создаёт TanStack persister с 90-дневным max age или `undefined`. |
59
+ | `installReactQueryBroadcast(queryClient, channels)` | Синхронизирует Query cache и explicit invalidate/set events между вкладками; возвращает `{ broadcast, cleanup }`. |
60
+ | `broadcastCacheEvent(event)` / `setBroadcastFn(fn)` | Imperative bridge для explicit cache event. Настраивается один раз в composition root. |
61
+ | `resetSessionScopedQueries(queryClient, { broadcast? })` | Отменяет, очищает и refetches active session-scoped queries после логина, логаута или смены роли. |
62
+ | `installSessionScopedQueryReset(...)` | Рассылает только команду reset, не query data; возвращает cleanup. |
63
+
64
+ Не отмечайте query обоими meta-флагами. Не кладите в persisted/broadcast cache tokens, персональные данные без принятой политики, DOM nodes, функции или class instances.
65
+
66
+ ### Оптимистичная мутация
67
+
68
+ `onMutateOptimistic`, `onErrorOptimistic`, `onSuccessOptimistic`, `onSettledOptimistic` — low-level helpers для одного известного cache key. `onMutateOptimistic` сначала отменяет запросы, сохраняет `previous`, затем применяет patch. Контекст обязательно передаётся в `onError` для rollback.
69
+
70
+ ```ts
71
+ useMutation({
72
+ mutationFn: updateTodo,
73
+ onMutate: (input) => onMutateOptimistic(queryClient, todoKey, (old) => patchTodo(old, input)),
74
+ onError: (_error, _input, context) => onErrorOptimistic(queryClient, todoKey, context),
75
+ onSettled: () => onSettledOptimistic(queryClient, todoKey, { refetchType: "active" })
76
+ });
77
+ ```
78
+
79
+ `OnSettledOptimisticOptions.refetchType` defaults to `"none"`. Не применяйте helper к непонятно широкому key: cache strategy должен владеть entity/feature, а не shared infrastructure.
80
+
81
+ ## `error-report`: безопасный diagnostic draft
82
+
83
+ ```ts
84
+ import {
85
+ captureQueryErrorReport,
86
+ captureRuntimeErrorReport,
87
+ getErrorReportDrafts,
88
+ installErrorReportBrowserBreadcrumbs,
89
+ setErrorReportRuntimeErrorReporter,
90
+ setErrorReportTransportErrorReporter
91
+ } from "@ryuzaki13/react-foundation-lib/error-report";
92
+ ```
93
+
94
+ Пакет подготавливает, sanitizes и локально сохраняет diagnostic draft. Он **не** отправляет отчёт в backend сам: transport/delivery принадлежит соответствующему API-пакету или host integration.
95
+
96
+ | Группа API | Контракт |
97
+ | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
98
+ | Environment | `isErrorReportingEnabled`, `getErrorReportEnvironment`, `getErrorReportClientEnvironment` дают browser/non-dev gate и минимальный runtime context. |
99
+ | Safe values | `createDiagnosticValue`, `createDataShape`, `sanitizeDetail`, `createErrorInfo` превращают `unknown` в serializable diagnostic form. Не передавайте секреты даже в sanitizing API. |
100
+ | Breadcrumbs | `addErrorReportBreadcrumb`, `getErrorReportBreadcrumbs`, `clearErrorReportBreadcrumbs`, `installErrorReportBrowserBreadcrumbs`. Установка browser listener возвращает cleanup. |
101
+ | Capture | `captureQueryErrorReport`, `captureMutationErrorReport`, `captureRuntimeErrorReport` создают `ErrorReportDraft` с query/mutation/runtime diagnostics. |
102
+ | Drafts | `captureErrorReportDraft`, `getErrorReportDraft`, `getErrorReportDrafts`, `updateErrorReportDraft` управляют локальными draft. |
103
+ | Reporting bridge | `setErrorReportRuntimeErrorReporter` + `reportRuntimeError`; `setErrorReportTransportErrorReporter`, `reportTransportError`, `suppressTransportErrorReport`, `isTransportErrorReportScheduled`. |
104
+ | Diagnostics | `collectQueryDiagnostics`, `collectMutationDiagnostics`, `collectQueryClientDiagnostics`, `collectPersistedQueryDiagnostics`. |
105
+
106
+ ### Подключение reporter-а
107
+
108
+ ```ts
109
+ setErrorReportRuntimeErrorReporter(async (error, context) => {
110
+ const draft = captureRuntimeErrorReport(error, context, queryClient);
111
+ // Передайте draft в owner transport только после собственной privacy policy.
112
+ await deliverDiagnosticDraft(await draft);
113
+ });
114
+ ```
115
+
116
+ `ErrorReportPayload`, `ErrorReportDraft`, `ErrorReportBreadcrumb`, `ErrorReportErrorInfo`, `ErrorReportSafeValue` и context types — публичные contracts для typed delivery. Runtime capture в браузере coalesces одинаковые ошибки на коротком окне, чтобы flood не создавал много draft. Не дублируйте transport report: `capture*` корректно вызывает `suppressTransportErrorReport` для исходной ошибки.
117
+
118
+ ## `notifications`: global imperative facade
119
+
120
+ ```ts
121
+ import { bindNotifications, createNotificationsStore, notify } from "@ryuzaki13/react-foundation-lib/notifications";
122
+ ```
123
+
124
+ ```ts
125
+ const notificationsStore = createNotificationsStore();
126
+ const unbind = bindNotifications(notificationsStore);
127
+
128
+ notify.success("Сохранено");
129
+ const progress = notify.progress("Загрузка…");
130
+ progress.success("Готово");
131
+
132
+ // teardown composition root: unbind();
133
+ ```
134
+
135
+ | API | Назначение |
136
+ | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
137
+ | `createNotificationsStore()` | Создаёт Zustand store с max 6 items и timer cleanup. Вызов только в browser-compatible UI composition. |
138
+ | `bindNotifications(store)` | Связывает единственный store с imperative `notify`; возвращает unbind. До bind любой `notify.*` бросает Error. |
139
+ | `notify.push/upsert/update/dismiss/clear` | Imperative actions над `NotificationPushInput`/`NotificationUpdatePatch`. |
140
+ | `notify.success/info/warning/error` | Удобные typed shortcuts. |
141
+ | `notify.progress(message, opts?)` | Возвращает `{ id, update, success, error, dismiss }` для долгой операции. |
142
+
143
+ `Notification`, `NotificationAction`, `NotificationType`, `NotificationTone`, `NotificationId` описывают данные, а не UI rendering. UI owner подписывается на `NotificationsStoreApi` и отвечает за accessibility/визуал.
144
+
145
+ ## OData collection preferences, session и fingerprint
146
+
147
+ ```ts
148
+ import { odataCollectionConfig, useODataCollectionStore } from "@ryuzaki13/react-foundation-lib/odata";
149
+ import { getSessionStorageId } from "@ryuzaki13/react-foundation-lib/session-storage";
150
+ import { getClientFingerprint } from "@ryuzaki13/react-foundation-lib/fingerprint";
151
+ ```
152
+
153
+ `odataCollectionConfig` даёт selectors для общих UI-defaults (`maxVisibleItems`, min search lengths, debounce); `useODataCollectionStore` даёт state и setters. Это клиентские предпочтения, не backend data и не metadata cache.
154
+
155
+ `getSessionStorageId(key, createId?)` возвращает стабильный ID одной вкладки из `sessionStorage`; при storage failure всё равно вернёт новый ID. `getClientFingerprint()` асинхронно возвращает fingerprint или `null`, если библиотека/API недоступны. Не используйте fingerprint как authentication/authorization credential.
@@ -0,0 +1,105 @@
1
+ import { Meta } from "@storybook/addon-docs/blocks";
2
+
3
+ <Meta title="Foundation Lib/Обзор" />
4
+
5
+ # `@ryuzaki13/react-foundation-lib`
6
+
7
+ Технический фундамент для host-приложений: чистые преобразования данных, browser/React hooks, сериализуемые runtime-контракты, OData metadata helpers и инфраструктура состояния. Пакет не знает домен приложения, UI-компоненты и transport конкретного backend.
8
+
9
+ ## Подключение
10
+
11
+ ```bash
12
+ npm install @ryuzaki13/react-foundation-lib
13
+ ```
14
+
15
+ Пакет ESM и намеренно **не имеет корневого импорта**. Подключайте ровно тот опубликованный subpath, который нужен сценарию:
16
+
17
+ ```ts
18
+ import { formatDateAsDate } from "@ryuzaki13/react-foundation-lib/formatters";
19
+ import { createQueryClient } from "@ryuzaki13/react-foundation-lib/query-client";
20
+ import type { RowRecord } from "@ryuzaki13/react-foundation-lib/types";
21
+ ```
22
+
23
+ ```ts
24
+ // Неверно: корневой entrypoint не опубликован.
25
+ import { formatDateAsDate } from "@ryuzaki13/react-foundation-lib";
26
+ ```
27
+
28
+ ## Граница ответственности
29
+
30
+ | Задача | Использовать | Не использовать вместо этого |
31
+ | ---------------------------------------------------------- | ----------------------------------------- | ------------------------------------ |
32
+ | Чистые OData V2 metadata, path, filter и value helpers | `odata-service` | HTTP/OData transport |
33
+ | Вызовы SAP Gateway, SSO, X-CSRF и TanStack Query operation | `@ryuzaki13/react-foundation-api/odata` | ручной `fetch` или этот пакет |
34
+ | UI primitives и дизайн-система | `@ryuzaki13/react-foundation-ui/<module>` | hooks/utilities из lib как компонент |
35
+ | Доменный mapping и пользовательский сценарий | host entity/feature | foundation-lib |
36
+
37
+ `react-foundation-lib` не создаёт бизнес-правила, не хранит backend snapshot и не заменяет API- или UI-пакеты.
38
+
39
+ ## Среда выполнения и peer dependencies
40
+
41
+ Большинство pure helpers не требуют React. Entry point с React hook, DOM, browser storage или Service Worker должен вызываться только в браузерном runtime и по правилам React hooks. Совместимые peer dependencies должны быть разрешены host-проектом для используемого entrypoint.
42
+
43
+ | Возможность | Когда нужна в host |
44
+ | ----------------------------------------------- | ---------------------------------------------------------------------------- |
45
+ | `react` | `hooks`, `dom`, `copy`, `media`, `pwa`, `three-scene`, selection/table hooks |
46
+ | `@tanstack/react-query`, persistence, broadcast | `query-client`, часть `error-report` |
47
+ | `@tanstack/react-table` | `table` |
48
+ | `@tanstack/react-virtual` | `virtualizer` |
49
+ | `@tanstack/react-router` | search helpers из `hooks` |
50
+ | `@floating-ui/react` | `useFloatingListbox`, DOM reference guards |
51
+ | `@dnd-kit/core`, `@dnd-kit/sortable` | `useDndSortableSensors` |
52
+ | `zustand`, `immer` | `notifications`, OData store |
53
+ | `zod` | `odata-service` schemas |
54
+ | `write-excel-file` | `excel` |
55
+
56
+ ## Выбор entrypoint
57
+
58
+ | Сценарий | Точный import |
59
+ | ---------------------------------------------------- | ----------------------------------------------------- |
60
+ | Массивы, дедупликация, grouping, reorder | `@ryuzaki13/react-foundation-lib/array` |
61
+ | Base64 и `Blob` | `@ryuzaki13/react-foundation-lib/binary` |
62
+ | Ограниченный стек копий | `@ryuzaki13/react-foundation-lib/bounded-copy-stack` |
63
+ | Anchor и state контекстного меню | `@ryuzaki13/react-foundation-lib/context-menu` |
64
+ | Clipboard и feedback hooks | `@ryuzaki13/react-foundation-lib/copy` |
65
+ | Hash и UUID | `@ryuzaki13/react-foundation-lib/crypto` |
66
+ | Валютные labels по OData-параметрам | `@ryuzaki13/react-foundation-lib/currency` |
67
+ | Сегменты маски даты | `@ryuzaki13/react-foundation-lib/date-segments` |
68
+ | Portal, focus, observers, browser download | `@ryuzaki13/react-foundation-lib/dom` |
69
+ | Ошибка отсутствующего React context | `@ryuzaki13/react-foundation-lib/error` |
70
+ | Подготовка и диагностика error report | `@ryuzaki13/react-foundation-lib/error-report` |
71
+ | Excel и экспорт таблиц | `@ryuzaki13/react-foundation-lib/excel` |
72
+ | `FileReader`, MIME, Content-Disposition, изображения | `@ryuzaki13/react-foundation-lib/file` |
73
+ | Client fingerprint | `@ryuzaki13/react-foundation-lib/fingerprint` |
74
+ | Form errors и presets | `@ryuzaki13/react-foundation-lib/form` |
75
+ | Даты, числа, строки, pipeline и value state | `@ryuzaki13/react-foundation-lib/formatters` |
76
+ | Реестр и выполнение клиентских формул таблицы | `@ryuzaki13/react-foundation-lib/formulas` |
77
+ | Общие React hooks | `@ryuzaki13/react-foundation-lib/hooks` |
78
+ | HTTP headers и text `Response` | `@ryuzaki13/react-foundation-lib/http` |
79
+ | Breakpoints и media-query hooks | `@ryuzaki13/react-foundation-lib/media` |
80
+ | Imperative notifications и store | `@ryuzaki13/react-foundation-lib/notifications` |
81
+ | Математика slider/scale | `@ryuzaki13/react-foundation-lib/number-scale` |
82
+ | OData code/text collections и store | `@ryuzaki13/react-foundation-lib/odata` |
83
+ | OData V2 metadata, builder, filters, formats | `@ryuzaki13/react-foundation-lib/odata-service` |
84
+ | Нормализация сохранённых preset ids | `@ryuzaki13/react-foundation-lib/presets` |
85
+ | Service Worker update и cache policy | `@ryuzaki13/react-foundation-lib/pwa` |
86
+ | Только cache policy | `@ryuzaki13/react-foundation-lib/pwa/sw-cache-policy` |
87
+ | QueryClient, persistence, broadcast | `@ryuzaki13/react-foundation-lib/query-client` |
88
+ | Вывод открытых границ диапазона | `@ryuzaki13/react-foundation-lib/range-output` |
89
+ | SEO/head metadata contracts | `@ryuzaki13/react-foundation-lib/seo` |
90
+ | ID в `sessionStorage` | `@ryuzaki13/react-foundation-lib/session-storage` |
91
+ | Предсказуемое строковое сравнение | `@ryuzaki13/react-foundation-lib/string-comparison` |
92
+ | TanStack Table layout, selection и OData adapter | `@ryuzaki13/react-foundation-lib/table` |
93
+ | Проверка доступности Three.js | `@ryuzaki13/react-foundation-lib/three-scene` |
94
+ | Построение tree-table rows | `@ryuzaki13/react-foundation-lib/tree-table` |
95
+ | Общие TypeScript contracts | `@ryuzaki13/react-foundation-lib/types` |
96
+ | Clone, className, keyboard, stable stringify, tree | `@ryuzaki13/react-foundation-lib/utils` |
97
+ | Runtime guards и URL/image validation | `@ryuzaki13/react-foundation-lib/validators` |
98
+ | Infinite-query подгрузка virtualizer | `@ryuzaki13/react-foundation-lib/virtualizer` |
99
+ | XML parse/build | `@ryuzaki13/react-foundation-lib/xml` |
100
+
101
+ ## Как читать справочник
102
+
103
+ Каждая последующая страница построена вокруг **published subpath**, а не каталога исходников. В ней указаны точный import, публичные contracts, обязательная инициализация, результат, lifecycle/cleanup и ограничения. Для pure helpers достаточно вызвать функцию; registry, browser и global-store API требуют отдельного раздела «Инициализация и side effects».
104
+
105
+ Если API не описан как публичный на соответствующей странице, не импортируйте его глубоким путём из `src` или `dist`: это не часть стабильного consumer contract.
package/src/file/file.mdx DELETED
@@ -1,6 +0,0 @@
1
- import { Markdown, Meta } from "@storybook/addon-docs/blocks";
2
- import Readme from './README.md?raw';
3
-
4
- <Meta title="Документация/shared/lib/file" />
5
-
6
- <Markdown >{Readme}</Markdown>
@@ -1,6 +0,0 @@
1
- import { Markdown, Meta } from "@storybook/addon-docs/blocks";
2
- import Readme from './README.md?raw';
3
-
4
- <Meta title="Документация/shared/lib/formatters/date" />
5
-
6
- <Markdown >{Readme}</Markdown>
@@ -1,6 +0,0 @@
1
- import { Markdown, Meta } from "@storybook/addon-docs/blocks";
2
- import Readme from './README.md?raw';
3
-
4
- <Meta title="Документация/shared/lib/formatters/number" />
5
-
6
- <Markdown >{Readme}</Markdown>
@@ -1,6 +0,0 @@
1
- import { Markdown, Meta } from "@storybook/addon-docs/blocks";
2
- import Readme from './README.md?raw';
3
-
4
- <Meta title="Документация/shared/lib/formatters/valueState" />
5
-
6
- <Markdown >{Readme}</Markdown>
@@ -1,6 +0,0 @@
1
- import { Markdown, Meta } from "@storybook/addon-docs/blocks";
2
- import Readme from './README.md?raw';
3
-
4
- <Meta title="Документация/shared/lib/formulas" />
5
-
6
- <Markdown >{Readme}</Markdown>
package/src/pwa/pwa.mdx DELETED
@@ -1,6 +0,0 @@
1
- import { Markdown, Meta } from "@storybook/addon-docs/blocks";
2
- import Readme from './README.md?raw';
3
-
4
- <Meta title="Документация/shared/lib/pwa" />
5
-
6
- <Markdown >{Readme}</Markdown>
@@ -1,6 +0,0 @@
1
- import { Markdown, Meta } from "@storybook/addon-docs/blocks";
2
- import Readme from './README.md?raw';
3
-
4
- <Meta title="Документация/shared/lib/queryClient" />
5
-
6
- <Markdown >{Readme}</Markdown>