form-father 0.6.0 → 0.7.1

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/README.md CHANGED
@@ -410,9 +410,12 @@ registerSchemaValidator('company-email', z.string().email(), 'Введите к
410
410
 
411
411
  ## Демо и рецепты
412
412
 
413
- - `demos/index.html` — статическое демо login/callback/search/upload после `npm run build`.
413
+ - `demos/index.html` — статическое демо login/callback/search/upload/public API после `npm run build`.
414
414
  - `npm run demos` — сборка и запуск Vite-сервера для демо.
415
+ - `docs/api/README.md` — компактный справочник публичного API, опций, методов и экспортов.
416
+ - `docs/demo/README.md` — сценарии ручной проверки демо и описание demo forms.
415
417
  - `docs/recipes/README.md` — короткие рецепты по API, data-атрибутам, adapters и server errors.
418
+ - `CHANGELOG.md` — история релизов и baseline покрытия.
416
419
 
417
420
  ## Сборка и разработка
418
421
 
@@ -420,6 +423,7 @@ registerSchemaValidator('company-email', z.string().email(), 'Введите к
420
423
 
421
424
  - **npm run build**: Сборка проекта.
422
425
  - **npm run watch**: Сборка в режиме наблюдения.
426
+ - **npm run docs:check**: Проверка версии, ссылок документации, demo-файлов и package README.
423
427
  - **npm run demos**: Запуск демо-версии с использованием Vite.
424
428
 
425
429
  ## Вклад
package/package.json CHANGED
@@ -1,25 +1,35 @@
1
1
  {
2
2
  "name": "form-father",
3
- "version": "0.6.0",
3
+ "version": "0.7.1",
4
4
  "description": "Form Father: Библиотека для обработки форм",
5
5
  "type": "module",
6
- "files": ["dist", "README.md", "LICENSE", "RESPONSE_API.md", "CHANGELOG.md", "docs", "demos"],
6
+ "main": "index.js",
7
+ "module": "index.js",
8
+ "types": "index.d.ts",
7
9
  "exports": {
8
10
  ".": {
9
- "import": "./dist/index.js",
10
- "types": "./dist/index.d.ts"
11
- }
11
+ "types": "./index.d.ts",
12
+ "import": "./index.js",
13
+ "default": "./index.js"
14
+ },
15
+ "./FormFather.min.js": "./FormFather.min.js"
12
16
  },
17
+ "unpkg": "./FormFather.min.js",
18
+ "jsdelivr": "./FormFather.min.js",
19
+ "files": [
20
+ "index.js",
21
+ "index.d.ts",
22
+ "FormFather.min.js",
23
+ "*.map",
24
+ "types",
25
+ "README.md",
26
+ "LICENSE",
27
+ "RESPONSE_API.md"
28
+ ],
13
29
  "scripts": {
14
30
  "build": "rollup -c",
15
31
  "watch": "rollup -c -w",
16
32
  "release": "node scripts/release.js",
17
- "release:check": "npm test -- --runInBand --watchman=false && npm run build && npm run smoke:package && npm run pack:dry-run",
18
- "test": "jest --coverage",
19
- "prepublishOnly": "npm test -- --runInBand --watchman=false && npm run build",
20
- "pack:dry-run": "npm_config_cache=/tmp/form-father-npm-cache npm pack --dry-run",
21
- "smoke:package": "node scripts/smoke-package.mjs",
22
- "versions:sync": "node scripts/sync-version.js",
23
33
  "demos": "BUILD_TARGET=demos npm run build && concurrently --kill-others \"vite\" \"npm run watch\""
24
34
  },
25
35
  "repository": {
@@ -47,15 +57,10 @@
47
57
  "@rollup/plugin-json": "^6.1.0",
48
58
  "@rollup/plugin-node-resolve": "^15.3.0",
49
59
  "@rollup/plugin-terser": "^0.4.4",
50
- "@types/jest": "^30.0.0",
51
- "@types/jsdom": "^21.1.7",
52
60
  "chalk": "^5.3.0",
53
61
  "concurrently": "^9.0.1",
54
62
  "fs-extra": "^11.2.0",
55
63
  "inquirer": "^12.1.0",
56
- "jest": "^30.0.5",
57
- "jest-environment-jsdom": "^30.0.5",
58
- "jsdom": "^26.1.0",
59
64
  "ora": "^8.1.1",
60
65
  "postcss-preset-env": "^10.0.8",
61
66
  "prettier-plugin-jsdoc": "^1.3.0",
@@ -65,9 +70,7 @@
65
70
  "rollup-plugin-dts": "^6.1.1",
66
71
  "rollup-plugin-typescript2": "^0.36.0",
67
72
  "sass-embedded": "^1.80.5",
68
- "ts-jest": "^29.4.0",
69
- "ts-node": "^10.9.2",
70
73
  "typescript": "^5.6.3",
71
74
  "vite": "^5.4.10"
72
75
  }
73
- }
76
+ }
package/CHANGELOG.md DELETED
@@ -1,135 +0,0 @@
1
- # Changelog
2
-
3
- All notable changes to this project are documented here.
4
-
5
- ## 0.6.0 - 2026-04-27
6
-
7
- ### Added
8
-
9
- - Added accessible field error wiring via `aria-describedby` with safe preservation of existing descriptions.
10
- - Added `errorSummary` option with default rendering, custom selector support, focus control, and custom renderers.
11
- - Added `ariaDescribeErrors` and `errorIdPrefix` options for UI/a11y integration control.
12
-
13
- ### Changed
14
-
15
- - Field, form-level, backend, and manual errors can now share one visible summary while keeping the existing inline error
16
- rendering path.
17
- - Demo forms now include accessible error summaries.
18
-
19
- ### Tests
20
-
21
- - Test suite expanded to 122 tests.
22
- - Coverage baseline: 98.30% statements, 86.88% branches, 97.25% functions, 100% lines.
23
-
24
- ## 0.5.0 - 2026-04-27
25
-
26
- ### Added
27
-
28
- - Added field validator DX helpers: `registerFieldValidator()`, `createPatternValidator()`, and
29
- `createLengthValidator()`.
30
- - Added form validator DX helpers: `createFormValidator()`, `sameAsField()`, `requiredIf()`, and `dateOrder()`.
31
- - Added helper types for reusable form validator predicates and issue factories.
32
-
33
- ### Changed
34
-
35
- - Demo and documentation now use higher-level helper APIs for common password-confirm and validation rule recipes.
36
-
37
- ### Tests
38
-
39
- - Test suite expanded to 115 tests.
40
- - Coverage baseline: 98.19% statements, 86.91% branches, 97.04% functions, 100% lines.
41
-
42
- ## 0.4.0 - 2026-04-27
43
-
44
- ### Added
45
-
46
- - Added form-level and cross-field validation via `formValidators`.
47
- - Added `setErrors()` for backend maps, `ErrorResponse[]`, global form errors, and custom validation issue objects.
48
- - Added `FORM_ERROR_FIELD` constant for form-level errors in `getErrors()`.
49
- - Added public TypeScript types for form validation contexts and issues.
50
-
51
- ### Changed
52
-
53
- - `validate()` now runs field-level rules first, then form-level validators over `getValues()`.
54
- - Cross-field and backend errors share the same rendering path as field validation errors.
55
-
56
- ### Tests
57
-
58
- - Test suite expanded to 113 tests.
59
- - Coverage baseline: 98.31% statements, 87.05% branches, 96.34% functions, 100% lines.
60
-
61
- ## 0.3.0 - 2026-04-25
62
-
63
- ### Added
64
-
65
- - Added convenience API: `Form.initAll()`, `updateOptions()`, public `submit()`, `validateField()`, `showFieldError()`,
66
- `getErrors()`, `getValues()`, `setValues()`, `clearErrors()`, and `reset()`.
67
- - Added client validation hooks: `onValidationError`, `onBeforeSubmit`, and `onSubmitError`.
68
- - Added live validation options: `validateOn`, `revalidateOn`, `validationDebounce`, and `focusFirstErroredInput`.
69
- - Added `data-validate`, `data-error-*`, and `data-error-container` support while keeping `data-custom-validate`.
70
- - Added optional mutation observing for dynamic fields and submit buttons.
71
- - Added race-safe async field validation state with `aria-busy` and configurable field state attributes.
72
- - Added dependency-free schema adapters: `createSchemaValidator()`, `registerSchemaValidator()`, and
73
- `createFieldValidator()`.
74
- - Added static demos for login, callback/server errors, GET search, and multipart upload.
75
- - Added recipes documentation for common API, data-attribute, adapter, and server-error flows.
76
-
77
- ### Changed
78
-
79
- - Validation now merges every matching schema rule for a field before applying data-attribute rules.
80
- - Server-side field errors now populate the public `getErrors()` list.
81
- - Package contents now include docs, demos, and the changelog.
82
-
83
- ### Tests
84
-
85
- - Test suite expanded to 109 tests.
86
- - Coverage baseline: 98.10% statements, 86.15% branches, 95.69% functions, 100% lines.
87
-
88
- ## 0.2.11 - 2026-04-25
89
-
90
- ### Added
91
-
92
- - Added release checklist, package smoke checks, CI workflow, and release gate scripts.
93
- - Added npm pack dry-run script with a temporary npm cache for local cache permission issues.
94
-
95
- ### Changed
96
-
97
- - Updated package metadata and release workflow after `0.2.10` had already been published.
98
-
99
- ## 0.2.10 - 2026-04-25
100
-
101
- ### Added
102
-
103
- - Exported public helper APIs from the package entrypoint: `serializeToFormData`, validators, URL/email/phone helpers, scroll helpers, and response helpers.
104
- - Exported TypeScript types for public consumers: `FormOptions`, `ValidationRule`, `ValidationSchema`, `ErrorResponse`, and `ResponseBody`.
105
- - Added package smoke checks for built files and public exports.
106
- - Added CI workflow for tests, build, smoke checks, and npm pack dry-run.
107
- - Added coverage thresholds to keep the stabilization baseline from regressing.
108
-
109
- ### Changed
110
-
111
- - `new Form(formEl)` now works without an options object.
112
- - Submit detection now supports implicit submit buttons (`<button>`) and `input[type="image"]`.
113
- - `GET` and `HEAD` forms now append form data to the action query string and do not send a request body.
114
- - `wrapData` now applies consistently across supported encodings: `application/x-www-form-urlencoded`, `multipart/form-data`, `text/plain`, and `application/json`.
115
- - Non-200 HTTP responses, `success !== true`, and invalid JSON responses now flow through `onResponseUnsuccess`.
116
- - Server-side field errors can be applied to `input`, `textarea`, and `select`.
117
- - `serializeToFormData` now skips disabled controls, controls marked with `data-no-serialize`, and button controls.
118
- - Built-in validators are registered idempotently across repeated module imports.
119
-
120
- ### Fixed
121
-
122
- - Loader and `waitResponse` cleanup now runs when `fetch` or response parsing fails.
123
- - Required radio groups now produce one validation error per group.
124
- - Field error rendering no longer requires a wrapper-level `showError()` method.
125
- - Release script now exits with `0` on success and handles missing temporary files during cleanup.
126
- - Rollup IIFE build no longer warns about mixed default and named exports.
127
-
128
- ### Tests
129
-
130
- - Test coverage baseline: 98.32% statements, 86.34% branches, 93.18% functions, 100% lines.
131
- - Test suite baseline: 93 tests passing.
132
-
133
- ## 0.2.9
134
-
135
- - Previous published patch release.
package/RESPONSE_API.md DELETED
@@ -1,233 +0,0 @@
1
- ## Краткое введение
2
-
3
- Эй, ребята! Собрались здесь для того, чтобы понять, как у нас отвечает сервер после того, как отправляем формы через
4
- AJAX. Это будет не какая-то скучная докуха, а всё по-кубански, с размахом и только по сути!
5
-
6
- ## Что и как 🛠️
7
-
8
- ### `success`
9
-
10
- - **Тип**: boolean.
11
- - **Описание**: Флаг, показывающий, всё ли круто.
12
- - **Как Работает**: Если сервер справился, то `true`, а если нет – `false`.
13
-
14
- ### `redirect-url`
15
-
16
- - **Тип**: string (опционально).
17
- - **Описание**: Куда пойти, если всё зашибись.
18
- - **Когда Появляется**: Только если `success` равно `true`.
19
-
20
- ### `redirect-url-delay`
21
-
22
- - **Тип**: number (опционально).
23
- - **Описание**: Задержка в ms перед редиректом.
24
-
25
- ### `reload`
26
-
27
- - **Тип**: boolean (опционально).
28
- - **Описание**: Как перезагрузить страничку.
29
- - **Когда Используем**: Когда сервер скажет "обновись".
30
-
31
- ### `reload-delay`
32
-
33
- - **Тип**: number (опционально).
34
- - **Описание**: Задержка в ms перед перезагрузкой страницы.
35
-
36
- ### `error`
37
-
38
- - **Тип**: boolean (опционально).
39
- - **Описание**: Флаг о проблемах.
40
- - **Как Работает**: Если есть косяк, то `true`.
41
-
42
- ### `error-msg`
43
-
44
- - **Тип**: string (опционально).
45
- - **Описание**: Пояснения от сервера о косяке.
46
- - **Пример**: "Тут беда, братишка".
47
-
48
- ### `errors`
49
-
50
- - **Тип**: array (опционально).
51
- - **Описание**: Список мелких недоразумений.
52
- - **Содержание**: Конкретные поля и тексты ошибок.
53
-
54
- Каждый объект в массиве содержит:
55
-
56
- - `name` (string): Имя поля, в котором произошла ошибка.
57
- - `error-msg` (string): Текст ошибки для данного поля.
58
-
59
- ### `error-toast`
60
-
61
- - Тип: string (опционально).
62
- - Описание: Выводится всплывашка(toast) с ошибкой.
63
- - Пример: "Тут беда, братишка".
64
-
65
- > [!Caution]
66
- > `error-toast` DEPRECATED!!!
67
-
68
- ### `toast`
69
- - Тип: объект | массив объектов.
70
- - Описание: Выводит определённый тип тоста и передаёт опции.
71
- - Пример, один тост:
72
- ```
73
- {
74
- type: 'success',
75
- title: 'Успешно',
76
- }
77
- ```
78
-
79
- - Пример, несколько тостов за раз:
80
- ```
81
- [
82
- {
83
- type: 'success',
84
- title: 'Успешно',
85
- },
86
- {
87
- type: 'error',
88
- title: 'Ошибка',
89
- }
90
- ]
91
- ```
92
-
93
-
94
- ## Примеры ответов 📝
95
-
96
- ### `Когда всё чик-пук, и можно идти дальше.`
97
-
98
- ```json
99
- {
100
- "success": true,
101
- }
102
- ```
103
-
104
- ### `Если нужен редирект.`
105
-
106
- ```json
107
- {
108
- "success": true,
109
- "redirect-url": "https://example.com/success",
110
- "redirect-url-delay": 5000, // если нужна задержка перед редиректом
111
- }
112
- ```
113
-
114
- ### `Если нужна перезагрузка страницы.`
115
-
116
- ```json
117
- {
118
- "success": true,
119
- "reload": true,
120
- "reload-delay": 5000, // если нужна задержка перед обновлением страницы
121
- }
122
- ```
123
-
124
- ### `Когда надо что-то менять.`
125
-
126
- ```json
127
- {
128
- "success": false,
129
- "error": true,
130
- "error-msg": "Тут беда, братишка",
131
- "errors": [
132
- {
133
- "name": "email",
134
- "error-msg": "Эй, мэйл какой-то кривой"
135
- }
136
- ]
137
- }
138
- ```
139
-
140
- Вот и всё, ребятки! Теперь вы знаете, как наш сервер отзывается на ваши AJAX-формы. Дерзайте!
141
-
142
- # Как работать с e-commerce
143
-
144
- - В сниппете #src/snippets/\_ym-metrika.html лежит пример кода инициализации Яндекс.Метрики.
145
- - В скрипте с id='ecommerceScript' есть 2 важных момента: первый - это пример запуска необходимого кода сразу после
146
- инициализации Яндекс.метрики, а второй - это функция, которая принимает данные и с учётом этого происходят действия
147
- необходимые для метрик.
148
- - На данный момент существует только 4 события: `click`, `submit`, `ajax-success` и `ajax-fail`.
149
- - Атрибут `data-ecom-data` нужно указывать, только для тех событий, которые не ожидают ответа от сервера.
150
-
151
- ## Примеры использования атрибутов:
152
-
153
- ### Обычный клик на ссылке
154
-
155
- ```html
156
- <a
157
- href="#"
158
- data-ecom-action="click"
159
- data-ecom-data='{
160
- "click": {
161
- "ymCounter123123123": "pull-right",
162
- "dataLayer": []
163
- }
164
- }'
165
- >
166
- Оформить заказ
167
- </a>
168
- ```
169
-
170
- ### Множественное количество событий на Форме-кнопке
171
-
172
- ```html
173
- <button
174
- data-form-button
175
- data-form-button-action="/endpoint"
176
- data-form-button-method="POST"
177
- data-form-button-data='{"someProperties": "1234"}'
178
- data-ecom-action="click,ajax-success,submit"
179
- data-ecom-data='{
180
- "click": {
181
- "ymCounter123123123": "pull-right",
182
- "dataLayer": []
183
- },
184
- "submit": {
185
- "ymCounter123123123": "pull-right",
186
- "dataLayer": []
187
- }
188
- }'
189
- >
190
- Оформить заказ
191
- </button>
192
- ```
193
-
194
- ### Cобытие у элемента формы
195
-
196
- ```html
197
- <form
198
- class="ordering-page__body"
199
- action="/api/order/"
200
- method="POST"
201
- name="ORDER_FORM"
202
- enctype="multipart/form-data"
203
- novalidate
204
- data-ecom-action="ajax-success"
205
- >
206
- ...
207
- </form>
208
- ```
209
-
210
- # Сериализация форм и полей
211
-
212
- ## Работа с атрибутом `data-no-serialize-before-changes`
213
-
214
- ### Общее описание
215
-
216
- Атрибут `data-no-serialize-before-changes` предназначен для контроля сериализации полей формы в AJAX-запросах. С его
217
- помощью можно указать, какие поля формы не должны быть сериализованы и отправлены на сервер до того момента, как в них
218
- произойдут изменения со стороны пользователя.
219
-
220
- ### Применение
221
-
222
- Для использования атрибута достаточно добавить его к любому элементу формы, например, `<input>`, `<select>` или
223
- `<textarea>`. Пока пользователь не изменит значение такого поля, оно не будет включено в сериализованные данные формы
224
- при AJAX-запросе.
225
-
226
- ### Пример
227
-
228
- ```html
229
- <input type="text" name="user-email" data-no-serialize-before-changes />
230
- ```
231
-
232
- В данном случае, поле для ввода email пользователя не будет сериализовано и отправлено на сервер до тех пор, пока
233
- пользователь явно не изменит его содержимое.
package/demos/index.html DELETED
@@ -1,161 +0,0 @@
1
- <!doctype html>
2
- <html lang="ru">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>Form Father demos</title>
7
- <link rel="stylesheet" href="./styles.css" />
8
- </head>
9
- <body>
10
- <header class="demo-header">
11
- <div>
12
- <p class="eyebrow">Form Father</p>
13
- <h1>Демо форм, валидации и ответов сервера</h1>
14
- </div>
15
- <a class="github-link" href="https://github.com/Poliklot/form-father">GitHub</a>
16
- </header>
17
-
18
- <main class="demo-grid">
19
- <section class="demo-panel">
20
- <div class="panel-title">
21
- <p class="eyebrow">Login</p>
22
- <h2>Live validation</h2>
23
- </div>
24
- <form data-form-father action="/demo/login" method="post" enctype="application/json" data-demo="login" novalidate>
25
- <div data-form-father-summary hidden></div>
26
-
27
- <label class="field">
28
- <span>Email</span>
29
- <input
30
- class="input"
31
- name="email"
32
- type="email"
33
- autocomplete="email"
34
- data-validate="required|email|available-email"
35
- data-error-required="Email обязателен"
36
- data-error-email="Введите корректный email"
37
- data-error-available-email="Этот email уже занят"
38
- data-error-container="#login-email-error"
39
- />
40
- <small id="login-email-error" class="field-error" hidden></small>
41
- </label>
42
-
43
- <label class="field">
44
- <span>Password</span>
45
- <input
46
- class="input"
47
- name="password"
48
- type="password"
49
- autocomplete="current-password"
50
- data-validate="required|min-length:6"
51
- data-error-required="Пароль обязателен"
52
- data-error-min-length="Минимум 6 символов"
53
- />
54
- </label>
55
-
56
- <label class="field">
57
- <span>Repeat password</span>
58
- <input
59
- class="input"
60
- name="passwordConfirm"
61
- type="password"
62
- autocomplete="current-password"
63
- data-validate="required"
64
- data-error-required="Повторите пароль"
65
- />
66
- </label>
67
-
68
- <button type="submit">Войти</button>
69
- </form>
70
- </section>
71
-
72
- <section class="demo-panel">
73
- <div class="panel-title">
74
- <p class="eyebrow">Callback</p>
75
- <h2>Server field errors</h2>
76
- </div>
77
- <form data-form-father action="/demo/callback" method="post" data-demo="callback" novalidate>
78
- <div data-form-father-summary hidden></div>
79
-
80
- <label class="field">
81
- <span>Имя</span>
82
- <input class="input" name="name" data-validate="required" data-error-required="Укажите имя" />
83
- </label>
84
-
85
- <label class="field">
86
- <span>Телефон</span>
87
- <input
88
- class="input"
89
- name="tel"
90
- type="tel"
91
- placeholder="+79991234567"
92
- data-validate="required|tel"
93
- data-error-tel="Телефон в формате +7XXXXXXXXXX"
94
- />
95
- </label>
96
-
97
- <button type="submit">Заказать звонок</button>
98
- </form>
99
- </section>
100
-
101
- <section class="demo-panel">
102
- <div class="panel-title">
103
- <p class="eyebrow">Search</p>
104
- <h2>GET query</h2>
105
- </div>
106
- <form data-form-father action="/demo/search?source=demos" method="get" data-demo="search" novalidate>
107
- <div data-form-father-summary hidden></div>
108
-
109
- <label class="field">
110
- <span>Запрос</span>
111
- <input class="input" name="q" value="form father" data-validate="required" />
112
- </label>
113
-
114
- <label class="field">
115
- <span>Раздел</span>
116
- <select class="input" name="section">
117
- <option value="docs">Docs</option>
118
- <option value="api">API</option>
119
- <option value="examples">Examples</option>
120
- </select>
121
- </label>
122
-
123
- <button type="submit">Найти</button>
124
- </form>
125
- </section>
126
-
127
- <section class="demo-panel">
128
- <div class="panel-title">
129
- <p class="eyebrow">Multipart</p>
130
- <h2>FormData upload</h2>
131
- </div>
132
- <form data-form-father action="/demo/upload" method="post" enctype="multipart/form-data" data-demo="upload" novalidate>
133
- <div data-form-father-summary hidden></div>
134
-
135
- <label class="field">
136
- <span>Название</span>
137
- <input class="input" name="title" data-validate="required" />
138
- </label>
139
-
140
- <label class="field">
141
- <span>Файл</span>
142
- <input class="input" name="attachment" type="file" />
143
- </label>
144
-
145
- <button type="submit">Отправить</button>
146
- </form>
147
- </section>
148
- </main>
149
-
150
- <section class="demo-output">
151
- <div class="panel-title">
152
- <p class="eyebrow">Output</p>
153
- <h2>Последний ответ</h2>
154
- </div>
155
- <pre id="demo-output">Заполните любую форму.</pre>
156
- </section>
157
-
158
- <script src="../dist/FormFather.min.js"></script>
159
- <script src="./main.js"></script>
160
- </body>
161
- </html>