@elcrm/form 0.0.79 → 0.0.81

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 (40) hide show
  1. package/dist/assets/styles/Color.module.css +1 -1
  2. package/dist/assets/styles/Field.module.css +1 -1
  3. package/dist/core/Field.js +1 -1
  4. package/dist/fields/Code.d.ts +14 -0
  5. package/dist/fields/Code.js +94 -0
  6. package/dist/fields/Color.js +133 -91
  7. package/dist/fields/Date.js +132 -77
  8. package/dist/fields/Display.d.ts +17 -0
  9. package/dist/fields/Display.js +49 -0
  10. package/dist/fields/DragDrop.d.ts +26 -0
  11. package/dist/fields/DragDrop.js +189 -0
  12. package/dist/fields/Email.d.ts +8 -0
  13. package/dist/fields/Email.js +80 -0
  14. package/dist/fields/File.d.ts +24 -0
  15. package/dist/fields/File.js +115 -0
  16. package/dist/fields/Hidden.d.ts +11 -0
  17. package/dist/fields/Hidden.js +33 -0
  18. package/dist/fields/Numeric.js +42 -24
  19. package/dist/fields/Percent.d.ts +13 -0
  20. package/dist/fields/Percent.js +100 -0
  21. package/dist/fields/Radio.d.ts +22 -0
  22. package/dist/fields/Radio.js +88 -0
  23. package/dist/fields/Rating.d.ts +12 -0
  24. package/dist/fields/Rating.js +82 -0
  25. package/dist/fields/RichText.d.ts +14 -0
  26. package/dist/fields/RichText.js +134 -0
  27. package/dist/fields/Tags.d.ts +12 -0
  28. package/dist/fields/Tags.js +97 -0
  29. package/dist/fields/Time.d.ts +8 -1
  30. package/dist/fields/Time.js +330 -156
  31. package/dist/fields/Url.d.ts +8 -0
  32. package/dist/fields/Url.js +80 -0
  33. package/dist/index.d.ts +27 -0
  34. package/dist/index.js +18 -6
  35. package/dist/index.umd.js +2 -2
  36. package/dist/package.js +1 -1
  37. package/dist/style.css +2 -2
  38. package/dist/styles/Color.module.js +23 -23
  39. package/dist/styles/Field.module.js +72 -24
  40. package/package.json +1 -1
