@reformer/ui-kit 5.0.3 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/form-array/form-array-section.d.ts +10 -8
- package/dist/form-array-section-D1c2AQzE.js +107 -0
- package/dist/form-array.js +1 -1
- package/dist/index.js +1 -1
- package/dist/ui/form-field.js +105 -103
- package/llms.txt +11 -8
- package/package.json +1 -1
- package/dist/form-array-section-CItAR061.js +0 -92
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
import { ComponentType, ReactNode } from 'react';
|
|
2
|
-
import { ArrayNode,
|
|
2
|
+
import { ArrayNode, FormArrayProxy, FormProxy } from '@reformer/core';
|
|
3
3
|
import { FieldWrapperProps } from '@reformer/renderer-react';
|
|
4
|
-
export interface FormArraySectionProps<T extends
|
|
5
|
-
/**
|
|
6
|
-
|
|
7
|
-
* FieldPathNode (path.<arrayField>) — в этом случае через `form` + navigator.
|
|
8
|
-
*/
|
|
9
|
-
control: FormArrayProxy<T> | ArrayNode<T> | FieldPathNode<unknown, unknown> | undefined;
|
|
4
|
+
export interface FormArraySectionProps<T extends object> {
|
|
5
|
+
/** Уже-резолвленный ArrayNode/ModelArrayNode/FormArrayProxy. */
|
|
6
|
+
control: FormArrayProxy<T> | ArrayNode<T> | undefined;
|
|
10
7
|
/** React FC получает `control: FormProxy<T>` для каждого элемента. */
|
|
11
8
|
itemComponent: ComponentType<{
|
|
12
9
|
control: FormProxy<T>;
|
|
@@ -39,6 +36,11 @@ export interface FormArraySectionProps<T extends FormFields> {
|
|
|
39
36
|
initialValue?: Partial<T>;
|
|
40
37
|
/** Показывать «Удалить» когда остался один элемент. По умолчанию `false`. */
|
|
41
38
|
showRemoveOnSingle?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Показывать кнопки ↑/↓ для перестановки элементов. По умолчанию `false`
|
|
41
|
+
* (обратная совместимость — существующие массивы не меняются).
|
|
42
|
+
*/
|
|
43
|
+
reorderable?: boolean;
|
|
42
44
|
/** Максимум items — AddButton отключается при достижении. */
|
|
43
45
|
maxItems?: number;
|
|
44
46
|
/** Внешний className секции. */
|
|
@@ -57,4 +59,4 @@ export interface FormArraySectionProps<T extends FormFields> {
|
|
|
57
59
|
*/
|
|
58
60
|
fieldWrapper?: ComponentType<FieldWrapperProps>;
|
|
59
61
|
}
|
|
60
|
-
export declare function FormArraySection<T extends
|
|
62
|
+
export declare function FormArraySection<T extends object>({ control, itemComponent: ItemComponent, title, itemLabel, addButtonLabel, removeButtonLabel, emptyMessage, emptyMessageHint, hasItems, initialValue, showRemoveOnSingle, reorderable, maxItems, className, cardClassName, }: FormArraySectionProps<T>): ReactNode;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { jsx as e, jsxs as r } from "react/jsx-runtime";
|
|
2
|
+
import { useFormControl as _ } from "@reformer/core";
|
|
3
|
+
import { FormArray as o } from "@reformer/cdk/form-array";
|
|
4
|
+
function B(n) {
|
|
5
|
+
return n ? typeof n == "object" && typeof n.push == "function" && typeof n.removeAt == "function" ? n : (typeof console < "u" && console.warn("[FormArraySection] control is not an ArrayNode/FormArrayProxy."), null) : null;
|
|
6
|
+
}
|
|
7
|
+
function E({
|
|
8
|
+
control: n,
|
|
9
|
+
itemComponent: p,
|
|
10
|
+
title: i,
|
|
11
|
+
itemLabel: s,
|
|
12
|
+
addButtonLabel: c = "+ Добавить",
|
|
13
|
+
removeButtonLabel: v = "Удалить",
|
|
14
|
+
emptyMessage: u,
|
|
15
|
+
emptyMessageHint: m,
|
|
16
|
+
hasItems: y,
|
|
17
|
+
initialValue: f,
|
|
18
|
+
showRemoveOnSingle: g = !1,
|
|
19
|
+
reorderable: x = !1,
|
|
20
|
+
maxItems: b,
|
|
21
|
+
className: N = "space-y-3 mt-2",
|
|
22
|
+
cardClassName: w = "mb-4 p-4 bg-white rounded border"
|
|
23
|
+
}) {
|
|
24
|
+
const l = B(n), j = _(
|
|
25
|
+
l ?? void 0
|
|
26
|
+
);
|
|
27
|
+
if (y === !1 || !l) return null;
|
|
28
|
+
const d = j?.length ?? 0, h = b != null && d >= b, A = (a, t) => typeof s == "function" ? s(a, t) : `${s ?? i ?? "Элемент"} #${t + 1}`;
|
|
29
|
+
return /* @__PURE__ */ e(o.Root, { control: l, children: /* @__PURE__ */ r("section", { className: N, children: [
|
|
30
|
+
i ? /* @__PURE__ */ r("div", { className: "flex justify-between items-center mb-4", children: [
|
|
31
|
+
/* @__PURE__ */ e("h3", { className: "text-lg font-semibold", children: i }),
|
|
32
|
+
h ? null : /* @__PURE__ */ e(
|
|
33
|
+
o.AddButton,
|
|
34
|
+
{
|
|
35
|
+
initialValue: f,
|
|
36
|
+
"data-testid": "array-add",
|
|
37
|
+
className: "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-primary text-primary-foreground shadow hover:bg-primary/90 h-9 px-4 py-2",
|
|
38
|
+
children: c
|
|
39
|
+
}
|
|
40
|
+
)
|
|
41
|
+
] }) : null,
|
|
42
|
+
/* @__PURE__ */ e(o.List, { className: "space-y-3", children: ({ control: a, index: t, remove: C, moveUp: $, moveDown: k, canMoveUp: F, canMoveDown: R }) => {
|
|
43
|
+
const S = g || d > 1;
|
|
44
|
+
return /* @__PURE__ */ r("div", { className: w, "data-testid": `array-item-${t}`, children: [
|
|
45
|
+
i || s ? /* @__PURE__ */ r("div", { className: "flex justify-between items-center mb-3", children: [
|
|
46
|
+
/* @__PURE__ */ e("h4", { className: "font-medium", children: A(a, t) }),
|
|
47
|
+
/* @__PURE__ */ r("div", { className: "flex items-center gap-2", children: [
|
|
48
|
+
x ? /* @__PURE__ */ r("div", { className: "flex items-center gap-1", children: [
|
|
49
|
+
/* @__PURE__ */ e(
|
|
50
|
+
"button",
|
|
51
|
+
{
|
|
52
|
+
type: "button",
|
|
53
|
+
onClick: $,
|
|
54
|
+
disabled: !F,
|
|
55
|
+
"aria-label": "Переместить вверх",
|
|
56
|
+
"data-testid": `array-item-${t}-move-up`,
|
|
57
|
+
className: "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-40 border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground h-9 w-9",
|
|
58
|
+
children: "↑"
|
|
59
|
+
}
|
|
60
|
+
),
|
|
61
|
+
/* @__PURE__ */ e(
|
|
62
|
+
"button",
|
|
63
|
+
{
|
|
64
|
+
type: "button",
|
|
65
|
+
onClick: k,
|
|
66
|
+
disabled: !R,
|
|
67
|
+
"aria-label": "Переместить вниз",
|
|
68
|
+
"data-testid": `array-item-${t}-move-down`,
|
|
69
|
+
className: "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-40 border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground h-9 w-9",
|
|
70
|
+
children: "↓"
|
|
71
|
+
}
|
|
72
|
+
)
|
|
73
|
+
] }) : null,
|
|
74
|
+
S ? /* @__PURE__ */ e(
|
|
75
|
+
"button",
|
|
76
|
+
{
|
|
77
|
+
type: "button",
|
|
78
|
+
onClick: C,
|
|
79
|
+
"data-testid": `array-item-${t}-remove`,
|
|
80
|
+
className: "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-destructive text-destructive-foreground shadow hover:bg-destructive/90 h-9 px-4 py-2",
|
|
81
|
+
children: v
|
|
82
|
+
}
|
|
83
|
+
) : null
|
|
84
|
+
] })
|
|
85
|
+
] }) : null,
|
|
86
|
+
/* @__PURE__ */ e(p, { control: a })
|
|
87
|
+
] });
|
|
88
|
+
} }),
|
|
89
|
+
d === 0 && u ? /* @__PURE__ */ e(o.Empty, { children: /* @__PURE__ */ r("div", { className: "p-4 bg-gray-100 border border-gray-300 rounded text-center text-gray-600", children: [
|
|
90
|
+
u,
|
|
91
|
+
m && /* @__PURE__ */ e("div", { className: "mt-2 text-xs text-gray-500", children: m })
|
|
92
|
+
] }) }) : null,
|
|
93
|
+
!i && !h ? /* @__PURE__ */ e("div", { children: /* @__PURE__ */ e(
|
|
94
|
+
o.AddButton,
|
|
95
|
+
{
|
|
96
|
+
initialValue: f,
|
|
97
|
+
"data-testid": "array-add",
|
|
98
|
+
className: "text-sm text-blue-600 hover:text-blue-700 hover:underline",
|
|
99
|
+
children: c
|
|
100
|
+
}
|
|
101
|
+
) }) : null
|
|
102
|
+
] }) });
|
|
103
|
+
}
|
|
104
|
+
E.__selfManagedChildren = !0;
|
|
105
|
+
export {
|
|
106
|
+
E as F
|
|
107
|
+
};
|
package/dist/form-array.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -15,7 +15,7 @@ import { Section as O } from "./ui/section.js";
|
|
|
15
15
|
import { Select as X, SelectContent as Y, SelectGroup as _, SelectItem as $, SelectLabel as ee, SelectScrollDownButton as oe, SelectScrollUpButton as te, SelectTrigger as re, SelectValue as ne } from "./ui/select.js";
|
|
16
16
|
import { Textarea as ie } from "./ui/textarea.js";
|
|
17
17
|
import { E as ae, L as ce } from "./loading-state-4VeOE6iN.js";
|
|
18
|
-
import { F as pe } from "./form-array-section-
|
|
18
|
+
import { F as pe } from "./form-array-section-D1c2AQzE.js";
|
|
19
19
|
import { F as me, a as xe, b as ge, S as ue } from "./form-wizard-C-yRYqTI.js";
|
|
20
20
|
const f = () => /* @__PURE__ */ o(
|
|
21
21
|
"svg",
|
package/dist/ui/form-field.js
CHANGED
|
@@ -1,47 +1,47 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import * as
|
|
3
|
-
import { forwardRef as f, Children as
|
|
4
|
-
import { useFormControl as
|
|
5
|
-
import { Checkbox as
|
|
6
|
-
function
|
|
7
|
-
const l = { ...
|
|
8
|
-
for (const
|
|
9
|
-
const o = r
|
|
10
|
-
|
|
11
|
-
t(...
|
|
12
|
-
} :
|
|
1
|
+
import { jsx as i, jsxs as x, Fragment as w } from "react/jsx-runtime";
|
|
2
|
+
import * as B from "react";
|
|
3
|
+
import { forwardRef as f, Children as L, isValidElement as A, cloneElement as V, useId as W, useMemo as $, createContext as E, useContext as M } from "react";
|
|
4
|
+
import { useFormControl as O } from "@reformer/core";
|
|
5
|
+
import { Checkbox as T } from "./checkbox.js";
|
|
6
|
+
function z(e, n) {
|
|
7
|
+
const l = { ...e };
|
|
8
|
+
for (const r of Object.keys(n)) {
|
|
9
|
+
const o = e[r], t = n[r];
|
|
10
|
+
r.startsWith("on") && typeof o == "function" && typeof t == "function" ? l[r] = (...d) => {
|
|
11
|
+
t(...d), o(...d);
|
|
12
|
+
} : r === "className" && typeof o == "string" && typeof t == "string" ? l[r] = [t, o].filter(Boolean).join(" ") : r === "style" && typeof o == "object" && typeof t == "object" ? l[r] = { ...t, ...o } : r === "disabled" ? l[r] = !!o || !!t : t !== void 0 && (l[r] = t);
|
|
13
13
|
}
|
|
14
14
|
return l;
|
|
15
15
|
}
|
|
16
|
-
const
|
|
17
|
-
({ children:
|
|
18
|
-
const
|
|
19
|
-
if (!
|
|
16
|
+
const b = f(
|
|
17
|
+
({ children: e, ...n }, l) => {
|
|
18
|
+
const r = L.only(e);
|
|
19
|
+
if (!A(r))
|
|
20
20
|
return null;
|
|
21
|
-
const o =
|
|
22
|
-
return
|
|
21
|
+
const o = r.props, t = z(n, o), d = r.ref;
|
|
22
|
+
return V(r, {
|
|
23
23
|
...t,
|
|
24
|
-
ref: l ||
|
|
24
|
+
ref: l || d
|
|
25
25
|
});
|
|
26
26
|
}
|
|
27
27
|
);
|
|
28
|
-
|
|
29
|
-
const k =
|
|
30
|
-
function
|
|
31
|
-
const
|
|
32
|
-
if (!
|
|
28
|
+
b.displayName = "Slot";
|
|
29
|
+
const k = E(null);
|
|
30
|
+
function F() {
|
|
31
|
+
const e = M(k);
|
|
32
|
+
if (!e)
|
|
33
33
|
throw new Error(
|
|
34
34
|
"FormField.* components must be used within <FormField.Root>. Wrap your field with <FormField.Root control={control}>."
|
|
35
35
|
);
|
|
36
|
-
return
|
|
36
|
+
return e;
|
|
37
37
|
}
|
|
38
38
|
function N({
|
|
39
|
-
control:
|
|
39
|
+
control: e,
|
|
40
40
|
children: n,
|
|
41
41
|
id: l,
|
|
42
|
-
hasDescription:
|
|
42
|
+
hasDescription: r = !1
|
|
43
43
|
}) {
|
|
44
|
-
const o =
|
|
44
|
+
const o = W(), t = l ?? o, d = $(
|
|
45
45
|
() => ({
|
|
46
46
|
controlId: `control-${t}`,
|
|
47
47
|
labelId: `label-${t}`,
|
|
@@ -49,97 +49,97 @@ function N({
|
|
|
49
49
|
errorId: `error-${t}`
|
|
50
50
|
}),
|
|
51
51
|
[t]
|
|
52
|
-
), s =
|
|
52
|
+
), s = O(e), c = $(() => {
|
|
53
53
|
const {
|
|
54
54
|
value: h,
|
|
55
55
|
errors: a,
|
|
56
56
|
pending: m,
|
|
57
|
-
disabled:
|
|
58
|
-
valid:
|
|
59
|
-
invalid:
|
|
57
|
+
disabled: v,
|
|
58
|
+
valid: y,
|
|
59
|
+
invalid: I,
|
|
60
60
|
touched: C,
|
|
61
|
-
shouldShowError:
|
|
62
|
-
componentProps:
|
|
61
|
+
shouldShowError: g,
|
|
62
|
+
componentProps: p
|
|
63
63
|
} = s;
|
|
64
64
|
return {
|
|
65
65
|
value: h,
|
|
66
66
|
errors: a,
|
|
67
67
|
pending: m,
|
|
68
|
-
disabled:
|
|
69
|
-
valid:
|
|
70
|
-
invalid:
|
|
68
|
+
disabled: v,
|
|
69
|
+
valid: y,
|
|
70
|
+
invalid: I,
|
|
71
71
|
touched: C,
|
|
72
|
-
shouldShowError:
|
|
73
|
-
error:
|
|
74
|
-
label:
|
|
75
|
-
required: !!
|
|
76
|
-
componentProps:
|
|
77
|
-
control:
|
|
78
|
-
ids:
|
|
79
|
-
hasDescription:
|
|
72
|
+
shouldShowError: g,
|
|
73
|
+
error: g ? a[0]?.message : void 0,
|
|
74
|
+
label: p.label,
|
|
75
|
+
required: !!p.required,
|
|
76
|
+
componentProps: p,
|
|
77
|
+
control: e,
|
|
78
|
+
ids: d,
|
|
79
|
+
hasDescription: r
|
|
80
80
|
};
|
|
81
|
-
}, [s,
|
|
82
|
-
return /* @__PURE__ */
|
|
81
|
+
}, [s, e, d, r]);
|
|
82
|
+
return /* @__PURE__ */ i(k.Provider, { value: c, children: n });
|
|
83
83
|
}
|
|
84
84
|
N.displayName = "FormField.Root";
|
|
85
|
-
const
|
|
86
|
-
({ asChild:
|
|
87
|
-
const { label: t, required:
|
|
88
|
-
return !c && !l ? null : /* @__PURE__ */
|
|
85
|
+
const j = f(
|
|
86
|
+
({ asChild: e = !1, children: n, forceRender: l = !1, ...r }, o) => {
|
|
87
|
+
const { label: t, required: d, ids: s } = F(), c = n ?? t;
|
|
88
|
+
return !c && !l ? null : /* @__PURE__ */ x(e ? b : "label", { ref: o, id: s.labelId, htmlFor: e ? void 0 : s.controlId, ...r, children: [
|
|
89
89
|
c,
|
|
90
|
-
|
|
90
|
+
d && /* @__PURE__ */ i("span", { "aria-hidden": "true", children: " *" })
|
|
91
91
|
] });
|
|
92
92
|
}
|
|
93
93
|
);
|
|
94
|
-
|
|
95
|
-
const
|
|
96
|
-
({ asChild:
|
|
94
|
+
j.displayName = "FormField.Label";
|
|
95
|
+
const R = f(
|
|
96
|
+
({ asChild: e = !1, children: n, ...l }, r) => {
|
|
97
97
|
const {
|
|
98
98
|
control: o,
|
|
99
99
|
value: t,
|
|
100
|
-
disabled:
|
|
100
|
+
disabled: d,
|
|
101
101
|
shouldShowError: s,
|
|
102
102
|
errors: c,
|
|
103
103
|
required: h,
|
|
104
104
|
ids: a,
|
|
105
105
|
hasDescription: m,
|
|
106
|
-
componentProps:
|
|
107
|
-
} =
|
|
106
|
+
componentProps: v
|
|
107
|
+
} = F(), y = [
|
|
108
108
|
m ? a.descriptionId : null,
|
|
109
109
|
s && c.length > 0 ? a.errorId : null
|
|
110
|
-
].filter(Boolean).join(" ") || void 0,
|
|
110
|
+
].filter(Boolean).join(" ") || void 0, I = {
|
|
111
111
|
id: a.controlId,
|
|
112
112
|
"aria-labelledby": a.labelId,
|
|
113
113
|
"aria-invalid": s ? !0 : void 0,
|
|
114
|
-
"aria-describedby":
|
|
114
|
+
"aria-describedby": y,
|
|
115
115
|
"aria-errormessage": s && c.length > 0 ? a.errorId : void 0,
|
|
116
116
|
"aria-required": h ? !0 : void 0
|
|
117
117
|
};
|
|
118
|
-
if (n ||
|
|
119
|
-
return /* @__PURE__ */
|
|
120
|
-
const C = o.component;
|
|
121
|
-
return /* @__PURE__ */
|
|
118
|
+
if (n || e)
|
|
119
|
+
return /* @__PURE__ */ i(b, { ref: r, ...I, ...l, children: n });
|
|
120
|
+
const C = o.component, { testId: g, ...p } = v ?? {};
|
|
121
|
+
return /* @__PURE__ */ i(
|
|
122
122
|
C,
|
|
123
123
|
{
|
|
124
|
-
ref:
|
|
125
|
-
...
|
|
126
|
-
...
|
|
124
|
+
ref: r,
|
|
125
|
+
...p,
|
|
126
|
+
...I,
|
|
127
127
|
...l,
|
|
128
128
|
value: t,
|
|
129
|
-
disabled:
|
|
130
|
-
onChange: (
|
|
129
|
+
disabled: d,
|
|
130
|
+
onChange: (D) => o.setValue(D),
|
|
131
131
|
onBlur: () => o.markAsTouched()
|
|
132
132
|
}
|
|
133
133
|
);
|
|
134
134
|
}
|
|
135
135
|
);
|
|
136
|
-
|
|
137
|
-
const
|
|
138
|
-
({ asChild:
|
|
139
|
-
const { shouldShowError:
|
|
140
|
-
if (!
|
|
141
|
-
const h =
|
|
142
|
-
return l ? /* @__PURE__ */
|
|
136
|
+
R.displayName = "FormField.Control";
|
|
137
|
+
const S = f(
|
|
138
|
+
({ asChild: e = !1, multi: n = !1, render: l, children: r, ...o }, t) => {
|
|
139
|
+
const { shouldShowError: d, errors: s, ids: c } = F();
|
|
140
|
+
if (!d || s.length === 0) return null;
|
|
141
|
+
const h = e ? b : "p";
|
|
142
|
+
return l ? /* @__PURE__ */ i(w, { children: s.map((a, m) => /* @__PURE__ */ i(
|
|
143
143
|
h,
|
|
144
144
|
{
|
|
145
145
|
id: m === 0 ? c.errorId : void 0,
|
|
@@ -148,7 +148,7 @@ const j = f(
|
|
|
148
148
|
children: l(a, m)
|
|
149
149
|
},
|
|
150
150
|
a.code ?? m
|
|
151
|
-
)) }) : n ? /* @__PURE__ */
|
|
151
|
+
)) }) : n ? /* @__PURE__ */ i(w, { children: s.map((a, m) => /* @__PURE__ */ i(
|
|
152
152
|
h,
|
|
153
153
|
{
|
|
154
154
|
id: m === 0 ? c.errorId : void 0,
|
|
@@ -157,61 +157,63 @@ const j = f(
|
|
|
157
157
|
children: a.message
|
|
158
158
|
},
|
|
159
159
|
a.code ?? m
|
|
160
|
-
)) }) : /* @__PURE__ */
|
|
160
|
+
)) }) : /* @__PURE__ */ i(h, { ref: t, id: c.errorId, role: "alert", ...o, children: r ?? s[0].message });
|
|
161
161
|
}
|
|
162
162
|
);
|
|
163
|
-
|
|
163
|
+
S.displayName = "FormField.Error";
|
|
164
164
|
const q = f(
|
|
165
|
-
({ asChild:
|
|
166
|
-
const { ids: o } =
|
|
167
|
-
return /* @__PURE__ */
|
|
165
|
+
({ asChild: e = !1, children: n, ...l }, r) => {
|
|
166
|
+
const { ids: o } = F();
|
|
167
|
+
return /* @__PURE__ */ i(e ? b : "p", { ref: r, id: o.descriptionId, ...l, children: n });
|
|
168
168
|
}
|
|
169
169
|
);
|
|
170
170
|
q.displayName = "FormField.Description";
|
|
171
171
|
const u = N;
|
|
172
172
|
u.Root = N;
|
|
173
|
-
u.Label =
|
|
174
|
-
u.Control =
|
|
175
|
-
u.Error =
|
|
173
|
+
u.Label = j;
|
|
174
|
+
u.Control = R;
|
|
175
|
+
u.Error = S;
|
|
176
176
|
u.Description = q;
|
|
177
|
-
|
|
178
|
-
|
|
177
|
+
const G = (e) => e.message || e.code;
|
|
178
|
+
E(G);
|
|
179
|
+
function H({
|
|
180
|
+
className: e,
|
|
179
181
|
testIdProp: n,
|
|
180
182
|
isCheckbox: l,
|
|
181
|
-
customChildren:
|
|
183
|
+
customChildren: r
|
|
182
184
|
}) {
|
|
183
|
-
const { componentProps: o, pending: t } =
|
|
184
|
-
return /* @__PURE__ */
|
|
185
|
-
!l && /* @__PURE__ */
|
|
185
|
+
const { componentProps: o, pending: t } = F(), d = n ?? o?.testId ?? "unknown";
|
|
186
|
+
return /* @__PURE__ */ x("div", { className: e, "data-testid": `field-${d}`, children: [
|
|
187
|
+
!l && /* @__PURE__ */ i(
|
|
186
188
|
u.Label,
|
|
187
189
|
{
|
|
188
190
|
className: "block mb-1 text-sm font-medium",
|
|
189
|
-
"data-testid": `label-${
|
|
191
|
+
"data-testid": `label-${d}`
|
|
190
192
|
}
|
|
191
193
|
),
|
|
192
|
-
|
|
193
|
-
/* @__PURE__ */
|
|
194
|
+
r ? /* @__PURE__ */ i(u.Control, { asChild: !0, children: r }) : /* @__PURE__ */ i(u.Control, { "data-testid": `input-${d}` }),
|
|
195
|
+
/* @__PURE__ */ i(
|
|
194
196
|
u.Error,
|
|
195
197
|
{
|
|
196
198
|
className: "text-destructive text-sm mt-1 block",
|
|
197
|
-
"data-testid": `error-${
|
|
199
|
+
"data-testid": `error-${d}`
|
|
198
200
|
}
|
|
199
201
|
),
|
|
200
|
-
t && /* @__PURE__ */
|
|
202
|
+
t && /* @__PURE__ */ i("span", { className: "text-gray-500 text-sm mt-1 block", children: "Проверка..." })
|
|
201
203
|
] });
|
|
202
204
|
}
|
|
203
|
-
const
|
|
204
|
-
const o =
|
|
205
|
-
return /* @__PURE__ */
|
|
206
|
-
|
|
205
|
+
const J = ({ control: e, className: n, testId: l, children: r }) => {
|
|
206
|
+
const o = e.component === T;
|
|
207
|
+
return /* @__PURE__ */ i(u.Root, { control: e, children: /* @__PURE__ */ i(
|
|
208
|
+
H,
|
|
207
209
|
{
|
|
208
210
|
className: n,
|
|
209
211
|
testIdProp: l,
|
|
210
212
|
isCheckbox: o,
|
|
211
|
-
customChildren:
|
|
213
|
+
customChildren: r
|
|
212
214
|
}
|
|
213
215
|
) });
|
|
214
|
-
},
|
|
216
|
+
}, X = B.memo(J, (e, n) => e.control === n.control && e.className === n.className && e.testId === n.testId && e.children === n.children);
|
|
215
217
|
export {
|
|
216
|
-
|
|
218
|
+
X as FormField
|
|
217
219
|
};
|
package/llms.txt
CHANGED
|
@@ -2470,7 +2470,7 @@ _Source: src/components/ui/example-card.tsx_
|
|
|
2470
2470
|
|
|
2471
2471
|
**Signature:**
|
|
2472
2472
|
```typescript
|
|
2473
|
-
export function FormArraySection<T extends
|
|
2473
|
+
export function FormArraySection<T extends object>({
|
|
2474
2474
|
control,
|
|
2475
2475
|
itemComponent: ItemComponent,
|
|
2476
2476
|
title,
|
|
@@ -2482,10 +2482,10 @@ export function FormArraySection<T extends FormFields>({
|
|
|
2482
2482
|
hasItems,
|
|
2483
2483
|
initialValue,
|
|
2484
2484
|
showRemoveOnSingle = false,
|
|
2485
|
+
reorderable = false,
|
|
2485
2486
|
maxItems,
|
|
2486
2487
|
className = 'space-y-3 mt-2',
|
|
2487
2488
|
cardClassName = 'mb-4 p-4 bg-white rounded border',
|
|
2488
|
-
form,
|
|
2489
2489
|
}: FormArraySectionProps<T>): ReactNode
|
|
2490
2490
|
```
|
|
2491
2491
|
|
|
@@ -2497,12 +2497,9 @@ _Source: src/components/form-array/form-array-section.tsx_
|
|
|
2497
2497
|
|
|
2498
2498
|
**Signature:**
|
|
2499
2499
|
```typescript
|
|
2500
|
-
export interface FormArraySectionProps<T extends
|
|
2501
|
-
/**
|
|
2502
|
-
|
|
2503
|
-
* FieldPathNode (path.<arrayField>) — в этом случае через `form` + navigator.
|
|
2504
|
-
*/
|
|
2505
|
-
control: FormArrayProxy<T> | ArrayNode<T> | FieldPathNode<unknown, unknown> | undefined;
|
|
2500
|
+
export interface FormArraySectionProps<T extends object> {
|
|
2501
|
+
/** Уже-резолвленный ArrayNode/ModelArrayNode/FormArrayProxy. */
|
|
2502
|
+
control: FormArrayProxy<T> | ArrayNode<T> | undefined;
|
|
2506
2503
|
|
|
2507
2504
|
/** React FC получает `control: FormProxy<T>` для каждого элемента. */
|
|
2508
2505
|
itemComponent: ComponentType<{ control: FormProxy<T> }>;
|
|
@@ -2544,6 +2541,12 @@ export interface FormArraySectionProps<T extends FormFields> {
|
|
|
2544
2541
|
/** Показывать «Удалить» когда остался один элемент. По умолчанию `false`. */
|
|
2545
2542
|
showRemoveOnSingle?: boolean;
|
|
2546
2543
|
|
|
2544
|
+
/**
|
|
2545
|
+
* Показывать кнопки ↑/↓ для перестановки элементов. По умолчанию `false`
|
|
2546
|
+
* (обратная совместимость — существующие массивы не меняются).
|
|
2547
|
+
*/
|
|
2548
|
+
reorderable?: boolean;
|
|
2549
|
+
|
|
2547
2550
|
/** Максимум items — AddButton отключается при достижении. */
|
|
2548
2551
|
maxItems?: number;
|
|
2549
2552
|
|
package/package.json
CHANGED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { jsx as e, jsxs as i } from "react/jsx-runtime";
|
|
2
|
-
import { useFormControl as S, extractPath as $, FieldPathNavigator as P } from "@reformer/core";
|
|
3
|
-
import { FormArray as s } from "@reformer/cdk/form-array";
|
|
4
|
-
const R = new P();
|
|
5
|
-
function B(t, a) {
|
|
6
|
-
if (!t) return null;
|
|
7
|
-
if (typeof t == "object" && typeof t.push == "function" && typeof t.removeAt == "function")
|
|
8
|
-
return t;
|
|
9
|
-
if (!a)
|
|
10
|
-
return typeof console < "u" && console.warn(
|
|
11
|
-
"[FormArraySection] control is a FieldPath but no `form` prop available. Ensure this component is rendered inside FormRenderer with form available, or pass form explicitly."
|
|
12
|
-
), null;
|
|
13
|
-
try {
|
|
14
|
-
const r = $(t), n = R.getNodeByPath(a, r);
|
|
15
|
-
return n || (typeof console < "u" && console.warn(`[FormArraySection] No ArrayNode at path "${r}".`), null);
|
|
16
|
-
} catch (r) {
|
|
17
|
-
return typeof console < "u" && console.warn("[FormArraySection] Failed to resolve control:", r), null;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
function E({
|
|
21
|
-
control: t,
|
|
22
|
-
itemComponent: a,
|
|
23
|
-
title: r,
|
|
24
|
-
itemLabel: n,
|
|
25
|
-
addButtonLabel: u = "+ Добавить",
|
|
26
|
-
removeButtonLabel: v = "Удалить",
|
|
27
|
-
emptyMessage: f,
|
|
28
|
-
emptyMessageHint: m,
|
|
29
|
-
hasItems: b,
|
|
30
|
-
initialValue: h,
|
|
31
|
-
showRemoveOnSingle: g = !1,
|
|
32
|
-
maxItems: p,
|
|
33
|
-
className: x = "space-y-3 mt-2",
|
|
34
|
-
cardClassName: N = "mb-4 p-4 bg-white rounded border",
|
|
35
|
-
form: w
|
|
36
|
-
}) {
|
|
37
|
-
const d = B(t, w), A = S(
|
|
38
|
-
d ?? void 0
|
|
39
|
-
);
|
|
40
|
-
if (b === !1 || !d) return null;
|
|
41
|
-
const c = A?.length ?? 0, y = p != null && c >= p, F = (l, o) => typeof n == "function" ? n(l, o) : `${n ?? r ?? "Элемент"} #${o + 1}`;
|
|
42
|
-
return /* @__PURE__ */ e(s.Root, { control: d, children: /* @__PURE__ */ i("section", { className: x, children: [
|
|
43
|
-
r ? /* @__PURE__ */ i("div", { className: "flex justify-between items-center mb-4", children: [
|
|
44
|
-
/* @__PURE__ */ e("h3", { className: "text-lg font-semibold", children: r }),
|
|
45
|
-
y ? null : /* @__PURE__ */ e(
|
|
46
|
-
s.AddButton,
|
|
47
|
-
{
|
|
48
|
-
initialValue: h,
|
|
49
|
-
"data-testid": "array-add",
|
|
50
|
-
className: "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-primary text-primary-foreground shadow hover:bg-primary/90 h-9 px-4 py-2",
|
|
51
|
-
children: u
|
|
52
|
-
}
|
|
53
|
-
)
|
|
54
|
-
] }) : null,
|
|
55
|
-
/* @__PURE__ */ e(s.List, { className: "space-y-3", children: ({ control: l, index: o, remove: j }) => {
|
|
56
|
-
const C = g || c > 1;
|
|
57
|
-
return /* @__PURE__ */ i("div", { className: N, "data-testid": `array-item-${o}`, children: [
|
|
58
|
-
r || n ? /* @__PURE__ */ i("div", { className: "flex justify-between items-center mb-3", children: [
|
|
59
|
-
/* @__PURE__ */ e("h4", { className: "font-medium", children: F(l, o) }),
|
|
60
|
-
C ? /* @__PURE__ */ e(
|
|
61
|
-
"button",
|
|
62
|
-
{
|
|
63
|
-
type: "button",
|
|
64
|
-
onClick: j,
|
|
65
|
-
"data-testid": `array-item-${o}-remove`,
|
|
66
|
-
className: "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-destructive text-destructive-foreground shadow hover:bg-destructive/90 h-9 px-4 py-2",
|
|
67
|
-
children: v
|
|
68
|
-
}
|
|
69
|
-
) : null
|
|
70
|
-
] }) : null,
|
|
71
|
-
/* @__PURE__ */ e(a, { control: l })
|
|
72
|
-
] });
|
|
73
|
-
} }),
|
|
74
|
-
c === 0 && f ? /* @__PURE__ */ e(s.Empty, { children: /* @__PURE__ */ i("div", { className: "p-4 bg-gray-100 border border-gray-300 rounded text-center text-gray-600", children: [
|
|
75
|
-
f,
|
|
76
|
-
m && /* @__PURE__ */ e("div", { className: "mt-2 text-xs text-gray-500", children: m })
|
|
77
|
-
] }) }) : null,
|
|
78
|
-
!r && !y ? /* @__PURE__ */ e("div", { children: /* @__PURE__ */ e(
|
|
79
|
-
s.AddButton,
|
|
80
|
-
{
|
|
81
|
-
initialValue: h,
|
|
82
|
-
"data-testid": "array-add",
|
|
83
|
-
className: "text-sm text-blue-600 hover:text-blue-700 hover:underline",
|
|
84
|
-
children: u
|
|
85
|
-
}
|
|
86
|
-
) }) : null
|
|
87
|
-
] }) });
|
|
88
|
-
}
|
|
89
|
-
E.__selfManagedChildren = !0;
|
|
90
|
-
export {
|
|
91
|
-
E as F
|
|
92
|
-
};
|