@reformer/core 11.0.0-beta.6 → 11.0.0-beta.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 (76) hide show
  1. package/dist/behaviors.js +124 -124
  2. package/dist/create-model-B8U-COv-.js +103 -0
  3. package/dist/en-CjAqn7h0.js +41 -0
  4. package/dist/form/behaviors/internals.d.ts +9 -0
  5. package/dist/form/types/contracts.d.ts +6 -0
  6. package/dist/form/types/validation-schema.d.ts +13 -1
  7. package/dist/form/validation/operators.d.ts +6 -1
  8. package/dist/form/validators/validation-error.d.ts +8 -0
  9. package/dist/i18n/descriptor.d.ts +54 -0
  10. package/dist/i18n/en.json.d.ts +45 -0
  11. package/dist/i18n/loader.d.ts +71 -0
  12. package/dist/i18n/locale-store.d.ts +39 -0
  13. package/dist/i18n/locale.d.ts +90 -0
  14. package/dist/i18n/message-format.d.ts +116 -0
  15. package/dist/i18n/resolve-localized.d.ts +17 -0
  16. package/dist/i18n/ru.json.d.ts +45 -0
  17. package/dist/i18n/translator.d.ts +50 -0
  18. package/dist/i18n/validation-message.d.ts +18 -0
  19. package/dist/i18n.d.ts +31 -0
  20. package/dist/i18n.js +303 -0
  21. package/dist/index-BrNkQj1y.js +105 -0
  22. package/dist/index.js +639 -736
  23. package/dist/loader-Dv_Hl7JC.js +216 -0
  24. package/dist/locale/en.d.ts +2 -0
  25. package/dist/locale/en.js +5 -0
  26. package/dist/locale/en.json +42 -0
  27. package/dist/locale/index.d.ts +18 -0
  28. package/dist/locale/ru.d.ts +2 -0
  29. package/dist/locale/ru.js +41 -0
  30. package/dist/locale/ru.json +42 -0
  31. package/dist/locale.d.ts +2 -0
  32. package/dist/locale.js +9 -0
  33. package/dist/model/create-model.d.ts +17 -3
  34. package/dist/model/index.d.ts +3 -3
  35. package/dist/model/model-signals-proxy.d.ts +25 -0
  36. package/dist/model/types.d.ts +19 -5
  37. package/dist/model-signals-proxy-2vqS243J.js +250 -0
  38. package/dist/model.js +18 -16
  39. package/dist/platforms/react/hooks/types.d.ts +6 -3
  40. package/dist/platforms/react/hooks/useFormControlValue.d.ts +2 -1
  41. package/dist/platforms/react/i18n/context.d.ts +13 -0
  42. package/dist/platforms/react/i18n/hooks.d.ts +59 -0
  43. package/dist/platforms/react/i18n/provider.d.ts +52 -0
  44. package/dist/{strategy-DA3JwxsR.js → strategy-BXS_gBfz.js} +7 -7
  45. package/dist/validation-error-B-U3RsV0.js +11 -0
  46. package/dist/validation.js +1 -1
  47. package/dist/validators/email.js +5 -8
  48. package/dist/validators/future-date.js +8 -11
  49. package/dist/validators/integer.js +4 -7
  50. package/dist/validators/is-date.js +5 -8
  51. package/dist/validators/is-number.js +4 -7
  52. package/dist/validators/max-age.js +8 -11
  53. package/dist/validators/max-date.js +8 -11
  54. package/dist/validators/max-length.js +5 -8
  55. package/dist/validators/max.js +4 -7
  56. package/dist/validators/min-age.js +8 -11
  57. package/dist/validators/min-date.js +8 -11
  58. package/dist/validators/min-length.js +5 -8
  59. package/dist/validators/min.js +4 -7
  60. package/dist/validators/multiple-of.js +5 -8
  61. package/dist/validators/non-negative.js +4 -7
  62. package/dist/validators/non-zero.js +4 -7
  63. package/dist/validators/past-date.js +8 -11
  64. package/dist/validators/pattern.js +5 -8
  65. package/dist/validators/phone.js +6 -9
  66. package/dist/validators/required.js +4 -7
  67. package/dist/validators/url.js +9 -14
  68. package/dist/validators.js +84 -106
  69. package/docs/llms/03-api-signatures.md +6 -0
  70. package/docs/llms/10-arrays.md +30 -0
  71. package/docs/llms/34-i18n.md +272 -0
  72. package/llms-index.json +1 -1
  73. package/llms.txt +1589 -98
  74. package/package.json +22 -3
  75. package/dist/create-model-Dxh9cfLp.js +0 -97
  76. package/dist/model-signals-proxy-mV3WGdlO.js +0 -233
