@elcrm/form 0.0.64 → 0.0.66

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 (41) hide show
  1. package/README.md +55 -27
  2. package/dist/core/Field.d.ts +3 -2
  3. package/dist/core/Field.js +1 -1
  4. package/dist/fields/Date.d.ts +2 -11
  5. package/dist/fields/Date.js +105 -98
  6. package/dist/fields/Input.d.ts +7 -22
  7. package/dist/fields/Input.js +110 -38
  8. package/dist/fields/Mask.d.ts +1 -1
  9. package/dist/fields/Mask.js +54 -48
  10. package/dist/fields/Modal.d.ts +7 -7
  11. package/dist/fields/Modal.js +37 -30
  12. package/dist/fields/Money.d.ts +8 -29
  13. package/dist/fields/Money.js +60 -53
  14. package/dist/fields/Numeric.d.ts +1 -1
  15. package/dist/fields/Numeric.js +46 -42
  16. package/dist/fields/Options.d.ts +9 -7
  17. package/dist/fields/Options.js +38 -32
  18. package/dist/fields/Password.d.ts +1 -1
  19. package/dist/fields/Password.js +90 -37
  20. package/dist/fields/Phone.d.ts +2 -20
  21. package/dist/fields/Phone.js +58 -55
  22. package/dist/fields/Range.d.ts +1 -1
  23. package/dist/fields/Range.js +74 -72
  24. package/dist/fields/Select.d.ts +1 -1
  25. package/dist/fields/Select.js +69 -66
  26. package/dist/fields/Textarea.d.ts +2 -22
  27. package/dist/fields/Textarea.js +37 -32
  28. package/dist/fields/Time.d.ts +1 -1
  29. package/dist/fields/Time.js +65 -63
  30. package/dist/fields/type.d.ts +50 -15
  31. package/dist/fields/visibility.d.ts +6 -0
  32. package/dist/fields/visibility.js +6 -0
  33. package/dist/hooks/use.d.ts +0 -1
  34. package/dist/index.d.ts +1 -1
  35. package/dist/index.js +24 -22
  36. package/dist/loadBaseStyles.d.ts +2 -0
  37. package/dist/loadBaseStyles.js +9 -0
  38. package/dist/package.js +6 -1
  39. package/package.json +6 -1
  40. package/dist/index.umd.js +0 -2
  41. package/dist/style.css +0 -5
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @elcrm/form
2
2
 
3
- React-компоненты полей ввода для elCRM: текст, пароль, маски, деньги, даты, селекты и связка с **`useForm`** (гранулярные подписки по имени поля).
3
+ React-компоненты полей ввода для elCRM: текст, пароль, маски, деньги, даты, время, селект, диапазон и связка с хуком **`useForm`** (подписки по имени поля, без лишних перерисовок всей формы).
4
4
 
5
5
  ## Установка
6
6
 
@@ -8,9 +8,14 @@ React-компоненты полей ввода для elCRM: текст, па
8
8
  npm install @elcrm/form
9
9
  ```
10
10
 
11
- Требуются **peer-зависимости** (см. `package.json`): **`react`** и **`react-dom`**.
11
+ **Peer-зависимости:** **`react`** и **`react-dom`** (версии — в `package.json`).
12
12
 
13
- **`Form.Init` не обязателен** — поля работают без него. Компонент нужен **только** если вы задаёте свои **`onModal`** и/или **`onNotice`** (см. ниже). Рендерит `null`, дерево приложения не оборачивает.
13
+ ## Стили и темы
14
+
15
+ - **Базовые стили полей** (Field / Form / Select) подключаются **сами** при импорте из **корня** пакета: `import { … } from "@elcrm/form"` — отдельный **`import "@elcrm/form/style.css"`** не обязателен.
16
+ - Если используете **только подпути** (`@elcrm/form/fields/Date` и т.д.) без входа с корня — один раз подключите **`@elcrm/form/style.css`** в приложении.
17
+ - **Темы** (светлая / тёмная): **`@elcrm/form/light.css`**, **`@elcrm/form/dark.css`** — атрибут **`data-theme`** на контейнере (подключаются вручную).
18
+ - Склеенный CSS модулей: **`@elcrm/form/style.css`** (дубликат того, что тянет корневой импорт).
14
19
 
15
20
  ## Быстрый старт
16
21
 
@@ -22,31 +27,33 @@ function Example() {
22
27
  const form = useForm({ login: "", password: "" });
23
28
 
24
29
  return (
25
- <>
30
+ <form autoComplete="on" onSubmit={(e) => e.preventDefault()}>
31
+ {/*
32
+ Логин: native + autoComplete — нативный <input> для автозаполнения браузером.
33
+ Без native StringField рендерит contentEditable — автозаполнение логина как у обычной формы не гарантируется.
34
+ */}
26
35
  <StringField
27
36
  name="login"
28
37
  form={form}
29
38
  value=""
30
- title="Логин"
31
- edit
32
- active
39
+ label="Логин"
40
+ native
41
+ autoComplete="username"
33
42
  />
34
43
  <PasswordField
35
44
  name="password"
36
45
  form={form}
37
46
  value=""
38
- title="Пароль"
39
- edit
40
- active
47
+ label="Пароль"
41
48
  />
42
- </>
49
+ </form>
43
50
  );
44
51
  }
45
52
  ```
