@letar/forms 1.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/CHANGELOG.md ADDED
@@ -0,0 +1,83 @@
1
+ # Changelog
2
+
3
+ Все значимые изменения в библиотеке @lena/form-components документируются в этом файле.
4
+
5
+ Формат основан на [Keep a Changelog](https://keepachangelog.com/ru/1.0.0/).
6
+
7
+ ## [0.54.1] - 2026-01-05
8
+
9
+ ### Fixed
10
+
11
+ - `FieldNumber`: для опциональных полей не передаём min/max в NumberInput когда значение пустое — убрана красная рамка для пустых опциональных полей
12
+
13
+ ## [0.54.0] - 2026-01-03
14
+
15
+ ### Added
16
+
17
+ - `form-from-schema.spec.tsx` — unit тесты для `FormFromSchema` (~15 тестов)
18
+ - `form-with-api.spec.tsx` — unit тесты для `FormWithApi` (~12 тестов)
19
+ - Покрытие тестами всех критичных компонентов схемогенерации
20
+
21
+ ### Changed
22
+
23
+ - Deprecated type aliases централизованы в `form-fields/index.ts`
24
+ - Удалены локальные deprecated экспорты из 7 selection компонентов
25
+ - `field-select.tsx` использует `BaseOption<string | number>[]` вместо `SelectOption`
26
+
27
+ ### Improved
28
+
29
+ - Общее покрытие тестами: +27 unit тестов
30
+ - Обратная совместимость сохранена через централизованный реэкспорт deprecated типов
31
+
32
+ ## [0.53.0] - 2025-12-31
33
+
34
+ ### Added
35
+
36
+ - Оптимизация производительности форм
37
+ - Улучшенная мемоизация в form-fields
38
+
39
+ ## [0.51.0] - 2025-12-24
40
+
41
+ ### Added
42
+
43
+ - `useAsyncSearch` — общий хук для async поиска с debounce (Combobox, Autocomplete)
44
+ - `AsyncQueryFn`, `AsyncQueryResult` — типы для async запросов
45
+ - Persistence TTL — опция `ttl` для времени жизни черновика
46
+ - `ClearDraftButton` — компонент кнопки очистки черновика
47
+ - `savedAt` — timestamp сохранения черновика в `FormPersistenceResult`
48
+
49
+ ### Changed
50
+
51
+ - `FieldCombobox` и `FieldAutocomplete` используют `useAsyncSearch` вместо дублирования логики
52
+ - `useFormPersistence` теперь сохраняет данные в новом формате с метаданными (version, savedAt)
53
+ - Обратная совместимость со старым форматом сохранённых данных
54
+
55
+ ## [0.50.0] - 2025-12-24
56
+
57
+ ### Added
58
+
59
+ - `SelectionFieldLabel` — общий компонент для label+tooltip в selection полях
60
+ - `useGroupedOptions` — хук группировки опций (Combobox, Listbox, Select)
61
+ - `getOptionLabel` — утилита для получения label опции
62
+ - `zod-utils.ts` — централизованные функции `unwrapSchema`, `unwrapSchemaWithRequired`
63
+ - `LinkPopover` — модальное окно для ввода URL вместо `window.prompt()`
64
+ - Защита от циклических схем в `schema-traversal` (WeakSet + MAX_DEPTH=20)
65
+ - `SWITCH_STYLES` константы в `field-schedule.tsx`
66
+
67
+ ### Changed
68
+
69
+ - `extractConstraints` рефакторинг с generic handler pattern
70
+ - `FormSteps` декомпозиция на хуки: `useStepState`, `useStepPersistence`, `useStepNavigation`
71
+ - Selection поля используют общие компоненты вместо дублирования
72
+
73
+ ### Fixed
74
+
75
+ - `field-rich-text`: добавлен try/catch для JSON.parse
76
+
77
+ ### Removed
78
+
79
+ - ~500 строк дублирующегося кода
80
+
81
+ ## [0.49.0] и ранее
82
+
83
+ История изменений до v0.50.0 не документировалась.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024-2026 Letar
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,188 @@
1
+ # @letar/forms
2
+
3
+ Declarative form components for React with **40+ field types**, powered by [TanStack Form](https://tanstack.com/form) and [Chakra UI v3](https://chakra-ui.com).
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@letar/forms)](https://www.npmjs.com/package/@letar/forms)
6
+ [![license](https://img.shields.io/npm/l/@letar/forms)](./LICENSE)
7
+
8
+ ## Quick Start
9
+
10
+ ```bash
11
+ npm install @letar/forms @tanstack/react-form @chakra-ui/react zod
12
+ ```
13
+
14
+ ```tsx
15
+ import { Form } from '@letar/forms'
16
+ import { z } from 'zod/v4'
17
+
18
+ const Schema = z.object({
19
+ title: z.string().min(2).meta({ ui: { title: 'Title', placeholder: 'Enter...' } }),
20
+ rating: z.number().min(0).max(10).meta({ ui: { title: 'Rating' } }),
21
+ })
22
+
23
+ function MyForm() {
24
+ return (
25
+ <Form schema={Schema} initialValue={{ title: '', rating: 5 }} onSubmit={save}>
26
+ <Form.Field.String name="title" />
27
+ <Form.Field.Number name="rating" />
28
+ <Form.Button.Submit>Save</Form.Button.Submit>
29
+ </Form>
30
+ )
31
+ }
32
+ ```
33
+
34
+ **Or fully auto-generated from schema:**
35
+
36
+ ```tsx
37
+ <Form.FromSchema schema={Schema} initialValue={data} onSubmit={handleSubmit} submitLabel="Create" />
38
+ ```
39
+
40
+ ## Philosophy: Separate Layout from Logic
41
+
42
+ | Aspect | Where defined | How used in JSX |
43
+ | --------------- | -------------------------- | ------------------------------- |
44
+ | **Validation** | Zod schema | `schema={Schema}` |
45
+ | **UI metadata** | Zod `.meta({ ui: {...} })` | Auto-extracted from schema |
46
+ | **Structure** | TypeScript types | `initialValue={data}` |
47
+ | **Layout** | JSX | `<HStack>`, `<VStack>`, `<Box>` |
48
+
49
+ **Result:** JSX contains only layout and field names. All logic lives in the schema.
50
+
51
+ ## Features
52
+
53
+ ### 40+ Field Components
54
+
55
+ ```tsx
56
+ // Text
57
+ <Form.Field.String name="title" />
58
+ <Form.Field.Textarea name="description" />
59
+ <Form.Field.RichText name="content" />
60
+ <Form.Field.Password name="password" />
61
+
62
+ // Numbers
63
+ <Form.Field.Number name="price" />
64
+ <Form.Field.Slider name="rating" />
65
+ <Form.Field.Currency name="amount" />
66
+
67
+ // Selection
68
+ <Form.Field.Select name="category" />
69
+ <Form.Field.Combobox name="search" />
70
+ <Form.Field.RadioGroup name="type" />
71
+ <Form.Field.Checkbox name="agree" />
72
+
73
+ // Date & Time
74
+ <Form.Field.Date name="birthday" />
75
+ <Form.Field.DateRange name="period" />
76
+ <Form.Field.Time name="time" />
77
+
78
+ // Specialized
79
+ <Form.Field.Phone name="phone" />
80
+ <Form.Field.FileUpload name="avatar" />
81
+ <Form.Field.ColorPicker name="color" />
82
+ <Form.Field.PinInput name="code" />
83
+ ```
84
+
85
+ ### Conditional Rendering
86
+
87
+ ```tsx
88
+ <Form schema={Schema} initialValue={data} onSubmit={save}>
89
+ <Form.Field.Select name="type" />
90
+
91
+ <Form.When field="type" is="company">
92
+ <Form.Field.String name="companyName" />
93
+ </Form.When>
94
+
95
+ <Form.Button.Submit />
96
+ </Form>
97
+ ```
98
+
99
+ ### Multi-Step Forms
100
+
101
+ ```tsx
102
+ <Form schema={Schema} initialValue={data} onSubmit={save}>
103
+ <Form.Steps animated validateOnNext>
104
+ <Form.Steps.Step title="Personal Info">
105
+ <Form.Field.String name="name" />
106
+ <Form.Field.String name="email" />
107
+ </Form.Steps.Step>
108
+
109
+ <Form.Steps.Step title="Address">
110
+ <Form.Field.String name="city" />
111
+ <Form.Field.String name="street" />
112
+ </Form.Steps.Step>
113
+
114
+ <Form.Steps.Navigation />
115
+ </Form.Steps>
116
+ </Form>
117
+ ```
118
+
119
+ ### Groups and Arrays
120
+
121
+ ```tsx
122
+ // Nested object
123
+ <Form.Group name="address">
124
+ <Form.Field.String name="city" /> {/* → address.city */}
125
+ <Form.Field.String name="street" /> {/* → address.street */}
126
+ </Form.Group>
127
+
128
+ // Array of items
129
+ <Form.Group.List name="phones">
130
+ <Form.Field.Phone />
131
+ <Form.Group.List.Button.Add>Add Phone</Form.Group.List.Button.Add>
132
+ </Form.Group.List>
133
+ ```
134
+
135
+ ### Auto Constraints from Zod
136
+
137
+ ```tsx
138
+ const Schema = z.object({
139
+ title: z.string().min(2).max(100), // → minLength={2} maxLength={100}
140
+ email: z.string().email(), // → type="email"
141
+ rating: z.number().min(1).max(10), // → min={1} max={10}
142
+ })
143
+
144
+ // DRY: validation and UI constraints in one place
145
+ <Form.Field.String name="title" /> {/* maxLength={100} from schema */}
146
+ ```
147
+
148
+ ### Error Summary
149
+
150
+ ```tsx
151
+ <Form schema={Schema} initialValue={data} onSubmit={save}>
152
+ <Form.Field.String name="name" />
153
+ <Form.Field.String name="email" />
154
+
155
+ <Form.Errors title="Please fix:" />
156
+ <Form.Button.Submit />
157
+ </Form>
158
+ ```
159
+
160
+ ## Subpath Exports
161
+
162
+ ```tsx
163
+ // Offline support (PWA)
164
+ import { FormOfflineIndicator, useOfflineForm } from '@letar/forms/offline'
165
+
166
+ // Internationalization
167
+ import { FormI18nProvider, useFormI18n } from '@letar/forms/i18n'
168
+ ```
169
+
170
+ ## Peer Dependencies
171
+
172
+ | Package | Version | Required |
173
+ | ---------------------- | --------- | -------- |
174
+ | `react` | >= 18.0.0 | Yes |
175
+ | `@tanstack/react-form` | >= 1.0.0 | Yes |
176
+ | `@chakra-ui/react` | >= 3.0.0 | Yes |
177
+ | `framer-motion` | >= 10.0.0 | Yes |
178
+ | `zod` | >= 3.24.0 | Yes |
179
+ | `@dnd-kit/*` | >= 6.0.0 | Optional |
180
+ | `use-mask-input` | >= 3.0.0 | Optional |
181
+
182
+ ## Documentation
183
+
184
+ Full documentation and live examples: **[forms.letar.best](https://forms.letar.best)**
185
+
186
+ ## License
187
+
188
+ [MIT](./LICENSE)