@@ -0,0 +1,250 @@
1
+ import { batch as y, signal as v, Signal as A, computed as w } from "@preact/signals-core";
2
+ const u = /* @__PURE__ */ new WeakMap();
3
+ function R(t) {
4
+ u.set(t, (u.get(t) ?? 0) + 1);
5
+ }
6
+ function D(t) {
7
+ const e = u.get(t);
8
+ e !== void 0 && (e <= 1 ? u.delete(t) : u.set(t, e - 1));
9
+ }
10
+ function _(t) {
11
+ return u.has(t);
12
+ }
13
+ const h = (t) => !(t === null || typeof t != "object" || Array.isArray(t) || t instanceof Date || typeof Blob < "u" && t instanceof Blob || typeof File < "u" && t instanceof File), o = (t, e) => t === "" ? String(e) : `${t}.${e}`, S = (t) => /^\d+$/.test(t), l = (t) => {
14
+ if (Array.isArray(t)) return t.map(l);
15
+ if (h(t)) {
16
+ const e = {};
17
+ for (const r of Object.keys(t)) e[r] = l(t[r]);
18
+ return e;
19
+ }
20
+ return t;
21
+ }, d = (t, e) => {
22
+ if (t === e) return !0;
23
+ if (Array.isArray(t) && Array.isArray(e))
24
+ return t.length !== e.length ? !1 : t.every((r, i) => d(r, e[i]));
25
+ if (h(t) && h(e)) {
26
+ const r = Object.keys(t), i = Object.keys(e);
27
+ return r.length !== i.length ? !1 : r.every((s) => d(t[s], e[s]));
28
+ }
29
+ return !1;
30
+ };
31
+ class j {
32
+ constructor(e, r) {
33
+ this.path = r;
34
+ const i = v(e);
35
+ i.__path = r, this.signal = i, this.initial = l(e);
36
+ }
37
+ kind = "leaf";
38
+ signal;
39
+ initial;
40
+ rebase(e) {
41
+ this.path = e, this.signal.__path = e;
42
+ }
43
+ /** Реактивное чтение (внутри effect/computed создаёт зависимость). */
44
+ read() {
45
+ return this.signal.value;
46
+ }
47
+ /** Нереактивный снимок. */
48
+ peek() {
49
+ return this.signal.peek();
50
+ }
51
+ set(e) {
52
+ this.signal.value = e;
53
+ }
54
+ resetToInitial() {
55
+ this.signal.value = l(this.initial);
56
+ }
57
+ captureInitial() {
58
+ this.initial = l(this.signal.peek());
59
+ }
60
+ dirty() {
61
+ return !d(this.signal.peek(), this.initial);
62
+ }
63
+ }
64
+ class $ {
65
+ constructor(e, r) {
66
+ this.path = r;
67
+ for (const i of Object.keys(e))
68
+ this.children.set(i, c(e[i], o(r, i)));
69
+ }
70
+ kind = "group";
71
+ children = /* @__PURE__ */ new Map();
72
+ rebase(e) {
73
+ this.path = e;
74
+ for (const [r, i] of this.children) i.rebase(o(e, r));
75
+ }
76
+ /** Реактивное чтение поддерева (внутри effect/computed подписывает на все листья группы). */
77
+ read() {
78
+ const e = {};
79
+ for (const [r, i] of this.children) e[r] = i.read();
80
+ return e;
81
+ }
82
+ peek() {
83
+ const e = {};
84
+ for (const [r, i] of this.children) e[r] = i.peek();
85
+ return e;
86
+ }
87
+ set(e) {
88
+ if (e == null || typeof e != "object") return;
89
+ const r = e;
90
+ y(() => {
91
+ for (const [i, s] of this.children)
92
+ i in r && (s.kind === "leaf" && _(s.signal) || s.set(r[i]));
93
+ });
94
+ }
95
+ resetToInitial() {
96
+ y(() => {
97
+ for (const e of this.children.values()) e.resetToInitial();
98
+ });
99
+ }
100
+ captureInitial() {
101
+ for (const e of this.children.values()) e.captureInitial();
102
+ }
103
+ dirty() {
104
+ for (const e of this.children.values()) if (e.dirty()) return !0;
105
+ return !1;
106
+ }
107
+ }
108
+ class x {
109
+ constructor(e, r) {
110
+ this.path = r, this.items = v(e.map((i, s) => c(i, o(r, s)))), this.initial = l(e);
111
+ }
112
+ kind = "array";
113
+ items;
114
+ initial;
115
+ rebase(e) {
116
+ this.path = e, this.items.peek().forEach((r, i) => r.rebase(o(e, i)));
117
+ }
118
+ reindex() {
119
+ this.items.peek().forEach((e, r) => e.rebase(o(this.path, r)));
120
+ }
121
+ push(e) {
122
+ const r = this.items.peek();
123
+ this.items.value = [...r, c(e, o(this.path, r.length))];
124
+ }
125
+ insertAt(e, r) {
126
+ const i = [...this.items.peek()];
127
+ i.splice(e, 0, c(r, o(this.path, e))), this.items.value = i, this.reindex();
128
+ }
129
+ removeAt(e) {
130
+ const r = [...this.items.peek()];
131
+ r.splice(e, 1), this.items.value = r, this.reindex();
132
+ }
133
+ move(e, r) {
134
+ const i = [...this.items.peek()], [s] = i.splice(e, 1);
135
+ s && i.splice(r, 0, s), this.items.value = i, this.reindex();
136
+ }
137
+ swap(e, r) {
138
+ const i = [...this.items.peek()];
139
+ e < 0 || r < 0 || e >= i.length || r >= i.length || e === r || ([i[e], i[r]] = [i[r], i[e]], this.items.value = i, this.reindex());
140
+ }
141
+ clear() {
142
+ this.items.value = [];
143
+ }
144
+ /**
145
+ * Реактивное чтение массива. Читаем `items.value` (а не `.peek()`) — внутри effect/computed это
146
+ * подписка на СОСТАВ массива, поэтому push/removeAt/move ретригерят наравне с правкой элемента.
147
+ */
148
+ read() {
149
+ return this.items.value.map((e) => e.read());
150
+ }
151
+ peek() {
152
+ return this.items.peek().map((e) => e.peek());
153
+ }
154
+ set(e) {
155
+ const r = Array.isArray(e) ? e : [];
156
+ this.items.value = r.map((i, s) => c(i, o(this.path, s)));
157
+ }
158
+ resetToInitial() {
159
+ this.set(l(this.initial));
160
+ }
161
+ captureInitial() {
162
+ this.initial = l(this.peek());
163
+ }
164
+ dirty() {
165
+ return !d(this.peek(), this.initial);
166
+ }
167
+ }
168
+ function c(t, e) {
169
+ return Array.isArray(t) ? new x(t, e) : h(t) ? new $(t, e) : new j(t, e);
170
+ }
171
+ const k = /* @__PURE__ */ new WeakMap();
172
+ function I(t) {
173
+ const e = w(() => t.read());
174
+ return {
175
+ get value() {
176
+ return e.value;
177
+ },
178
+ peek: () => e.peek(),
179
+ subscribe: (r) => e.subscribe(r),
180
+ valueOf: () => e.value,
181
+ toString: () => String(e.value),
182
+ toJSON: () => e.value,
183
+ brand: e.brand
184
+ };
185
+ }
186
+ function b(t) {
187
+ if (t.kind === "leaf") return t.signal;
188
+ const e = k.get(t);
189
+ if (e) return e;
190
+ const r = I(t), i = t.kind === "group", s = (a) => i ? t.children.get(a) : S(a) ? t.items.value[Number(a)] : void 0, g = i ? {} : {
191
+ get length() {
192
+ return t.items.value.length;
193
+ }
194
+ }, m = new Proxy(g, {
195
+ get: (a, n, p) => {
196
+ if (n === "__path") return t.path;
197
+ if (n === "__kind") return t.kind;
198
+ if (typeof n != "string") return Reflect.get(r, n, r);
199
+ const f = s(n);
200
+ return f ? b(f) : !i && Reflect.has(a, n) ? Reflect.get(a, n, p) : Reflect.get(r, n, r);
201
+ },
202
+ set: (a, n, p) => {
203
+ if (!i && n === "value")
204
+ return t.set(p), !0;
205
+ const f = t.path === "" ? "model.$" : `model.$.${t.path}`;
206
+ throw new TypeError(
207
+ `[@reformer/core] ${f}: запись в «${String(n)}» ` + (i ? "узла-группы невозможна — группа читается целиком, а пишется по полям (model.$.<поле>.value) либо через model.patch(...)" : "узла-массива невозможна — массив заменяется целиком через .value, а элемент правится своим сигналом (model.$.<массив>[i].value)")
208
+ );
209
+ },
210
+ has: (a, n) => typeof n == "string" && (s(n) !== void 0 || !i && Reflect.has(a, n)),
211
+ ownKeys: () => i ? [...t.children.keys()] : Reflect.ownKeys(g),
212
+ getOwnPropertyDescriptor: (a, n) => typeof n == "string" && s(n) ? { enumerable: !0, configurable: !0 } : i ? void 0 : Reflect.getOwnPropertyDescriptor(a, n)
213
+ });
214
+ return k.set(t, m), m;
215
+ }
216
+ function P(t) {
217
+ if (t == null || typeof t != "object") return !1;
218
+ const e = t.__kind;
219
+ return e === "group" || e === "array";
220
+ }
221
+ function O(t) {
222
+ return t == null || typeof t != "object" ? !1 : t.__kind === "array";
223
+ }
224
+ function M(t) {
225
+ return t instanceof A || O(t);
226
+ }
227
+ function T(t, e) {
228
+ if (!e) return;
229
+ let r = t;
230
+ for (const i of e.split(".")) {
231
+ if (!r) return;
232
+ if (r.kind === "group") r = r.children.get(i);
233
+ else if (r.kind === "array") r = r.items.peek()[Number(i)];
234
+ else return;
235
+ }
236
+ if (r)
237
+ return r.kind === "leaf" ? r.signal : r.kind === "array" ? b(r) : void 0;
238
+ }
239
+ export {
240
+ $ as G,
241
+ M as a,
242
+ _ as b,
243
+ S as c,
244
+ O as d,
245
+ P as i,
246
+ R as m,
247
+ T as r,
248
+ b as s,
249
+ D as u
250
+ };
package/dist/model.js CHANGED
@@ -1,21 +1,23 @@
1
- import { c as s, e as r } from "./create-model-Dxh9cfLp.js";
2
- import { a as i, i as t, m as c, u as l } from "./model-signals-proxy-mV3WGdlO.js";
3
- import { c as n, a as f, r as m, b as u, d as p, e as b, f as h, s as k, t as v, w as D } from "./behaviors-value-C7dSEhCc.js";
1
+ import { c as s, e as r, a as i } from "./create-model-B8U-COv-.js";
2
+ import { b as o, i as c, a as n, m as t, u as d } from "./model-signals-proxy-2vqS243J.js";
3
+ import { c as m, a as u, r as b, b as h, d as p, e as g, f as k, s as v, t as D, w as F } from "./behaviors-value-C7dSEhCc.js";
4
4
  export {
5
- n as computeFrom,
6
- f as copyFrom,
5
+ m as computeFrom,
6
+ u as copyFrom,
7
7
  s as createModel,
8
8
  r as eachLeafSignal,
9
- i as isDerived,
10
- t as isModelContainerSignal,
11
- c as markDerived,
12
- m as resetWhen,
13
- u as revalidateWhen,
9
+ i as eachValueSignal,
10
+ o as isDerived,
11
+ c as isModelContainerSignal,
12
+ n as isValueSignal,
13
+ t as markDerived,
14
+ b as resetWhen,
15
+ h as revalidateWhen,
14
16
  p as runOutsideEffect,
15
- b as safeCallback,
16
- h as safeDebouncedCallback,
17
- k as syncFields,
18
- v as transformValue,
19
- l as unmarkDerived,
20
- D as watchField
17
+ g as safeCallback,
18
+ k as safeDebouncedCallback,
19
+ v as syncFields,
20
+ D as transformValue,
21
+ d as unmarkDerived,
22
+ F as watchField
21
23
  };