46
53
 
47
54
  ### `Form.Init` (опционально)
48
55
 
49
- Подключайте, когда нужны **уведомления** (например после копирования телефона в буфер) или **свои модалки** для полей **ModalField**, **OptionsField** (`modal="module.name"`):
56
+ Нужен, если используются **уведомления** (например, копирование телефона в буфер) или **свои модалки** для **ModalField** / **OptionsField** (`modal="module.name"`). Рендерит **`null`**, дочерние элементы не оборачивает.
50
57
 
51
58
  ```tsx
52
59
  import { Form, useForm, PhoneField } from "@elcrm/form";
@@ -71,43 +78,64 @@ function Example() {
71
78
  /* открыть модалку и передать результат в callback(...) */
72
79
  }}
73
80
  />
74
- <PhoneField name="phone" form={form} title="Телефон" edit active />
81
+ <PhoneField name="phone" form={form} label="Телефон" />
75
82
  </>
76
83
  );
77
84
  }
78
85
  ```
79
86
 
80
- Без **`Form.Init`** вызовы **`onNotice` / `onModal`** из полей просто ничего не делают (пустые заглушки).
87
+ Без **`Form.Init`** колбэки **`onNotice`** и **`onModal`** из полей заглушки (no-op).
88
+
89
+ ## Хук `useForm`
90
+
91
+ - **`useForm(initialValues?)`** — хранение значений, **`onValue`** / **`setValue`** / **`setValues`**, подписки по имени поля.
92
+ - Поля с **`name`** и **`form`** читают значение через **`useFormFieldState`** и обновляют форму согласно своей логике.
93
+
94
+ Подробнее о API — в исходниках **`hooks/use.ts`** и **`CHANGELOG.md`**.
81
95
 
82
- Темы: подключите `@elcrm/form/light.css` и `@elcrm/form/dark.css`, переключайте `data-theme` на контейнере.
96
+ ## Общие пропы (`TInput`)
83
97
 
84
- Стили полей (классы из SCSS-модулей): `import "@elcrm/form/style.css"` (альтернатива — `@elcrm/form/dist/style.css`).
98
+ База: **`TFieldFormBindings`** (связь с формой) + **`TFieldPresentation`** (оформление).
99
+
100
+ | Проп | Описание |
101
+ | ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
102
+ | **`name`**, **`form`**, **`value`**, **`onValue`**, **`onBlur`** | Связь с формой; **`onBlur`** — «коммит» после ухода фокуса, аргумент **`{ value, name }`**, не нативный `FocusEvent`. |
103
+ | **`label`**, **`placeholder`**, **`error`**, **`className`**, **`id`** | Подпись, плейсхолдер, текст ошибки, класс блока, id. |
104
+ | **`disabled`** | Только просмотр / без ввода. |
105
+ | **`hidden`** | При **`true`** поле **не рендерится, только если значение пустое**; при непустом — **показывается**. |
106
+ | **`before`**, **`after`** | Узлы до/после области ввода (например иконки). |
107
+ | **`native`** | Только **`StringField`**: нативный **`<input>`** вместо **contentEditable** — для **автозаполнения** логина/почты; сочетать с **`autoComplete`**, **`inputType`**. |
108
+ | **`autoComplete`**, **`inputType`** | Атрибуты нативного поля при **`native`** (например **`username`**, **`email`**). |
109
+ | **`inputmode`**, **`spellCheck`**, **`maxLength`** | Подсказки ввода (в т.ч. мобильная клавиатура), орфография, лимит длины — по смыслу каждого компонента. |
110
+
111
+ У **`PasswordField`** свой тип **`TPasswordField`**: проп **`native`** там означает **«не рендерить компонент»** (внешний нативный пароль), не путать с **`native`** у **`StringField`**.
112
+
113
+ ### `PasswordField`
114
+
115
+ - Нативный **`<input type="password"`** / **`text`** при показе пароля.
116
+ - Переключатель «показать / скрыть» с **встроенными SVG-иконками**; свои иконки — проп **`eyes={[показать, скрыть]}`**.
85
117
 