@@ -0,0 +1,80 @@
1
+ import e from "../styles/Field.module.js";
2
+ import t from "../core/Field.js";
3
+ import { useFormFieldState as n } from "../hooks/use.js";
4
+ import { isEmptyTextLike as r } from "./visibility.js";
5
+ import i from "react";
6
+ import { jsx as a, jsxs as o } from "react/jsx-runtime";
7
+ //#region src/lib/fields/Email.tsx
8
+ function s({ value: s = "", form: c, onValue: l, onBlur: u, name: d = "", placeholder: f = "", label: p = "", error: m = "", hidden: h = !1, disabled: g = !1, className: _ = "", after: v = "", before: y = "", maxLength: b, autoComplete: x = "email", id: S }) {
9
+ let { value: C, version: w } = n(c, d, s), T = !g, E = typeof C == "string" || typeof C == "number" ? String(C) : "", D = i.useRef(null);
10
+ i.useEffect(() => {
11
+ let e = D.current;
12
+ !e || e.value === E || (e.value = E);
13
+ }, [E, w]);
14
+ let O = (e, t = !1) => {
15
+ let n = {
16
+ value: e,
17
+ name: d
18
+ };
19
+ c && d && (t ? c.setValue(n) : c.onValue(n)), l && l !== c?.onValue && l(n);
20
+ };
21
+ return h && r(C) ? null : /* @__PURE__ */ o(t, {
22
+ type: "email",
23
+ label: p,
24
+ error: m,
25
+ element_blok: { className: [_ || ""] },
26
+ element_input: {
27
+ className: [e.w],
28
+ props: { "data-disabled": g || !T ? "true" : void 0 }
29
+ },
30
+ children: [
31
+ y ? /* @__PURE__ */ a("span", {
32
+ className: e.affix,
33
+ children: y
34
+ }) : null,
35
+ /* @__PURE__ */ a("div", { children: /* @__PURE__ */ a("input", {
36
+ id: S,
37
+ ref: D,
38
+ type: "email",
39
+ name: d || void 0,
40
+ defaultValue: E,
41
+ placeholder: f,
42
+ maxLength: b,
43
+ disabled: g,
44
+ readOnly: !T,
45
+ autoComplete: x,
46
+ inputMode: "email",
47
+ spellCheck: !1,
48
+ "aria-label": p || f || "Email",
49
+ onChange: (e) => O(e.target.value),
50
+ onBlur: (e) => {
51
+ let t = (e.target.value || "").trim();
52
+ O(t, !0), u?.({
53
+ value: t,
54
+ name: d
55
+ });
56
+ },
57
+ onKeyDown: (e) => {
58
+ e.key === "Enter" && e.preventDefault();
59
+ },
60
+ style: {
61
+ width: "100%",
62
+ border: "none",
63
+ outline: "none",
64
+ background: "transparent",
65
+ font: "inherit",
66
+ color: "inherit",
67
+ padding: 0,
68
+ margin: 0
69
+ }
70
+ }) }),
71
+ v ? /* @__PURE__ */ a("span", {
72
+ className: e.affix,
73
+ children: v
74
+ }) : null
75
+ ]
76
+ });
77
+ }
78
+ s.displayName = "EmailField";
79
+ //#endregion
80
+ export { s as default };
@@ -0,0 +1,24 @@
1
+ import { TInput } from './type';
2
+ /** Метаданные выбранного файла (File в форме сериализовать нельзя надёжно). */
3
+ export type TFileMeta = {
4
+ name: string;
5
+ size: number;
6
+ type: string;
7
+ lastModified: number;
8
+ };
9
+ export type TFile = TInput & {
10
+ accept?: string;
11
+ multiple?: boolean;
12
+ /** Макс. размер одного файла, байт */
13
+ maxSize?: number;
14
+ /**
15
+ * Если true — в форму пишутся сами `File` / `File[]`.
16
+ * Иначе — метаданные `TFileMeta` / `TFileMeta[]` (удобнее для превью).
17
+ */
18
+ keepFile?: boolean;
19
+ };
20
+ declare function FileField({ value, form, onValue, onBlur: onBlurField, name, placeholder, label, error, hidden, disabled, className, after, before, accept, multiple, maxSize, keepFile, }: TFile): import("react/jsx-runtime").JSX.Element | null;
21
+ declare namespace FileField {
22
+ var displayName: string;
23
+ }
24
+ export default FileField;
@@ -0,0 +1,115 @@
1
+ import e from "../styles/Field.module.js";
2
+ import t from "../core/Field.js";
3
+ import { useFormFieldState as n } from "../hooks/use.js";
4
+ import r from "react";
5
+ import { jsx as i, jsxs as a } from "react/jsx-runtime";
6
+ //#region src/lib/fields/File.tsx
7
+ function o(e) {
8
+ return {
9
+ name: e.name,
10
+ size: e.size,
11
+ type: e.type,
12
+ lastModified: e.lastModified
13
+ };
14
+ }
15
+ function s(e) {
16
+ return e ? Array.isArray(e) ? e : typeof File < "u" && e instanceof File || typeof e == "object" && e && "name" in e ? [e] : [] : [];
17
+ }
18
+ function c(e) {
19
+ return e < 1024 ? `${e} Б` : e < 1024 * 1024 ? `${(e / 1024).toFixed(1)} КБ` : `${(e / (1024 * 1024)).toFixed(1)} МБ`;
20
+ }
21
+ function l({ value: l, form: u, onValue: d, onBlur: f, name: p = "", placeholder: m = "Выберите файл", label: h = "", error: g = "", hidden: _ = !1, disabled: v = !1, className: y = "", after: b = "", before: x = "", accept: S, multiple: C = !1, maxSize: w, keepFile: T = !0 }) {
22
+ let { value: E } = n(u, p, l), D = s(E), O = !v, k = r.useRef(null), [A, j] = r.useState(""), M = (e) => {
23
+ let t = {
24
+ value: e,
25
+ name: p
26
+ };
27
+ u && p && u.setValue(t), d && d !== u?.onValue && d(t);
28
+ }, N = (e) => {
29
+ if (!e || e.length === 0) return;
30
+ let t = Array.from(e);
31
+ if (w !== void 0) {
32
+ let e = t.find((e) => e.size > w);
33
+ if (e) {
34
+ j(`Файл «${e.name}» больше ${c(w)}`);
35
+ return;
36
+ }
37
+ }
38
+ j("");
39
+ let n = T ? C ? t : t[0] : C ? t.map(o) : o(t[0]);
40
+ M(n), f?.({
41
+ value: n,
42
+ name: p
43
+ });
44
+ }, P = () => {
45
+ O && (M(C ? [] : null), k.current && (k.current.value = ""), j(""));
46
+ }, F = D.length === 0;
47
+ return _ && F ? null : /* @__PURE__ */ a(t, {
48
+ type: "file",
49
+ label: h,
50
+ error: g || A,
51
+ element_blok: { className: [y || ""] },
52
+ element_input: {
53
+ className: [e.file],
54
+ props: { "data-disabled": v || !O ? "true" : void 0 }
55
+ },
56
+ children: [
57
+ x ? /* @__PURE__ */ i("span", {
58
+ className: e.affix,
59
+ children: x
60
+ }) : null,
61
+ /* @__PURE__ */ a("div", {
62
+ className: e.fileInner,
63
+ children: [
64
+ /* @__PURE__ */ i("input", {
65
+ ref: k,
66
+ type: "file",
67
+ className: e.fileInput,
68
+ accept: S,
69
+ multiple: C,
70
+ disabled: v || !O,
71
+ "aria-label": h || m || "Файл",
72
+ onChange: (e) => N(e.target.files)
73
+ }),
74
+ /* @__PURE__ */ i("button", {
75
+ type: "button",
76
+ className: e.fileButton,
77
+ disabled: !O,
78
+ onClick: () => k.current?.click(),
79
+ children: m
80
+ }),
81
+ /* @__PURE__ */ i("div", {
82
+ className: e.fileList,
83
+ children: F ? /* @__PURE__ */ i("span", {
84
+ className: e.fileEmpty,
85
+ children: "Нет файла"
86
+ }) : D.map((t, n) => /* @__PURE__ */ a("span", {
87
+ className: e.fileItem,
88
+ children: [/* @__PURE__ */ i("span", {
89
+ className: e.fileName,
90
+ children: t.name
91
+ }), /* @__PURE__ */ i("span", {
92
+ className: e.fileSize,
93
+ children: c(t.size)
94
+ })]
95
+ }, `${t.name}-${n}`))
96
+ }),
97
+ !F && O ? /* @__PURE__ */ i("button", {
98
+ type: "button",
99
+ className: e.fileClear,
100
+ "aria-label": "Очистить",
101
+ onClick: P,
102
+ children: "×"
103
+ }) : null
104
+ ]
105
+ }),
106
+ b ? /* @__PURE__ */ i("span", {
107
+ className: e.affix,
108
+ children: b
109
+ }) : null
110
+ ]
111
+ });
112
+ }
113
+ l.displayName = "FileField";
114
+ //#endregion
115
+ export { l as default };
@@ -0,0 +1,11 @@
1
+ import { TInput } from './type';
2
+ /**
3
+ * HiddenField — значение в форме без UI.
4
+ * Рендерит нативный `<input type="hidden">` для submit обычных форм.
5
+ */
6
+ export type THidden = Pick<TInput, "value" | "form" | "onValue" | "name" | "id" | "hidden">;
7
+ declare function HiddenField({ value, form, onValue, name, id, hidden, }: THidden): import("react/jsx-runtime").JSX.Element | null;
8
+ declare namespace HiddenField {
9
+ var displayName: string;
10
+ }
11
+ export default HiddenField;
@@ -0,0 +1,33 @@
1
+ import { useFormFieldState as e } from "../hooks/use.js";
2
+ import t from "react";
3
+ import { jsx as n } from "react/jsx-runtime";
4
+ //#region src/lib/fields/Hidden.tsx
5
+ function r({ value: r = "", form: i, onValue: a, name: o = "", id: s, hidden: c = !1 }) {
6
+ let { value: l } = e(i, o, r);
7
+ if (t.useEffect(() => {
8
+ if (!i || !o || i.getValue(o) !== void 0) return;
9
+ let e = {
10
+ value: l,
11
+ name: o
12
+ };
13
+ i.onValue(e), a && a !== i.onValue && a(e);
14
+ }, [
15
+ i,
16
+ o,
17
+ l,
18
+ a
19
+ ]), c) return null;
20
+ let u = l == null ? "" : typeof l == "string" || typeof l == "number" || typeof l == "boolean" ? String(l) : JSON.stringify(l);
21
+ return /* @__PURE__ */ n("input", {
22
+ type: "hidden",
23
+ id: s,
24
+ name: o || void 0,
25
+ value: u,
26
+ readOnly: !0,
27
+ "data-field": "hidden",
28
+ "aria-hidden": !0
29
+ });
30
+ }
31
+ r.displayName = "HiddenField";
32
+ //#endregion
33
+ export { r as default };
@@ -15,39 +15,55 @@ function u({ value: u, form: d, onValue: f, name: p = "", placeholder: m = "", l
15
15
  let e = j.current;
16
16
  e && e.textContent !== A && (e.textContent = A);
17
17
  }, [A, k]);
