ngx-form-stepper 0.0.3 → 0.0.5

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 (3) hide show
  1. package/index.d.ts +1 -1
  2. package/package.json +1 -1
  3. package/README.fr.md +0 -380
package/index.d.ts CHANGED
@@ -247,4 +247,4 @@ declare function minDate(min: Date, errorText: string): Validator<'minDate'>;
247
247
  declare function maxDate(max: Date, errorText: string): Validator<'maxDate'>;
248
248
 
249
249
  export { FormStepper, FormStepperComponent, Input, InputType, Select, Step, check, confirm, email, integer, max, maxDate, maxLength, min, minDate, minLength, pattern, phone, required, strongPassword };
250
- export type { MultiStepClassNames, SingleStepClassNames };
250
+ export type { MultiStepButtonText, MultiStepClassNames, RedirectItem, SelectItem, SingleStepClassNames };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ngx-form-stepper",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "peerDependencies": {
5
5
  "@angular/common": "^20.3.0",
6
6
  "@angular/core": "^20.3.0"
package/README.fr.md DELETED
@@ -1,380 +0,0 @@
1
- # ngx-form-stepper
2
-
3
- **ngx-form-stepper** est une librairie Angular pour créer des formulaires à étapes avec validations par champ, **extrêmement typée**.
4
-
5
- Elle empêche la création d’états invalides **au moment du développement**, pas à l’exécution.
6
-
7
- Destinée aux développeurs Angular qui veulent des formulaires robustes, typés et maintenables sans configuration complexe.
8
-
9
- ## Pourquoi ?
10
-
11
- - Formulaires multi-étapes simples à déclarer
12
- - Validation par champ rapide à mettre en place
13
- - Impossible d’associer un mauvais `validator` à un `Input`
14
- - Valeurs toujours cohérentes avec leur type
15
- - Clés de retour uniques obligatoires
16
- - **Aucun `as const` requis**
17
-
18
- ## Installation
19
-
20
- ```bash
21
- npm install ngx-form-stepper
22
- ```
23
-
24
- ## Exemple rapide
25
-
26
- ```typescript
27
- step1 = new Step([
28
- new Input(InputType.Text, null, 'firstName', 'First name', [required('First name is required')]),
29
- new Input(InputType.Text, null, 'lastName', 'Last name', [required('Last name is required')]),
30
- ]);
31
-
32
- step2 = new Step([
33
- new Input(InputType.Email, null, 'email', 'E-mail', [
34
- required('E-mail is required'),
35
- email('E-mail is invalid'),
36
- ]),
37
- new Input(InputType.Password, null, 'password', 'Password', [
38
- required('Password is required'),
39
- strongPassword('Password is too weak'),
40
- ]),
41
- ]);
42
-
43
- signupForm = new FormStepper([step1, step2], {
44
- title: 'Sign in',
45
- buttonText: { next: 'Next', previous: 'Previous', final: 'Sign up' },
46
- });
47
-
48
- onComplete() {
49
- console.log(signupForm.values);
50
- }
51
- ```
52
-
53
- ```html
54
- <app-form-stepper [formStepper]="signupForm" (completed)="onComplete()" />
55
- ```
56
-
57
- ## Input
58
-
59
- Chaque type d’`Input` accepte uniquement les `validators` compatibles.
60
-
61
- Exemples :
62
-
63
- - `email` ❌ interdit sur `number`
64
- - `minLength` ❌ interdit sur `checkbox`
65
- - `confirm` ❌ interdit sur `select`
66
-
67
- Et uniquement les valeurs par défaut compatibles.
68
-
69
- Exemples :
70
-
71
- - `string` ❌ interdit sur `number`
72
- - `number` ❌ interdit sur `checkbox`
73
- - `string | number` ❌ interdit sur `select`
74
-
75
- Clé de retour au format camelCase.
76
-
77
- Impossible de dupliquer un `validator`.
78
-
79
- ```typescript
80
- export class Input<
81
- T extends InputType,
82
- D extends InputDefaultValue<T>,
83
- K extends string,
84
- V extends ValidatorTuple<ValidatorsNamesOfType<T>>
85
- > {
86
- readonly defaultValue: D;
87
-
88
- constructor(
89
- readonly type: T,
90
- defaultValue: D,
91
- readonly returnKey: IsCamelCase<K> extends true ? K : never,
92
- readonly label: string,
93
- readonly validators?: HasDuplicateValidators<V> extends true ? never : V
94
- ) {
95
- this.defaultValue = (
96
- type === InputType.Checkbox ? (defaultValue === null ? false : defaultValue) : defaultValue
97
- ) as D;
98
- }
99
- }
100
-
101
- export enum InputType {
102
- Text = 'text',
103
- Password = 'password',
104
- Email = 'email',
105
- Number = 'number',
106
- Tel = 'tel',
107
- Checkbox = 'checkbox',
108
- Date = 'date',
109
- Select = 'select',
110
- }
111
- ```
112
-
113
- ## Validator
114
-
115
- Un `validator` est une fonction qu’on peut passer à un `Input`. Elle prend différents arguments comme la valeur conditionnelle ou le texte de l’erreur.
116
-
117
- ```typescript
118
- export function minLength(min: number, errorText: string): Validator<'minLength'> {
119
- const name: StandardValidatorNameFn<'minLength'> = (params: { key: string }) =>
120
- `${params.key}-minLength`;
121
-
122
- const fn = (params: { key: string }) => (control: AbstractControl<string>) => {
123
- const customName: StandardValidatorName<'minLength'> = `${params.key}-minLength`;
124
-
125
- return control.value.length < min ? { [customName]: true } : null;
126
- };
127
-
128
- return {
129
- kind: 'minLength',
130
- name,
131
- fn,
132
- errorText,
133
- };
134
- }
135
-
136
- export type ValidatorsNames =
137
- | 'required'
138
- | 'check'
139
- | 'confirm'
140
- | 'minLength'
141
- | 'maxLength'
142
- | 'min'
143
- | 'max'
144
- | 'integer'
145
- | 'pattern'
146
- | 'strongPassword'
147
- | 'email'
148
- | 'phone'
149
- | 'minDate'
150
- | 'maxDate';
151
- ```
152
-
153
- ## Select
154
-
155
- Tuple d'un ou plusieurs `SelectItem`.
156
-
157
- Le `currentIndex` doit obligatoirement être un index valide du tuple ou null.
158
-
159
- ```typescript
160
- select = new Input(
161
- InputType.Select,
162
- new Select(
163
- [
164
- { label: 'Male', value: 'male' },
165
- { label: 'Female', value: 'female' },
166
- ],
167
- 0
168
- ),
169
- 'gender',
170
- 'Gender'
171
- );
172
-
173
- export class Select<T extends SelectItemTuple, I extends number | null> {
174
- current: SelectItem | null;
175
-
176
- constructor(readonly items: T, readonly currentIndex: HasIndex<T, I> extends true ? I : never) {
177
- this.current = currentIndex === null ? null : this.items[currentIndex];
178
- }
179
- }
180
-
181
- export type SelectItem = {
182
- label: string;
183
- value: string;
184
- };
185
- ```
186
-
187
- ## Step
188
-
189
- Impossible de dupliquer la clé de retour d’un `Input`.
190
-
191
- Tuple d’un ou plusieurs `Inputs`.
192
-
193
- ```typescript
194
- export class Step<T extends InputTuple> {
195
- constructor(
196
- readonly inputs: HasDuplicateReturnKeys<T> extends true ? never : T,
197
- readonly config?: StepConfig
198
- ) {}
199
- }
200
-
201
- export type StepConfig = Readonly<{
202
- title: string;
203
- }>;
204
- ```
205
-
206
- ## FormStepper
207
-
208
- Impossible de dupliquer la clé de retour d’un `Input` entre deux `Steps`.
209
-
210
- Objet de configuration qui dépend du nombre de `Steps`.
211
-
212
- Tuple d’une ou plusieurs `Steps`.
213
-
214
- ```typescript
215
- export class FormStepper<T extends StepTuple> {
216
- readonly values: FormStepperValues<T>;
217
-
218
- constructor(
219
- readonly steps: HasDuplicateReturnKeys<T> extends true ? never : T,
220
- readonly config: T extends MultiStepTuple ? MultiStepConfig : SingleStepConfig
221
- ) {
222
- this.values = Object.fromEntries(
223
- steps.flatMap((step) => step.inputs.map((input) => [input.returnKey, input.defaultValue]))
224
- ) as FormStepperValues<T>;
225
- }
226
- }
227
-
228
- export type SingleStepConfig = Readonly<{
229
- title?: string;
230
- actionText?: RedirectItem[];
231
- buttonText: SingleStepButtonText;
232
- footerText?: RedirectItem[];
233
- classNames?: SingleStepClassNames;
234
- }>;
235
-
236
- export type MultiStepConfig = Readonly<{
237
- title?: string;
238
- actionText?: RedirectItem[];
239
- buttonText: MultiStepButtonText;
240
- footerText?: RedirectItem[];
241
- classNames?: MultiStepClassNames;
242
- }>;
243
- ```
244
-
245
- ## RedirectItem[]
246
-
247
- Un `RedirectItem[]` est un tableau de string ou d’objet `RedirectUrl`, une sorte de mini langage TS permettant de créer des textes avec lien cliquable.
248
-
249
- ```typescript
250
- actionText = ['You already have an account ?', { url: '/signin', urlText: 'Sign in' }];
251
-
252
- export type RedirectUrl = Readonly<{ url: string; urlText: string }>;
253
-
254
- export type RedirectText = string;
255
-
256
- export type RedirectItem = RedirectText | RedirectUrl;
257
- ```
258
-
259
- ## ButtonText
260
-
261
- La propriété `buttonText` du `FormStepper` dépend du nombre de `Steps`.
262
-
263
- ```typescript
264
- export type SingleStepButtonText = string;
265
-
266
- export type MultiStepButtonText = Readonly<{
267
- final: string;
268
- previous: string;
269
- next: string;
270
- }>;
271
- ```
272
-
273
- ## ClassNames
274
-
275
- Pour ajouter vos propres styles sur un `FormStepper`, je vous conseille de créer un fichier de style séparé et d'y ajouter vos class. Vous devrez ensuite importer le fichier créé dans le fichier global de styles de l'app.
276
-
277
- ```typescript
278
- classNames: SingleStepClassNames = {
279
- title: 'fs-title',
280
- input: {
281
- error: 'fs-input-error',
282
- },
283
- };
284
-
285
- form = new FormStepper([this.step], { buttonText: 'Submit', classNames: this.classNames });
286
- ```
287
-
288
- ```css
289
- /* app/fs.css */
290
-
291
- .fs-title {
292
- color: blue;
293
- }
294
-
295
- .fs-input-error {
296
- color: red;
297
- }
298
- ```
299
-
300
- ```css
301
- /* styles.css */
302
-
303
- @import 'app/fs.css';
304
- ```
305
-
306
- La propriété `classNames` du `FormStepper` dépend du nombre de `Steps`.
307
-
308
- ```typescript
309
- export type SingleStepClassNames = DeepPartial<{
310
- container: string;
311
- title: string;
312
- actionText: {
313
- container: string;
314
- text: string;
315
- url: string;
316
- };
317
- step: {
318
- container: string;
319
- title: string;
320
- form: string;
321
- inputContainer: string;
322
- };
323
- input: {
324
- container: string;
325
- label: string;
326
- required: string;
327
- input: string;
328
- errorContainer: string;
329
- error: string;
330
- };
331
- button: {
332
- container: string;
333
- button: string;
334
- disabled: string;
335
- };
336
- footerText: {
337
- container: string;
338
- text: string;
339
- url: string;
340
- };
341
- }>;
342
-
343
- export type MultiStepClassNames = DeepPartial<{
344
- container: string;
345
- title: string;
346
- actionText: {
347
- container: string;
348
- text: string;
349
- url: string;
350
- };
351
- step: {
352
- container: string;
353
- title: string;
354
- form: string;
355
- inputContainer: string;
356
- };
357
- input: {
358
- container: string;
359
- label: string;
360
- required: string;
361
- input: string;
362
- errorContainer: string;
363
- error: string;
364
- };
365
- button: {
366
- container: string;
367
- button: string;
368
- disabled: string;
369
- first: string;
370
- final: string;
371
- previous: string;
372
- next: string;
373
- };
374
- footerText: {
375
- container: string;
376
- text: string;
377
- url: string;
378
- };
379
- }>;
380
- ```