86
118
  ### Минимальный бандл (tree-shaking)
87
119
 
88
- Пакет собран как **ESM по модулям** — бандлер приложения может отбросить неиспользуемые поля. Импорт из корня:
120
+ Пакет собран как **ESM по модулям**. Импорт из корня:
89
121
 
90
122
  ```ts
91
123
  import { DateField, useForm } from "@elcrm/form";
92
124
  ```
93
125
 
94
- Чтобы подключать только нужные части, используйте **подпути** (имя совпадает с компонентом, например `Date` → поле даты):
126
+ Подключение только нужных файлов **подпути** (имя файла совпадает с компонентом):
95
127
 
96
128
  ```ts
97
129
  import DateField from "@elcrm/form/fields/Date";
98
130
  import { useForm } from "@elcrm/form/hooks/use";
99
131
  ```
100
132
 
101
- Доступные префиксы: `fields/*`, `hooks/*`, `events/*`, `core/*`, `mask/*` — см. поле **`exports`** в `package.json` пакета.
102
-
103
- Объектные пропы (например `options` у селекта) не создавайте заново на каждый рендер — вынесите в константу модуля или держите одну ссылку.
104
-
105
- Типы **`TModalOpenPayload`**, **`FormInitProps`** экспортируются из пакета. Хук **`useFormInit()`** внутри полей; без **`Form.Init`** возвращаются заглушки — можно вызывать и в своих компонентах.
133
+ Префиксы: **`fields/*`**, **`hooks/*`**, **`events/*`**, **`core/*`**, **`mask/*`** — см. **`exports`** в **`package.json`**.
106
134
 
107
- ## История изменений
135
+ Объектные пропы (**`options`** у селекта и т.д.) не пересоздавайте на каждый рендер — вынесите в константы модуля.
108
136
 
109
- Список версий и правок — в **`CHANGELOG.md`** в репозитории пакета.
137
+ ## Экспорт компонентов (корень пакета)
110
138
 
111
- ## Лицензия
139
+ `StringField`, `PasswordField`, `TextareaField`, `NumberField`, `MoneyField`, `MaskField`, `PhoneField`, `DateField`, `TimeField`, `SelectField`, `RangeField`, `ModalField`, `OptionsField`, **`Form`**, хуки **`useForm`**, **`useFormField`**, **`useFormFieldState`**, **`useFormInit`**.
112
140
 
113
- MIT см. `package.json`.
141
+ Типы: **`TInput`**, **`TPasswordField`**, **`TValue`**, **`TFieldFormBindings`**, **`TFieldPresentation`**, **`UseFormApi`**, **`FormInitProps`**, **`TModalOpenPayload`** и др.
@@ -7,12 +7,13 @@ interface Input {
7
7
  className?: string[];
8
8
  props?: Record<string, unknown>;
9
9
  };
10
- title?: string;
10
+ /** Текст подписи поля (колонка `<dt>`) */
11
+ label?: string;
11
12
  before?: ReactNode;
12
13
  type?: string;
13
14
  after?: ReactNode;
14
15
  children?: ReactNode;
15
16
  error?: string;
16
17
  }
17
- declare const Field: ({ element_blok, element_input, type, title, error, before, after, children, }: Input) => import("react/jsx-runtime").JSX.Element;
18
+ declare const Field: ({ element_blok, element_input, type, label, error, before, after, children, }: Input) => import("react/jsx-runtime").JSX.Element;
18
19
  export default Field;