18
- let N = w ?? T, P = !1, F = (e) => {
19
- let t = e.currentTarget, n = (t.textContent || "").replace(/\D/g, "");
20
- n.length > N && (n = n.slice(0, N), t.textContent = n, queueMicrotask(() => {
21
- let e = t.firstChild;
22
- if (e && e.nodeType === Node.TEXT_NODE) {
23
- let t = n.length, r = window.getSelection(), i = document.createRange();
24
- i.setStart(e, t), i.collapse(!0), r?.removeAllRanges(), r?.addRange(i);
25
- }
18
+ let N = w ?? T, P = !1, F = (e, t) => {
19
+ e.textContent !== t && (e.textContent = t, queueMicrotask(() => {
20
+ let n = e.firstChild;
21
+ if (n && n.nodeType === Node.TEXT_NODE) {
22
+ let e = t.length, r = window.getSelection(), i = document.createRange();
23
+ i.setStart(n, e), i.collapse(!0), r?.removeAllRanges(), r?.addRange(i);
24
+ } else t || (e.innerHTML = "<br>");
26
25
  }));
26
+ }, I = (e) => {
27
+ let t = e.currentTarget, n = (t.textContent || "").replace(/\D/g, "");
28
+ N > 0 && n.length > N && (n = n.slice(0, N)), F(t, n);
27
29
  let r = {
28
30
  value: n,
29
31
  name: p
30
32
  };
31
33
  d && p && d.onValue(r), f && f !== d?.onValue && f(r);
32
- }, I = (e) => {
34
+ }, L = (e) => {
33
35
  M.current = !0;
34
36
  let t = e.currentTarget;
35
37
  t.textContent = (t.textContent || "").replace(/\D/g, ""), r.Focus({ target: e.currentTarget });
36
- }, L = (e) => {
38
+ }, R = (e) => {
37
39
  if (P && e.which === 86) return;
38
40
  if (e.which === 17 || e.which === 91) return P = !0;
39
41
  if (e.key === "Backspace") return;
40
42
  let t = (e.currentTarget.textContent ?? "").replace(/\D/g, "").length;
41
- N > 0 && t >= N && e.key.length === 1 && /\d/.test(e.key) && e.preventDefault(), e.key === "Enter" && e.preventDefault(), e.key.length === 1 && !/\d/.test(e.key) && e.preventDefault();
42
- }, R = (e) => {
43
+ N > 0 && t >= N && e.key.length === 1 && /\d/.test(e.key) && e.preventDefault(), e.key === "Enter" && e.preventDefault(), e.key.length === 1 && !/\d/.test(e.key) && !e.metaKey && !e.ctrlKey && e.preventDefault();
44
+ }, z = (e) => {
43
45
  if (e.which === 17 || e.which === 91) return P = !1;
44
- }, z = (e) => r.PasteDigits(N, i(e)), B = (e) => {
45
- r.Blur(e), v?.({
46
- value: e.currentTarget.textContent,
46
+ }, B = (e) => {
47
+ r.PasteDigits(N, i(e)), queueMicrotask(() => {
48
+ let e = j.current;
49
+ if (!e) return;
50
+ let t = (e.textContent || "").replace(/\D/g, "");
51
+ N > 0 && t.length > N && (t = t.slice(0, N)), F(e, t), d && p && d.onValue({
52
+ value: t,
53
+ name: p
54
+ });
55
+ });
56
+ }, V = (e) => {
57
+ e.preventDefault();
58
+ }, H = (e) => {
59
+ r.Blur(e);
60
+ let t = (e.currentTarget.textContent || "").replace(/\D/g, "");
61
+ e.currentTarget.textContent !== t && (e.currentTarget.textContent = t), v?.({
62
+ value: t,
47
63
  name: p
48
64
  }), M.current = !1;
49
- }, V = {};
50
- return D && (V.edit = ""), V.inputMode = C ?? "numeric", m && (V.placeholder = m), g && a(O) ? /* @__PURE__ */ c(s, {}) : /* @__PURE__ */ l(t, {
65
+ }, U = {};
66
+ return D && (U.edit = ""), U.inputMode = C ?? "numeric", m && (U.placeholder = m), g && a(O) ? /* @__PURE__ */ c(s, {}) : /* @__PURE__ */ l(t, {
51
67
  type: "numeric",
52
68
  label: h,
53
69
  error: S,
@@ -60,19 +76,21 @@ function u({ value: u, form: d, onValue: f, name: p = "", placeholder: m = "", l
60
76
  }) : null,
61
77
  /* @__PURE__ */ c("div", {
62
78
  ref: j,
63
- onPaste: z,
64
- onInput: F,
65
- onFocus: I,
66
- onBlur: B,
67
- onKeyDown: L,
68
- onKeyUp: R,
79
+ onPaste: B,
80
+ onDrop: V,
81
+ onDragOver: (e) => e.preventDefault(),
82
+ onInput: I,
83
+ onFocus: L,
84
+ onBlur: H,
85
+ onKeyDown: R,
86
+ onKeyUp: z,
69
87
  spellCheck: !1,
70
88
  role: "textbox",
71
89
  tabIndex: D ? 0 : -1,
72
90
  "aria-label": h || m || "Число",
73
91
  contentEditable: D ? "plaintext-only" : !1,
74
92
  suppressContentEditableWarning: !0,
75
- ...V
93
+ ...U
76
94
  }),
77
95
  b ? /* @__PURE__ */ c("span", {
78
96
  className: e.affix,
@@ -0,0 +1,13 @@
1
+ import { TInput } from './type';
2
+ /** PercentField — процент 0…max с суффиксом «%». */
3
+ export type TPercent = TInput & {
4
+ min?: number;
5
+ max?: number;
6
+ /** Допускать дробную часть */
7
+ decimals?: number;
8
+ };
9
+ declare function PercentField({ value, form, onValue, onBlur: onBlurField, name, placeholder, label, error, hidden, disabled, className, after, before, min, max, decimals, inputmode, }: TPercent): import("react/jsx-runtime").JSX.Element | null;
10
+ declare namespace PercentField {
11
+ var displayName: string;
12
+ }
13
+ export default PercentField;
@@ -0,0 +1,100 @@
1
+ import e from "../styles/Field.module.js";
2
+ import t from "../core/Field.js";
3
+ import { useFormFieldState as n } from "../hooks/use.js";
4
+ import r, { asEditableClipboard as i } from "../events/onEvent.js";
5
+ import a from "react";
6
+ import { jsx as o, jsxs as s } from "react/jsx-runtime";
7
+ //#region src/lib/fields/Percent.tsx
8
+ function c(e, t, n) {
9
+ return Number.isFinite(e) ? Math.min(n, Math.max(t, e)) : t;
10
+ }
11
+ function l(e, t) {
12
+ let n = e.replace(",", ".").replace(/[^\d.]/g, "");
13
+ if (!n) return null;
14
+ let r = Number(n);
15
+ if (!Number.isFinite(r)) return null;
16
+ if (t <= 0) return Math.round(r);
17
+ let i = 10 ** t;
18
+ return Math.round(r * i) / i;
19
+ }
20
+ function u(e, t) {
21
+ return Number.isFinite(e) ? String(t <= 0 ? Math.round(e) : Number(e.toFixed(t))) : "";
22
+ }
23
+ function d({ value: d = 0, form: f, onValue: p, onBlur: m, name: h = "", placeholder: g = "0", label: _ = "", error: v = "", hidden: y = !1, disabled: b = !1, className: x = "", after: S, before: C = "", min: w = 0, max: T = 100, decimals: E = 0, inputmode: D = "decimal" }) {
24
+ let { value: O, version: k } = n(f, h, d), A = !b, j = c(Number(O), w, T), M = O == null || O === "" ? "" : u(j, E), N = a.useRef(null), P = a.useRef(!1);
25
+ a.useLayoutEffect(() => {
26
+ if (P.current) return;
27
+ let e = N.current;
28
+ e && e.textContent !== M && (e.textContent = M);
29
+ }, [M, k]);
30
+ let F = (e, t = !1) => {
31
+ let n = {
32
+ value: e,
33
+ name: h
34
+ };
35
+ f && h && (t ? f.setValue(n) : f.onValue(n)), p && p !== f?.onValue && p(n);
36
+ }, I = (e) => {
37
+ let t = (e.currentTarget.textContent || "").replace(/[^\d.,]/g, "");
38
+ e.currentTarget.textContent !== t && (e.currentTarget.textContent = t);
39
+ let n = l(t, E);
40
+ if (n === null) {
41
+ F("");
42
+ return;
43
+ }
44
+ F(c(n, w, T));
45
+ }, L = (e) => {
46
+ r.Blur(e), P.current = !1;
47
+ let t = l(e.currentTarget.textContent || "", E), n = t === null ? w : c(t, w, T), i = u(n, E);
48
+ e.currentTarget.textContent !== i && (e.currentTarget.textContent = i), F(n, !0), m?.({
49
+ value: n,
50
+ name: h
51
+ });
52
+ };
53
+ if (y && (O == null || O === "")) return null;
54
+ let R = {};
55
+ return g && (R.placeholder = g), A && (R.edit = ""), R.inputMode = D || "decimal", /* @__PURE__ */ s(t, {
56
+ type: "percent",
57
+ label: _,
58
+ error: v,
59
+ element_blok: { className: [x || ""] },
60
+ element_input: {
61
+ className: [e.w],
62
+ props: { "data-disabled": b || !A ? "true" : void 0 }
63
+ },
64
+ children: [
65
+ C ? /* @__PURE__ */ o("span", {
66
+ className: e.affix,
67
+ children: C
68
+ }) : null,
69
+ /* @__PURE__ */ o("div", {
70
+ ref: N,
71
+ onInput: I,
72
+ onFocus: (e) => {
73
+ P.current = !0, r.Focus({ target: e.currentTarget });
74
+ },
75
+ onBlur: L,
76
+ onPaste: (e) => r.Paste(12, i(e)),
77
+ onKeyDown: (e) => {
78
+ e.key === "Enter" && e.preventDefault(), e.key.length === 1 && !/[\d.,]/.test(e.key) && !e.metaKey && !e.ctrlKey && e.preventDefault();
79
+ },
80
+ spellCheck: !1,
81
+ role: "textbox",
82
+ tabIndex: A ? 0 : -1,
83
+ "aria-label": _ || g || "Процент",
84
+ contentEditable: A ? "plaintext-only" : !1,
85
+ suppressContentEditableWarning: !0,
86
+ ...R
87
+ }),
88
+ S === void 0 ? /* @__PURE__ */ o("span", {
89
+ className: e.affix,
90
+ children: "%"
91
+ }) : /* @__PURE__ */ o("span", {
92
+ className: e.affix,
93
+ children: S
94
+ })
95
+ ]
96
+ });
97
+ }
98
+ d.displayName = "PercentField";
99
+ //#endregion
100
+ export { d as default };
@@ -0,0 +1,22 @@
1
+ import { TInput } from './type';
2
+ type RadioOptionObject = Record<string | number, {
3
+ n: string;
4
+ s?: number;
5
+ }>;
6
+ type RadioOptionArrayItem = {
7
+ id?: string | number;
8
+ i?: string | number;
9
+ n: string;
10
+ s?: number;
11
+ };
12
+ type RadioOptions = RadioOptionObject | RadioOptionArrayItem[];
13
+ export type TRadio = TInput & {
14
+ options?: RadioOptions;
15
+ /** Горизонтальный ряд вместо колонки */
16
+ inline?: boolean;
17
+ };
18
+ declare function RadioField({ value, form, onValue, onBlur: onBlurField, name, placeholder, label, error, hidden, disabled, className, after, before, options, inline, }: TRadio): import("react/jsx-runtime").JSX.Element | null;
19
+ declare namespace RadioField {
20
+ var displayName: string;
21
+ }
22
+ export default RadioField;
@@ -0,0 +1,88 @@
1
+ import e from "../styles/Field.module.js";
2
+ import t from "../core/Field.js";
3
+ import { useFormFieldState as n } from "../hooks/use.js";
4
+ import r from "react";
5
+ import { jsx as i, jsxs as a } from "react/jsx-runtime";
6
+ //#region src/lib/fields/Radio.tsx
7
+ function o(e) {
8
+ return e ? Array.isArray(e) ? e.map((e) => ({
9
+ id: e.id ?? e.i ?? "",
10
+ label: e.n || "",
11
+ hidden: e.s === 0
12
+ })).filter((e) => e.label.length > 0 && e.id !== "") : Object.keys(e).map((t) => {
13
+ let n = e[t], r = Number(t);
14
+ return {
15
+ id: Number.isFinite(r) && String(r) === t ? r : t,
16
+ label: n?.n || "",
17
+ hidden: n?.s === 0
18
+ };
19
+ }).filter((e) => e.label.length > 0) : [];
20
+ }
21
+ function s(e, t) {
22
+ return e === t ? !0 : String(e) === String(t);
23
+ }
24
+ function c({ value: c = "", form: l, onValue: u, onBlur: d, name: f = "", placeholder: p = "", label: m = "", error: h = "", hidden: g = !1, disabled: _ = !1, className: v = "", after: y = "", before: b = "", options: x, inline: S = !1 }) {
25
+ let { value: C } = n(l, f, c), w = !_, T = o(x).filter((e) => !e.hidden), E = r.useId(), D = (e) => {
26
+ let t = {
27
+ value: e,
28
+ name: f
29
+ };
30
+ l && f && l.setValue(t), u && u !== l?.onValue && u(t);
31
+ };
32
+ return g && (C == null || C === "") ? null : /* @__PURE__ */ a(t, {
33
+ type: "radio",
34
+ label: m,
35
+ error: h,
36
+ element_blok: { className: [v || ""] },
37
+ element_input: {
38
+ className: [e.radio, S ? e.radioInline : ""],
39
+ props: {
40
+ "data-disabled": _ || !w ? "true" : void 0,
41
+ role: "radiogroup",
42
+ "aria-label": m || p || "Выбор"
43
+ }
44
+ },
45
+ children: [
46
+ b ? /* @__PURE__ */ i("span", {
47
+ className: e.affix,
48
+ children: b
49
+ }) : null,
50
+ /* @__PURE__ */ i("div", { children: T.map((t) => {
51
+ let n = s(C, t.id);
52
+ return /* @__PURE__ */ a("button", {
53
+ type: "button",
54
+ className: e.radioItem,
55
+ role: "radio",
56
+ "aria-checked": n,
57
+ "aria-disabled": _ || !w ? !0 : void 0,
58
+ disabled: _ || !w,
59
+ name: E,
60
+ onClick: () => {
61
+ w && D(t.id);
62
+ },
63
+ onBlur: () => {
64
+ !d || !f || d({
65
+ value: l ? l.getValue(f, C) : C,
66
+ name: f
67
+ });
68
+ },
69
+ children: [/* @__PURE__ */ i("span", {
70
+ className: e.radioDot,
71
+ "aria-hidden": !0,
72
+ children: n ? /* @__PURE__ */ i("span", { className: e.radioDotFill }) : null
73
+ }), /* @__PURE__ */ i("span", {
74
+ className: e.radioText,
75
+ children: t.label
76
+ })]
77
+ }, String(t.id));
78
+ }) }),
79
+ y ? /* @__PURE__ */ i("span", {
80
+ className: e.affix,
81
+ children: y
82
+ }) : null
83
+ ]
84
+ });
85
+ }
86
+ c.displayName = "RadioField";
87
+ //#endregion
88
+ export { c as default };
@@ -0,0 +1,12 @@
1
+ import { TInput } from './type';
2
+ /** RatingField — оценка звёздами. Значение: число 0…max. */
3
+ export type TRating = TInput & {
4
+ max?: number;
5
+ /** Разрешить сброс повторным кликом по текущей оценке */
6
+ allowClear?: boolean;
7
+ };
8
+ declare function RatingField({ value, form, onValue, onBlur: onBlurField, name, placeholder, label, error, hidden, disabled, className, after, before, max, allowClear, }: TRating): import("react/jsx-runtime").JSX.Element | null;
9
+ declare namespace RatingField {
10
+ var displayName: string;
11
+ }
12
+ export default RatingField;