@@ -15,6 +15,7 @@ import { ValidationError } from '../../../form/types/index';
15
15
  *
16
16
  * function TextField({ control }: Props) {
17
17
  * const state = useFormControl(control);
18
+ * const message = useValidationMessage(); // из '@reformer/core/i18n'
18
19
  *
19
20
  * return (
20
21
  * <div>
@@ -24,7 +25,7 @@ import { ValidationError } from '../../../form/types/index';
24
25
  * onChange={e => control.setValue(e.target.value)}
25
26
  * />
26
27
  * {state.shouldShowError && state.errors[0] && (
27
- * <span className="error">{state.errors[0].message}</span>
28
+ * <span className="error">{message(state.errors[0])}</span>
28
29
  * )}
29
30
  * </div>
30
31
  * );
@@ -89,11 +90,12 @@ export interface FieldControlState<T> {
89
90
  * @example
90
91
  * ```tsx
91
92
  * const { errors } = useFormControl(field);
93
+ * const message = useValidationMessage(); // из '@reformer/core/i18n'
92
94
  *
93
95
  * return (
94
96
  * <ul className="error-list">
95
97
  * {errors.map((error, i) => (
96
- * <li key={i}>{error.message}</li>
98
+ * <li key={i}>{message(error)}</li>
97
99
  * ))}
98
100
  * </ul>
99
101
  * );
@@ -152,12 +154,13 @@ export interface FieldControlState<T> {
152
154
  * @example
153
155
  * ```tsx
154
156
  * const { shouldShowError, errors } = useFormControl(field);
157
+ * const message = useValidationMessage(); // из '@reformer/core/i18n'
155
158
  *
156
159
  * return (
157
160
  * <div>
158
161
  * <input {...props} />
159
162
  * {shouldShowError && (
160
- * <span className="error">{errors[0]?.message}</span>
163
+ * <span className="error">{message(errors[0])}</span>
161
164
  * )}
162
165
  * </div>
163
166
  * );
@@ -134,6 +134,7 @@ import { FormValue } from '../../../form/types/index';
134
134
  * // Основной редактор использует useFormControl для полного состояния
135
135
  * function MarkdownEditor({ control }: MarkdownEditorProps) {
136
136
  * const { value, shouldShowError, errors } = useFormControl(control);
137
+ * const message = useValidationMessage(); // из '@reformer/core/i18n'
137
138
  *
138
139
  * return (
139
140
  * <div className="editor-container">
@@ -141,7 +142,7 @@ import { FormValue } from '../../../form/types/index';
141
142
  * value={value}
142
143
  * onChange={e => control.setValue(e.target.value)}
143
144
  * />
144
- * {shouldShowError && <span className="error">{errors[0]?.message}</span>}
145
+ * {shouldShowError && <span className="error">{message(errors[0])}</span>}
145
146
  *
146
147
  * {/* Preview обновляется только при изменении value *}
147
148
  * <MarkdownPreview control={control} />
@@ -0,0 +1,13 @@
1
+ import { I18nHandle } from '../../../i18n/translator';
2
+ /** Имя контекста и одновременно маркер, по которому страж ищет его копии в сборках. */
3
+ export declare const I18N_CONTEXT_MARKER = "ReformerI18nContext";
4
+ /** Что видит компонент: ручка активной локали и состояние её загрузки. */
5
+ export interface I18nContextValue extends I18nHandle {
6
+ /** Идёт загрузка другого языка; на экране пока прежний. Без загрузчика всегда `false`. */
7
+ readonly pending: boolean;
8
+ /** Ошибка последней загрузки языка. */
9
+ readonly error: unknown;
10
+ }
11
+ /** Значение контекста для локали: ручка плюс состояние загрузки. */
12
+ export declare function contextValue(handle: I18nHandle, pending: boolean, error: unknown): I18nContextValue;
13
+ export declare const I18nContext: import('react').Context<I18nContextValue>;
@@ -0,0 +1,59 @@
1
+ import { ValidationError } from '../../../form/types/contracts';
2
+ import { Messages } from '../../../i18n/locale';
3
+ import { MessageValues } from '../../../i18n/message-format';
4
+ import { I18nContextValue } from './context';
5
+ /**
6
+ * Активная локаль: перевод ключей приложения, форматирование чисел, дат и размеров, состояние
7
+ * загрузки языка. Без провайдера — английский с пустым словарём.
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * function LangBadge() {
12
+ * const { code, pending, t } = useI18n();
13
+ * return <span aria-busy={pending}>{t('app.language')}: {code}</span>;
14
+ * }
15
+ * ```
16
+ */
17
+ export declare function useI18n(): I18nContextValue;
18
+ /**
19
+ * Переводчик пакета: ищет ключ в локали провайдера, а при промахе берёт встроенную английскую
20
+ * таблицу этого пакета. Так пакет говорит по-английски без провайдера и не зависит от того, знает
21
+ * ли локаль его ключи. Тип ключа выводится из таблицы — опечатка в ключе не скомпилируется.
22
+ *
23
+ * `defaults` должен быть стабильной ссылкой (импорт JSON-модуля), иначе переводчик будет
24
+ * пересоздаваться на каждый рендер.
25
+ *
26
+ * @param defaults - Встроенная английская таблица пакета.
27
+ * @returns Функция `(ключ, значения?) => строка`; её идентичность меняется вместе с локалью.
28
+ *
29
+ * @example
30
+ * ```tsx
31
+ * import en from './locale/en.json';
32
+ *
33
+ * const useKitMessages = () => useMessages(en);
34
+ *
35
+ * function ClearButton() {
36
+ * const t = useKitMessages();
37
+ * return <button aria-label={t('kit.select.clear')} />;
38
+ * }
39
+ * ```
40
+ */
41
+ export declare function useMessages<D extends Messages>(defaults: D): (key: keyof D & string, values?: MessageValues) => string;
42
+ /**
43
+ * Резолвер текста ошибки валидации по активной локали: `messageKey` автора → явное `message` →
44
+ * словарь локали по коду → встроенный английский → код. Идентичность функции меняется вместе с
45
+ * локалью, поэтому показанные ошибки переводятся при смене языка без повторной валидации.
46
+ *
47
+ * `FormField` из `@reformer/cdk` использует его сам; вызывайте напрямую, если рисуете ошибки
48
+ * своим компонентом.
49
+ *
50
+ * @example
51
+ * ```tsx
52
+ * function FieldErrors({ control }: { control: FieldNode<string> }) {
53
+ * const message = useValidationMessage();
54
+ * const { errors } = useFormControl(control);
55
+ * return <>{errors.map((error) => <span key={error.code}>{message(error)}</span>)}</>;
56
+ * }
57
+ * ```
58
+ */
59
+ export declare function useValidationMessage(): (error: ValidationError) => string;
@@ -0,0 +1,52 @@
1
+ import { ReactElement, ReactNode } from 'react';
2
+ import { FormLocale } from '../../../i18n/locale';
3
+ import { LocaleLoad } from '../../../i18n/locale-store';
4
+ /** Режим «готовая локаль». */
5
+ export interface I18nStaticProviderProps {
6
+ /** Локаль. Смена объекта переключает язык сразу. */
7
+ locale: FormLocale;
8
+ children?: ReactNode;
9
+ }
10
+ /** Режим «провайдер грузит сам». */
11
+ export interface I18nLoadingProviderProps {
12
+ /** Код языка. Смена кода запускает загрузку; до её конца на экране прежний язык. */
13
+ lang: string;
14
+ /** Загрузчик локалей — обычно результат `createLocaleLoader`. */
15
+ load: LocaleLoad;
16
+ /**
17
+ * Что показать, пока не загружена самая первая локаль. По умолчанию — ничего: иначе на кадр
18
+ * мелькнул бы встроенный английский. Если локаль уже в кэше загрузчика (`load.preload(lang)`
19
+ * до монтирования), первый рендер синхронный и `fallback` не показывается.
20
+ */
21
+ fallback?: ReactNode;
22
+ /** Отказ загрузки. Язык на экране при этом не меняется. */
23
+ onError?: (error: unknown, lang: string) => void;
24
+ children?: ReactNode;
25
+ }
26
+ export type I18nProviderProps = I18nStaticProviderProps | I18nLoadingProviderProps;
27
+ /**
28
+ * Провайдер локализации для подписей компонентов, ошибок валидации и авторских подписей формы.
29
+ * Без провайдера компоненты говорят встроенным английским.
30
+ *
31
+ * При смене `lang` на экране остаётся прежний язык, пока новый не загрузится (`useI18n().pending`
32
+ * — для индикатора). При быстром переключении применяется только последний запрос. Вложенный
33
+ * провайдер заменяет локаль для своего поддерева целиком.
34
+ *
35
+ * @example Провайдер грузит локаль сам
36
+ * ```tsx
37
+ * const [lang, setLang] = useState('ru');
38
+ *
39
+ * <I18nProvider lang={lang} load={loadLocale}>
40
+ * <LangSwitch value={lang} onChange={setLang} />
41
+ * <CreditForm />
42
+ * </I18nProvider>
43
+ * ```
44
+ *
45
+ * @example Готовая локаль — SSR и тесты
46
+ * ```tsx
47
+ * import { ru } from '@reformer/ui-kit/locale/ru';
48
+ *
49
+ * <I18nProvider locale={ru}><CreditForm /></I18nProvider>
50
+ * ```
51
+ */
52
+ export declare function I18nProvider(props: I18nProviderProps): ReactElement | null;
@@ -1,5 +1,5 @@
1
1
  import { signal as A, effect as M } from "@preact/signals-core";
2
- import { e as W } from "./create-model-Dxh9cfLp.js";
2
+ import { a as W } from "./create-model-B8U-COv-.js";
3
3
  import { g as v } from "./signal-node-registry-tiwel-TV.js";
4
4
  let g = null;
5
5
  function E(e, n) {
@@ -75,23 +75,23 @@ function z(e) {
75
75
  return e;
76
76
  }
77
77
  const x = /* @__PURE__ */ new WeakMap();
78
- function L(e, n) {
78
+ function P(e, n) {
79
79
  let t = x.get(e);
80
80
  t || x.set(e, t = /* @__PURE__ */ new WeakMap());
81
81
  let r = t.get(n);
82
82
  return r || t.set(n, r = { fields: /* @__PURE__ */ new Set(), ac: null }), r;
83
83
  }
84
- const P = (e) => {
84
+ const T = (e) => {
85
85
  for (const n of e.values()) for (const t of n) if (t.severity !== "warning") return !0;
86
86
  return !1;
87
87
  };
88
- function T(e) {
88
+ function V(e) {
89
89
  return e.aborted ? Promise.resolve() : new Promise((n) => {
90
90
  e.addEventListener("abort", () => n(), { once: !0 });
91
91
  });
92
92
  }
93
93
  async function C(e, n, t) {
94
- const r = L(e, n);
94
+ const r = P(e, n);
95
95
  r.ac?.abort();
96
96
  const o = new AbortController();
97
97
  r.ac = o;
@@ -102,12 +102,12 @@ async function C(e, n, t) {
102
102
  whenStack: [],
103
103
  signal: o.signal
104
104
  };
105
- if (E(a, () => n({ model: e })), a.pending.length && await Promise.race([Promise.all(a.pending), T(o.signal)]), o.signal.aborted) return !1;
105
+ if (E(a, () => n({ model: e })), a.pending.length && await Promise.race([Promise.all(a.pending), V(o.signal)]), o.signal.aborted) return !1;
106
106
  const i = new Set(a.errors.keys());
107
107
  for (const s of r.fields) i.has(s) || v(s)?.setErrors([]);
108
108
  for (const s of i) v(s)?.setErrors(a.errors.get(s) ?? []);
109
109
  if (t?.touch) for (const s of i) v(s)?.markAsTouched();
110
- return r.fields = i, !P(a.errors);
110
+ return r.fields = i, !T(a.errors);
111
111
  }
112
112
  function G(e, n, t = {}) {
113
113
  const { strategy: r = "submit", debounce: o = 0, liveAfterSubmit: a = "change" } = t, i = A(!1);
@@ -0,0 +1,11 @@
1
+ function m(s, e, a) {
2
+ const r = {
3
+ code: s,
4
+ message: e?.message ?? "",
5
+ params: a === void 0 ? e?.params : { ...a, ...e?.params }
6
+ };
7
+ return e?.messageKey !== void 0 && (r.messageKey = e.messageKey), r;
8
+ }
9
+ export {
10
+ m as v
11
+ };
@@ -1,4 +1,4 @@
1
- import { d as s, h as d, c as i, f as l, e as t, v as o, a as c, g as n, b as r } from "./strategy-DA3JwxsR.js";
1
+ import { d as s, h as d, c as i, f as l, e as t, v as o, a as c, g as n, b as r } from "./strategy-BXS_gBfz.js";
2
2
  export {
3
3
  s as apply,
4
4
  d as createFormValidation,
@@ -1,11 +1,8 @@
1
- const s = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
2
- function n(e) {
3
- return (r) => r ? s.test(r) ? null : {
4
- code: "email",
5
- message: e?.message ?? "invalid",
6
- params: e?.params
7
- } : null;
1
+ import { v as n } from "../validation-error-B-U3RsV0.js";
2
+ const i = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
3
+ function o(t) {
4
+ return (r) => r ? i.test(r) ? null : n("email", t) : null;
8
5
  }
9
6
  export {
10
- n as email
7
+ o as email
11
8
  };
@@ -1,19 +1,16 @@
1
- import { p as s, n as l, g as o } from "../date-utils-dTT_x_Be.js";
2
- function i(a) {
1
+ import { p as e, n as i, g as l } from "../date-utils-dTT_x_Be.js";
2
+ import { v as u } from "../validation-error-B-U3RsV0.js";
3
+ function f(n) {
3
4
  return (r) => {
4
5
  if (r == null || r === "")
5
6
  return null;
6
- const e = s(r);
7
- if (e === null)
7
+ const t = e(r);
8
+ if (t === null)
8
9
  return null;
9
- const n = l(e), t = o();
10
- return n < t ? {
11
- code: "date_past",
12
- message: a?.message ?? "invalid",
13
- params: a?.params
14
- } : null;
10
+ const o = i(t), a = l();
11
+ return o < a ? u("date_past", n) : null;
15
12
  };
16
13
  }
17
14
  export {
18
- i as futureDate
15
+ f as futureDate
19
16
  };
@@ -1,10 +1,7 @@
1
- function n(e) {
2
- return (r) => r == null || typeof r != "number" || isNaN(r) || Number.isInteger(r) ? null : {
3
- code: "integer",
4
- message: e?.message ?? "invalid",
5
- params: e?.params
6
- };
1
+ import { v as t } from "../validation-error-B-U3RsV0.js";
2
+ function e(n) {
3
+ return (r) => r == null || typeof r != "number" || isNaN(r) || Number.isInteger(r) ? null : t("integer", n);
7
4
  }
8
5
  export {
9
- n as integer
6
+ e as integer
10
7
  };
@@ -1,11 +1,8 @@
1
- import { p as a } from "../date-utils-dTT_x_Be.js";
2
- function t(e) {
3
- return (r) => r == null || r === "" ? null : a(r) === null ? {
4
- code: "date_invalid",
5
- message: e?.message ?? "invalid",
6
- params: e?.params
7
- } : null;
1
+ import { p as t } from "../date-utils-dTT_x_Be.js";
2
+ import { v as i } from "../validation-error-B-U3RsV0.js";
3
+ function l(n) {
4
+ return (r) => r == null || r === "" ? null : t(r) === null ? i("date_invalid", n) : null;
8
5
  }
9
6
  export {
10
- t as isDate
7
+ l as isDate
11
8
  };
@@ -1,10 +1,7 @@
1
- function n(e) {
2
- return (r) => r == null ? null : typeof r != "number" || isNaN(r) ? {
3
- code: "isNumber",
4
- message: e?.message ?? "invalid",
5
- params: e?.params
6
- } : null;
1
+ import { v as i } from "../validation-error-B-U3RsV0.js";
2
+ function o(n) {
3
+ return (r) => r == null ? null : typeof r != "number" || isNaN(r) ? i("isNumber", n) : null;
7
4
  }
8
5
  export {
9
- n as isNumber
6
+ o as isNumber
10
7
  };