@@ -4,7 +4,7 @@ import { jsx as t, jsxs as n } from "react/jsx-runtime";
4
4
  var r = ({ element_blok: r = { className: [] }, element_input: i = {
5
5
  className: [],
6
6
  props: {}
7
- }, type: a = "input", title: o, error: s, before: c, after: l, children: u }) => /* @__PURE__ */ n("dl", {
7
+ }, type: a = "input", label: o, error: s, before: c, after: l, children: u }) => /* @__PURE__ */ n("dl", {
8
8
  "data-field": a,
9
9
  className: [e.l, ...r.className || []].filter((e) => e !== void 0).join(" "),
10
10
  children: [
@@ -5,17 +5,8 @@ type TDate = TInput & {
5
5
  min?: Date;
6
6
  icon?: () => React.JSX.Element;
7
7
  };
8
- /**
9
- * DateField component
10
- *
11
- * @param {string} [title] - заголовок
12
- * @param {string} [error] - ошибка
13
- * @param {boolean} [edit] - редактировать
14
- * @param {boolean} [active] - активность
15
- * @param {string} [className] - css class
16
- * @param {string} [placeholder] - placeholder
17
- */
18
- declare function DateField({ title, label, error, edit, active, className, placeholder, max, min, onValue, form, icon, name, value, after, disabled, }: TDate): import("react/jsx-runtime").JSX.Element;
8
+ /** DateField — дата с выпадающим календарём. */
9
+ declare function DateField({ label, error, hidden, className, placeholder, disabled, onValue, max, min, form, icon, name, value, after, before, }: TDate): import("react/jsx-runtime").JSX.Element;
19
10
  declare namespace DateField {
20
11
  var displayName: string;
21
12
  }
@@ -1,19 +1,20 @@
1
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 "../styles/Form.module.js";
5
- import i from "react";
6
- import { Fragment as a, jsx as o, jsxs as s } from "react/jsx-runtime";
7
- import { createPortal as c } from "react-dom";
2
+ import t from "../styles/Form.module.js";
3
+ import n from "../core/Field.js";
4
+ import { useFormFieldState as r } from "../hooks/use.js";
5
+ import { isEmptyTextLike as i } from "./visibility.js";
6
+ import a from "react";
7
+ import { Fragment as o, jsx as s, jsxs as c } from "react/jsx-runtime";
8
+ import { createPortal as l } from "react-dom";
8
9
  //#region src/lib/fields/Date.tsx
9
- function l(e, t, n, r) {
10
+ function u(e, t, n, r) {
10
11
  let i = new Date(e, t - 1, 1);
11
12
  return !(n && new Date(e, t, 0) < n || r && i > r);
12
13
  }
13
- function u(e, t, n) {
14
+ function d(e, t, n) {
14
15
  return !(t && e < t.getFullYear() || n && e > n.getFullYear());
15
16
  }
16
- function d(e, t, n) {
17
+ function f(e, t, n) {
17
18
  let r = e;
18
19
  if (t) {
19
20
  let e = t.getFullYear();
@@ -25,70 +26,76 @@ function d(e, t, n) {
25
26
  }
26
27
  return r;
27
28
  }
28
- function f({ title: r, label: l = "", error: u, edit: d = !0, active: f = !0, className: m, placeholder: h, max: _, min: v, onValue: y, form: b, icon: x, name: S = "", value: C, after: w, disabled: T = !1 }) {
29
- let E = i.useCallback((e) => e == null ? /* @__PURE__ */ new Date() : e instanceof Date || typeof e == "string" || typeof e == "number" ? e : /* @__PURE__ */ new Date(), []), { value: D, version: O } = n(b, S, C), [k, A] = i.useState(E(D)), j = i.useRef({
29
+ function p({ label: t = "", error: u, hidden: d = !1, className: f, placeholder: p, disabled: h = !1, onValue: g, max: v, min: y, form: b, icon: x, name: S = "", value: C, after: w = "", before: T = "" }) {
30
+ let E = a.useCallback((e) => e == null ? /* @__PURE__ */ new Date() : e instanceof Date || typeof e == "string" || typeof e == "number" ? e : /* @__PURE__ */ new Date(), []), { value: D, version: O } = r(b, S, C), [k, A] = a.useState(E(D)), j = a.useRef({
30
31
  x: 0,
31
32
  y: 0,
32
33
  b: 0
33
- }), [M, N] = i.useState(!1), P = !d && f;
34
- i.useEffect(() => {
34
+ }), [M, N] = a.useState(!1);
35
+ a.useEffect(() => {
35
36
  A(E(D));
36
37
  }, [
37
38
  D,
38
39
  O,
39
40
  E
40
41
  ]);
41
- let F = (e) => {
42
+ let P = (e) => {
42
43
  let t = {
43
44
  value: e,
44
45
  name: S
45
46
  };
46
- b && S ? b.setValue(t) : A(e), y && y !== b?.onValue && y(t);
47
- }, I = (e) => {
48
- if (T || !(d && f)) return;
47
+ b && S ? b.setValue(t) : A(e), g && g !== b?.onValue && g(t);
48
+ }, F = (e) => {
49
+ if (h) return;
49
50
  let t = e.currentTarget.getBoundingClientRect();
50
51
  j.current = {
51
52
  x: t.left,
52
53
  b: t.bottom,
53
54
  y: t.top
54
55
  }, N(!0);
55
- }, L = {};
56
- return h && (L.placeholder = h), P ? /* @__PURE__ */ o(a, {}) : /* @__PURE__ */ s(a, { children: [x ? x() : /* @__PURE__ */ s(t, {
56
+ }, I = {};
57
+ p && (I.placeholder = p);
58
+ let L = D == null || D === "" || typeof D == "string" && i(D);
59
+ return d && L ? /* @__PURE__ */ s(o, {}) : /* @__PURE__ */ c(o, { children: [x ? x() : /* @__PURE__ */ c(n, {
57
60
  type: "date",
58
- title: r || l,
61
+ label: t,
59
62
  error: u,
60
- element_blok: { className: [m || ""] },
63
+ element_blok: { className: [f || ""] },
61
64
  element_input: {
62
65
  className: [e.w],
63
- props: { "data-disabled": T || !(d && f) ? "true" : void 0 }
66
+ props: { "data-disabled": h ? "true" : void 0 }
64
67
  },
65
- children: [/* @__PURE__ */ o("div", {
66
- onClick: I,
67
- onKeyDown: (e) => {
68
- (e.key === "Enter" || e.key === " ") && (e.preventDefault(), I(e));
69
- },
70
- tabIndex: T || !(d && f) ? -1 : 0,
71
- role: "button",
72
- "aria-haspopup": "dialog",
73
- "aria-expanded": M,
74
- "aria-label": r || l || h || "Дата",
75
- "data-edit": d && f ? "true" : void 0,
76
- ...L,
77
- style: { cursor: T || !(d && f) ? "not-allowed" : "pointer" },
78
- children: g(k, "dd.mm.yyyy")
79
- }, O), w]
80
- }), M && c(/* @__PURE__ */ o(p, {
68
+ children: [
69
+ T,
70
+ /* @__PURE__ */ s("div", {
71
+ onClick: F,
72
+ onKeyDown: (e) => {
73
+ (e.key === "Enter" || e.key === " ") && (e.preventDefault(), F(e));
74
+ },
75
+ tabIndex: h ? -1 : 0,
76
+ role: "button",
77
+ "aria-haspopup": "dialog",
78
+ "aria-expanded": M,
79
+ "aria-label": t || p || "Дата",
80
+ "data-edit": h ? void 0 : "true",
81
+ ...I,
82
+ style: { cursor: h ? "not-allowed" : "pointer" },
83
+ children: _(k, "dd.mm.yyyy")
84
+ }, O),
85
+ w
86
+ ]
87
+ }), M && l(/* @__PURE__ */ s(m, {
81
88
  position: j.current,
82
- onValue: F,
89
+ onValue: P,
83
90
  date: k,
84
- max: _,
85
- min: v,
91
+ max: v,
92
+ min: y,
86
93
  onOpen: N,
87
- className: m
94
+ className: f
88
95
  }, (/* @__PURE__ */ new Date()).getTime()), document.body)] });
89
96
  }
90
- f.displayName = "DateField";
91
- var p = ({ date: e, onValue: t, position: n, max: c, min: f, className: p, onOpen: g }) => {
97
+ p.displayName = "DateField";
98
+ var m = ({ date: e, onValue: n, position: r, max: i, min: l, className: p, onOpen: m }) => {
92
99
  let _ = /* @__PURE__ */ new Date(), v = new Date(e), y = {
93
100
  y: _.getFullYear(),
94
101
  d: _.getDate(),
@@ -97,10 +104,10 @@ var p = ({ date: e, onValue: t, position: n, max: c, min: f, className: p, onOpe
97
104
  y: v.getFullYear(),
98
105
  d: v.getDate(),
99
106
  m: v.getMonth() + 1
100
- }, [x, S] = i.useState({
107
+ }, [x, S] = a.useState({
101
108
  y: b.y,
102
109
  m: b.m
103
- }), [C, w] = i.useState("days"), [T, E] = i.useState(() => d(b.y - 5, f, c)), D = (e) => {
110
+ }), [C, w] = a.useState("days"), [T, E] = a.useState(() => f(b.y - 5, l, i)), D = (e) => {
104
111
  let t = e.getDay();
105
112
  return t === 0 && (t = 7), t - 1;
106
113
  }, O = [
@@ -115,29 +122,29 @@ var p = ({ date: e, onValue: t, position: n, max: c, min: f, className: p, onOpe
115
122
  for (let e = 0; e < D(A); e++) j.push(0);
116
123
  for (; A.getMonth() === k;) j.push(A.getDate()), A.setDate(A.getDate() + 1);
117
124
  let M = () => {
118
- g(!1);
125
+ m(!1);
119
126
  }, N = () => {
120
127
  V(x.m + 1, x.y);
121
128
  }, P = () => {
122
129
  V(x.m - 1, x.y);
123
130
  }, F = () => {
124
- C === "days" ? P() : C === "months" ? V(x.m, x.y - 1) : E((e) => d(e - 12, f, c));
131
+ C === "days" ? P() : C === "months" ? V(x.m, x.y - 1) : E((e) => f(e - 12, l, i));
125
132
  }, I = () => {
126
- C === "days" ? N() : C === "months" ? V(x.m, x.y + 1) : E((e) => d(e + 12, f, c));
133
+ C === "days" ? N() : C === "months" ? V(x.m, x.y + 1) : E((e) => f(e + 12, l, i));
127
134
  }, L = (e) => {
128
- e.stopPropagation(), E(d(x.y - 5, f, c)), w("years");
135
+ e.stopPropagation(), E(f(x.y - 5, l, i)), w("years");
129
136
  }, R = (e) => {
130
- l(x.y, e, f, c) && (S({
137
+ u(x.y, e, l, i) && (S({
131
138
  y: x.y,
132
139
  m: e
133
140
  }), w("days"));
134
141
  }, z = (e) => {
135
- u(e, f, c) && (S({
142
+ d(e, l, i) && (S({
136
143
  y: e,
137
144
  m: x.m
138
145
  }), w("days"));
139
146
  }, B = (e) => {
140
- t(x.y + "-" + h(2, x.m) + "-" + h(2, e)), M();
147
+ n(x.y + "-" + g(2, x.m) + "-" + g(2, e)), M();
141
148
  }, V = (e, t) => {
142
149
  t = e > 12 ? t + 1 : e < 1 ? t - 1 : t, e = e > 12 ? 1 : e < 1 ? 12 : e, S({
143
150
  y: t,
@@ -145,105 +152,105 @@ var p = ({ date: e, onValue: t, position: n, max: c, min: f, className: p, onOpe
145
152
  });
146
153
  }, H = (e) => y.y === x.y && y.m === x.m && y.d === e ? { "data-active": "true" } : {}, U = (e) => b.y === x.y && b.m === x.m && b.d === e ? { "data-current": "true" } : {}, W = (e) => {
147
154
  let t = !0;
148
- return c && c.getTime() < new Date(x.y, x.m - 1, e).getTime() && (t = !1), f && f.getTime() > new Date(x.y, x.m - 1, e).getTime() && (t = !1), t;
149
- }, G = window.innerHeight - n.b < 360 ? Math.max(8, n.y - 360) : n.b, K = window.innerWidth - n.x < 270 ? n.x - 246 : n.x;
150
- return /* @__PURE__ */ s(a, { children: [/* @__PURE__ */ o("div", {
151
- className: r.o,
155
+ return i && i.getTime() < new Date(x.y, x.m - 1, e).getTime() && (t = !1), l && l.getTime() > new Date(x.y, x.m - 1, e).getTime() && (t = !1), t;
156
+ }, G = window.innerHeight - r.b < 360 ? Math.max(8, r.y - 360) : r.b, K = window.innerWidth - r.x < 270 ? r.x - 246 : r.x;
157
+ return /* @__PURE__ */ c(o, { children: [/* @__PURE__ */ s("div", {
158
+ className: t.o,
152
159
  onClick: () => M()
153
- }), /* @__PURE__ */ s("div", {
154
- className: [r.c, p && p + "-backdrop"].join(" "),
160
+ }), /* @__PURE__ */ c("div", {
161
+ className: [t.c, p && p + "-backdrop"].join(" "),
155
162
  style: {
156
163
  top: G + "px",
157
164
  left: K + "px"
158
165
  },
159
166
  onClick: (e) => e.stopPropagation(),
160
167
  children: [
161
- /* @__PURE__ */ s("s", { children: [
162
- /* @__PURE__ */ o("i", {
168
+ /* @__PURE__ */ c("s", { children: [
169
+ /* @__PURE__ */ s("i", {
163
170
  onClick: (e) => {
164
171
  e.stopPropagation(), F();
165
172
  },
166
- children: /* @__PURE__ */ o("svg", {
173
+ children: /* @__PURE__ */ s("svg", {
167
174
  width: "16",
168
175
  height: "16",
169
176
  fill: "currentColor",
170
177
  viewBox: "0 0 24 24",
171
178
  xmlns: "http://www.w3.org/2000/svg",
172
- children: /* @__PURE__ */ o("path", { d: "m15.09 4.594-7.646 6.553a1.126 1.126 0 0 0 0 1.708l7.647 6.552c.73.625 1.857.107 1.857-.854V5.447c0-.961-1.127-1.48-1.857-.853Z" })
179
+ children: /* @__PURE__ */ s("path", { d: "m15.09 4.594-7.646 6.553a1.126 1.126 0 0 0 0 1.708l7.647 6.552c.73.625 1.857.107 1.857-.854V5.447c0-.961-1.127-1.48-1.857-.853Z" })
173
180
  })
174
181
  }),
175
- /* @__PURE__ */ s("h2", { children: [/* @__PURE__ */ o("span", {
176
- className: r.dateHeaderMonth,
182
+ /* @__PURE__ */ c("h2", { children: [/* @__PURE__ */ s("span", {
183
+ className: t.dateHeaderMonth,
177
184
  onClick: (e) => {
178
185
  e.stopPropagation(), w(C === "years" ? "months" : C === "months" ? "days" : "months");
179
186
  },
180
187
  title: C === "years" ? "К списку месяцев" : C === "months" ? "К календарю" : "Выбрать месяц",
181
- children: m(x.m).name
182
- }), /* @__PURE__ */ o("span", {
183
- className: r.dateHeaderYear,
188
+ children: h(x.m).name
189
+ }), /* @__PURE__ */ s("span", {
190
+ className: t.dateHeaderYear,
184
191
  onClick: (e) => {
185
192
  e.stopPropagation(), C === "years" ? w("days") : L(e);
186
193
  },
187
194
  title: C === "years" ? "К календарю" : "Выбрать год",
188
195
  children: x.y
189
196
  })] }),
190
- /* @__PURE__ */ o("i", {
197
+ /* @__PURE__ */ s("i", {
191
198
  onClick: (e) => {
192
199
  e.stopPropagation(), I();
193
200
  },
194
- children: /* @__PURE__ */ o("svg", {
201
+ children: /* @__PURE__ */ s("svg", {
195
202
  width: "16",
196
203
  height: "16",
197
204
  fill: "currentColor",
198
205
  viewBox: "0 0 24 24",
199
206
  xmlns: "http://www.w3.org/2000/svg",
200
- children: /* @__PURE__ */ o("path", { d: "m8.91 19.406 7.646-6.552a1.125 1.125 0 0 0 0-1.709L8.91 4.593c-.73-.625-1.857-.107-1.857.854v13.107c0 .96 1.127 1.479 1.857.852Z" })
207
+ children: /* @__PURE__ */ s("path", { d: "m8.91 19.406 7.646-6.552a1.125 1.125 0 0 0 0-1.709L8.91 4.593c-.73-.625-1.857-.107-1.857.854v13.107c0 .96 1.127 1.479 1.857.852Z" })
201
208
  })
202
209
  })
203
210
  ] }),
204
- C === "days" && /* @__PURE__ */ s("div", {
211
+ C === "days" && /* @__PURE__ */ c("div", {
205
212
  "grid-calendar": "",
206
- children: [O.map((e, t) => /* @__PURE__ */ o("p", { children: e }, "v" + t)), j.map((e, t) => /* @__PURE__ */ o("span", { children: e !== 0 && W(e) ? /* @__PURE__ */ o("b", {
213
+ children: [O.map((e, t) => /* @__PURE__ */ s("p", { children: e }, "v" + t)), j.map((e, t) => /* @__PURE__ */ s("span", { children: e !== 0 && W(e) ? /* @__PURE__ */ s("b", {
207
214
  ...H(e),
208
215
  ...U(e),
209
216
  onClick: () => B(e),
210
217
  children: e
211
- }) : /* @__PURE__ */ o("p", {
218
+ }) : /* @__PURE__ */ s("p", {
212
219
  ...H(e),
213
220
  ...U(e),
214
221
  children: e === 0 ? "" : e
215
222
  }) }, t))]
216
223
  }),
217
- C === "months" && /* @__PURE__ */ o("div", {
224
+ C === "months" && /* @__PURE__ */ s("div", {
218
225
  "grid-month": "",
219
- children: Array.from({ length: 12 }, (e, t) => {
220
- let n = t + 1, i = l(x.y, n, f, c), a = y.y === x.y && y.m === n ? { "data-active": "true" } : {}, s = b.y === x.y && b.m === n ? { "data-current": "true" } : {};
221
- return /* @__PURE__ */ o("b", {
222
- className: i ? "" : r.dateHeaderDisabled,
223
- ...a,
224
- ...s,
225
- onClick: () => i && R(n),
226
- children: m(n).abc
227
- }, n);
226
+ children: Array.from({ length: 12 }, (e, n) => {
227
+ let r = n + 1, a = u(x.y, r, l, i), o = y.y === x.y && y.m === r ? { "data-active": "true" } : {}, c = b.y === x.y && b.m === r ? { "data-current": "true" } : {};
228
+ return /* @__PURE__ */ s("b", {
229
+ className: a ? "" : t.dateHeaderDisabled,
230
+ ...o,
231
+ ...c,
232
+ onClick: () => a && R(r),
233
+ children: h(r).abc
234
+ }, r);
228
235
  })
229
236
  }),
230
- C === "years" && /* @__PURE__ */ o("div", {
237
+ C === "years" && /* @__PURE__ */ s("div", {
231
238
  "grid-month": "",
232
- children: Array.from({ length: 12 }, (e, t) => {
233
- let n = T + t, i = u(n, f, c), a = y.y === n ? { "data-active": "true" } : {}, s = b.y === n ? { "data-current": "true" } : {};
234
- return /* @__PURE__ */ o("b", {
235
- className: i ? "" : r.dateHeaderDisabled,
236
- ...a,
237
- ...s,
238
- onClick: () => i && z(n),
239
- children: n
240
- }, n);
239
+ children: Array.from({ length: 12 }, (e, n) => {
240
+ let r = T + n, a = d(r, l, i), o = y.y === r ? { "data-active": "true" } : {}, c = b.y === r ? { "data-current": "true" } : {};
241
+ return /* @__PURE__ */ s("b", {
242
+ className: a ? "" : t.dateHeaderDisabled,
243
+ ...o,
244
+ ...c,
245
+ onClick: () => a && z(r),
246
+ children: r
247
+ }, r);
241
248
  })
242
249
  })
243
250
  ]
244
251
  })] });
245
252
  };
246
- function m(e) {
253
+ function h(e) {
247
254
  return e = typeof e == "number" ? e : new Date(e).getMonth() + 1, {
248
255
  1: {
249
256
  val: "01",
@@ -319,12 +326,12 @@ function m(e) {
319
326
  }
320
327
  }[e];
321
328
  }
322
- function h(e, t) {
329
+ function g(e, t) {
323
330
  let n = t + "";
324
331
  for (; n.length < e;) n = "0" + n;
325
332
  return n;
326
333
  }
327
- function g(e, t) {
334
+ function _(e, t) {
328
335
  let n, r;
329
336
  t === void 0 ? (r = String(e), n = /* @__PURE__ */ new Date()) : (r = t, n = new Date(e));
330
337
  let i = r, a = {
@@ -342,4 +349,4 @@ function g(e, t) {
342
349
  return i;
343
350
  }
344
351
  //#endregion
345
- export { f as default };
352
+ export { p as default };
@@ -1,27 +1,12 @@
1
1
  import { TInput } from './type';
2
2
  /**
3
- * StringField component
3
+ * StringField — текстовое поле (по умолчанию contentEditable).
4
4
  *
5
- * @param {string} value - Значение поля ввода.
6
- * @param {Function} onValue - Колбэк при изменении значения.
7
- * @param {Function} [onSave] - Колбэк при сохранении значения (например, при потере фокуса).
8
- * @param {string} [name] - Имя поля.
9
- * @param {string} [placeholder] - Текст-подсказка, отображаемый, когда поле пустое.
10
- * @param {string} [title] - Заголовок или подпись для поля.
11
- * @param {string} [label] - Метка поля (альтернативное описание).
12
- * @param {string} [error] - Текст ошибки для индикации некорректного ввода.
13
- * @param {boolean} [hide] - Признак скрытия поля.
14
- * @param {boolean} [edit] - Признак возможности редактировать поле.
15
- * @param {Boolean} [active] - Является ли поле активным.
16
- * @param {any} [after] - Контент, отображаемый после поля (например, иконка).
17
- * @param {any} [before] - Контент, отображаемый перед полем.
18
- * @param {Boolean} [show] - Показывать ли поле.
19
- * @param {string} [view] - Тип отображения поля.
20
- * @param {string} [id] - Уникальный идентификатор поля.
21
- * @param {string} [className] - Дополнительные CSS-классы.
22
- * @param {number} [maxLength] - Максимально допустимая длина значения.
23
- * @param {boolean} [isReload] - Нужно ли обновлять данные при изменении.
24
- * @param {boolean} [spellCheck] - Включить проверку орфографии.
5
+ * **Автозаполнение (логин + пароль):** менеджеры паролей опираются на нативные `<input>`.
6
+ * У `contentEditable` автозаполнение **не работает** как у поля логина.
7
+ * Включите **`native`** и задайте **`autoComplete="username"`** оберните поля в `<form>`, при необходимости).
8
+ *
9
+ * @param hidden при true скрывает поле, только если значение пустое
25
10
  */
26
- declare function StringField({ value, form, onValue, name, inputmode, placeholder, title, label, show, hide, edit, active, maxLength, onSave, className, spellCheck, isReload, after, before, error, }: TInput): import("react/jsx-runtime").JSX.Element | "";
11
+ declare function StringField({ value, form, onValue, name, placeholder, label, hidden, disabled, onBlur: onBlurField, className, after, before, error, inputmode, maxLength, spellCheck, native, autoComplete, inputType, id, }: TInput): import("react/jsx-runtime").JSX.Element | "";
27
12
  export default StringField;