@bookinglab/booking-ui-react 1.0.3 → 1.2.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/README.md CHANGED
@@ -182,6 +182,167 @@ type FormValues = Record<number, string | number | boolean>;
182
182
  - Error messages display after field is touched
183
183
  - Hidden conditional fields are excluded from validation
184
184
 
185
+ ---
186
+
187
+ ## RegistrationForm
188
+
189
+ A reusable, accessible registration form component with built-in validation, customizable fields, and programmatic control.
190
+
191
+ ### Props
192
+
193
+ | Prop | Type | Default | Description |
194
+ |------|------|---------|-------------|
195
+ | `fields` | `FieldConfig[]` | Default fields | Custom field configuration |
196
+ | `additionalFields` | `FieldConfig[]` | `undefined` | Extra fields appended after default/custom fields |
197
+ | `onSubmit` | `(values: FormValues) => void` | required | Callback fired when form is submitted with valid values |
198
+ | `onChange` | `(values: FormValues, isValid: boolean) => void` | `undefined` | Callback fired on every field change |
199
+ | `validateOnBlur` | `boolean` | `true` | Whether to validate fields on blur |
200
+ | `submitLabel` | `string` | `"Submit"` | Text for the submit button |
201
+ | `className` | `string` | `""` | Class name for the form element |
202
+ | `classNames` | `RegistrationFormClassNames` | `undefined` | Custom class names for styling |
203
+
204
+ ### Default Fields
205
+
206
+ | Field | Label | Type | Required | Validation |
207
+ |-------|-------|------|----------|------------|
208
+ | `firstName` | First name | text | Yes | required |
209
+ | `lastName` | Last name | text | Yes | required |
210
+ | `email` | Email address | email | Yes | required, email format |
211
+ | `phone` | Contact number | tel | No | phone format (if provided) |
212
+ | `address1` | Address 1 | text | Yes | required |
213
+ | `address2` | Address 2 | text | No | none |
214
+ | `city` | Town/City | text | Yes | required |
215
+ | `postcode` | Postcode | text | Yes | required, UK postcode |
216
+
217
+ ### Custom Fields
218
+
219
+ Override default fields by passing a `fields` prop:
220
+
221
+ ```tsx
222
+ import { RegistrationForm, FieldConfig } from '@bookinglab/booking-ui-react';
223
+
224
+ const customFields: FieldConfig[] = [
225
+ { name: 'username', label: 'Username', type: 'text', required: true },
226
+ { name: 'email', label: 'Email', type: 'email', required: true },
227
+ {
228
+ name: 'age',
229
+ label: 'Age',
230
+ type: 'text',
231
+ validate: (value) => {
232
+ const num = parseInt(value, 10);
233
+ if (isNaN(num) || num < 18) return 'Must be 18 or older';
234
+ return null;
235
+ }
236
+ },
237
+ ];
238
+
239
+ <RegistrationForm fields={customFields} onSubmit={handleSubmit} />
240
+ ```
241
+
242
+ ### Additional Fields
243
+
244
+ Append extra fields after the defaults using `additionalFields`:
245
+
246
+ ```tsx
247
+ import { RegistrationForm, FieldConfig } from '@bookinglab/booking-ui-react';
248
+
249
+ const extraFields: FieldConfig[] = [
250
+ { name: 'company', label: 'Company Name', type: 'text' },
251
+ {
252
+ name: 'service',
253
+ label: 'Service Type',
254
+ type: 'select',
255
+ required: true,
256
+ options: [
257
+ { id: 1, name: 'Consultation', price: 0, is_default: true },
258
+ { id: 2, name: 'Premium Support', price: 50 },
259
+ { id: 3, name: 'Enterprise', price: 200 },
260
+ ],
261
+ },
262
+ ];
263
+
264
+ <RegistrationForm additionalFields={extraFields} onSubmit={handleSubmit} />
265
+ ```
266
+
267
+ ### Select Field Options
268
+
269
+ Select fields accept an `options` array with the following structure:
270
+
271
+ ```typescript
272
+ interface FieldOption {
273
+ id: number | string; // Unique identifier (submitted as the value)
274
+ name: string; // Display text
275
+ price?: number; // Optional price modifier (displayed as "+£X")
276
+ is_default?: boolean; // Pre-select this option
277
+ }
278
+ ```
279
+
280
+ ### Ref Methods
281
+
282
+ Access imperative methods via `ref`:
283
+
284
+ ```tsx
285
+ import { useRef } from 'react';
286
+ import { RegistrationForm, RegistrationFormRef } from '@bookinglab/booking-ui-react';
287
+
288
+ function MyComponent() {
289
+ const formRef = useRef<RegistrationFormRef>(null);
290
+
291
+ return (
292
+ <>
293
+ <RegistrationForm ref={formRef} onSubmit={handleSubmit} />
294
+ <button onClick={() => formRef.current?.reset()}>Reset Form</button>
295
+ <button onClick={() => formRef.current?.setValues({ email: 'test@example.com' })}>
296
+ Pre-fill Email
297
+ </button>
298
+ </>
299
+ );
300
+ }
301
+ ```
302
+
303
+ | Method | Description |
304
+ |--------|-------------|
305
+ | `reset()` | Clear all values, errors, and touched state |
306
+ | `setValues(values)` | Programmatically set field values |
307
+
308
+ ### Styling
309
+
310
+ Override styles using the `classNames` prop:
311
+
312
+ ```tsx
313
+ <RegistrationForm
314
+ onSubmit={handleSubmit}
315
+ classNames={{
316
+ fieldWrapper: 'mb-6',
317
+ label: 'text-white font-bold',
318
+ input: 'border-2 border-gray-400 rounded-lg p-3',
319
+ inputError: 'border-red-500',
320
+ errorText: 'text-red-400 text-sm',
321
+ button: 'bg-primary text-white py-3 px-6 rounded-lg',
322
+ }}
323
+ />
324
+ ```
325
+
326
+ ### Validators
327
+
328
+ The package exports reusable validators:
329
+
330
+ ```typescript
331
+ import { required, email, phone, ukPostcode, minLen, compose } from '@bookinglab/booking-ui-react';
332
+
333
+ // Use in custom fields
334
+ const fields = [
335
+ {
336
+ name: 'password',
337
+ label: 'Password',
338
+ type: 'text',
339
+ validate: compose(required, minLen(8)),
340
+ },
341
+ ];
342
+ ```
343
+
344
+ ---
345
+
185
346
  ## Requirements
186
347
 
187
348
  - React 17.0.0 or higher
@@ -200,6 +361,13 @@ import type {
200
361
  FormErrors,
201
362
  BookingFormProps,
202
363
  BookingFormClassNames,
364
+ FieldConfig,
365
+ FieldOption,
366
+ RegistrationFormProps,
367
+ RegistrationFormRef,
368
+ RegistrationFormValues,
369
+ RegistrationFormErrors,
370
+ RegistrationFormClassNames,
203
371
  } from '@bookinglab/booking-ui-react';
204
372
  ```
205
373
 
package/dist/index.d.cts CHANGED
@@ -1,4 +1,95 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React from 'react';
3
+
4
+ /**
5
+ * Option for select fields
6
+ */
7
+ interface FieldOption {
8
+ /** Option display name */
9
+ name: string;
10
+ /** Option price (if applicable) */
11
+ price?: number;
12
+ /** Whether this is the default option */
13
+ is_default?: boolean;
14
+ /** Unique option ID */
15
+ id: number | string;
16
+ }
17
+ /**
18
+ * Configuration for a single form field
19
+ */
20
+ interface FieldConfig {
21
+ /** Unique field name (used as key in values object) */
22
+ name: string;
23
+ /** Display label for the field */
24
+ label: string;
25
+ /** Input type */
26
+ type: 'text' | 'email' | 'tel' | 'select';
27
+ /** Whether the field is required */
28
+ required?: boolean;
29
+ /** Placeholder text */
30
+ placeholder?: string;
31
+ /** Custom validation function - returns error message or null */
32
+ validate?: (value: string) => string | null;
33
+ /** Options for select fields */
34
+ options?: FieldOption[];
35
+ }
36
+ /**
37
+ * Form values keyed by field name
38
+ */
39
+ type RegistrationFormValues = Record<string, string>;
40
+ /**
41
+ * Form errors keyed by field name
42
+ */
43
+ type RegistrationFormErrors = Record<string, string>;
44
+ /**
45
+ * Custom class names for styling form elements
46
+ */
47
+ interface RegistrationFormClassNames {
48
+ /** Wrapper for each form field */
49
+ fieldWrapper?: string;
50
+ /** All labels */
51
+ label?: string;
52
+ /** All input elements */
53
+ input?: string;
54
+ /** Input elements in error state */
55
+ inputError?: string;
56
+ /** Help text below fields */
57
+ helpText?: string;
58
+ /** Error message text */
59
+ errorText?: string;
60
+ /** Submit button */
61
+ button?: string;
62
+ }
63
+ /**
64
+ * Props for the RegistrationForm component
65
+ */
66
+ interface RegistrationFormProps {
67
+ /** Custom field configuration (overrides defaults) */
68
+ fields?: FieldConfig[];
69
+ /** Additional fields to append after default fields */
70
+ additionalFields?: FieldConfig[];
71
+ /** Callback fired when form is submitted with valid values */
72
+ onSubmit: (values: RegistrationFormValues) => void;
73
+ /** Callback fired on every field change */
74
+ onChange?: (values: RegistrationFormValues, isValid: boolean) => void;
75
+ /** Whether to validate on blur (default: true) */
76
+ validateOnBlur?: boolean;
77
+ /** Text for the submit button */
78
+ submitLabel?: string;
79
+ /** Class name for the form element */
80
+ className?: string;
81
+ /** Custom class names for styling individual elements */
82
+ classNames?: RegistrationFormClassNames;
83
+ }
84
+ /**
85
+ * Imperative handle methods exposed via ref
86
+ */
87
+ interface RegistrationFormRef {
88
+ /** Reset all form values and errors */
89
+ reset: () => void;
90
+ /** Programmatically set form values */
91
+ setValues: (values: Partial<RegistrationFormValues>) => void;
92
+ }
2
93
 
3
94
  interface QuestionOption {
4
95
  id: number;
@@ -90,4 +181,65 @@ interface BookingUIConfig {
90
181
  */
91
182
  declare function BookingForm({ questions, onSubmit, submitLabel, className, labelClassName, classNames: classNamesProp, }: BookingFormProps): react_jsx_runtime.JSX.Element;
92
183
 
93
- export { BookingForm, type BookingFormClassNames, type BookingFormProps, type BookingUIConfig, type FormErrors, type FormValues, type Question, type QuestionOption, type QuestionSettings };
184
+ /**
185
+ * A reusable, accessible registration form component.
186
+ *
187
+ * Features:
188
+ * - Customizable fields via props
189
+ * - Built-in validation with blur and submit triggers
190
+ * - Full accessibility support (ARIA attributes, keyboard navigation)
191
+ * - Imperative handle for programmatic control (reset, setValues)
192
+ * - Granular styling via classNames prop
193
+ *
194
+ * @example
195
+ * ```tsx
196
+ * const formRef = useRef<RegistrationFormRef>(null);
197
+ *
198
+ * <RegistrationForm
199
+ * ref={formRef}
200
+ * onSubmit={(values) => console.log(values)}
201
+ * onChange={(values, isValid) => console.log(isValid)}
202
+ * submitLabel="Register"
203
+ * />
204
+ *
205
+ * // Programmatic control
206
+ * formRef.current?.reset();
207
+ * formRef.current?.setValues({ email: 'test@example.com' });
208
+ * ```
209
+ */
210
+ declare const RegistrationForm: React.ForwardRefExoticComponent<RegistrationFormProps & React.RefAttributes<RegistrationFormRef>>;
211
+
212
+ /**
213
+ * Validation helper functions for form fields
214
+ * Each validator returns an error message string if invalid, or null if valid
215
+ */
216
+ /**
217
+ * Validates that a value is not empty
218
+ */
219
+ declare function required(value: string): string | null;
220
+ /**
221
+ * Validates email format (RFC 5322 compliant)
222
+ */
223
+ declare function email(value: string): string | null;
224
+ /**
225
+ * Validates phone number format (international)
226
+ * Accepts formats like: +44 1234 567890, 01onal234 567890, +1-234-567-8900
227
+ */
228
+ declare function phone(value: string): string | null;
229
+ /**
230
+ * Validates UK postcode format
231
+ * Accepts formats like: SW1A 1AA, SW1A1AA, M1 1AA, B33 8TH
232
+ */
233
+ declare function ukPostcode(value: string): string | null;
234
+ /**
235
+ * Creates a minimum length validator
236
+ * @param min - Minimum number of characters required
237
+ */
238
+ declare function minLen(min: number): (value: string) => string | null;
239
+ /**
240
+ * Combines multiple validators into one
241
+ * Returns the first error encountered, or null if all pass
242
+ */
243
+ declare function compose(...validators: Array<(value: string) => string | null>): (value: string) => string | null;
244
+
245
+ export { BookingForm, type BookingFormClassNames, type BookingFormProps, type BookingUIConfig, type FieldConfig, type FieldOption, type FormErrors, type FormValues, type Question, type QuestionOption, type QuestionSettings, RegistrationForm, type RegistrationFormClassNames, type RegistrationFormErrors, type RegistrationFormProps, type RegistrationFormRef, type RegistrationFormValues, compose, email, minLen, phone, required, ukPostcode };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,95 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React from 'react';
3
+
4
+ /**
5
+ * Option for select fields
6
+ */
7
+ interface FieldOption {
8
+ /** Option display name */
9
+ name: string;
10
+ /** Option price (if applicable) */
11
+ price?: number;
12
+ /** Whether this is the default option */
13
+ is_default?: boolean;
14
+ /** Unique option ID */
15
+ id: number | string;
16
+ }
17
+ /**
18
+ * Configuration for a single form field
19
+ */
20
+ interface FieldConfig {
21
+ /** Unique field name (used as key in values object) */
22
+ name: string;
23
+ /** Display label for the field */
24
+ label: string;
25
+ /** Input type */
26
+ type: 'text' | 'email' | 'tel' | 'select';
27
+ /** Whether the field is required */
28
+ required?: boolean;
29
+ /** Placeholder text */
30
+ placeholder?: string;
31
+ /** Custom validation function - returns error message or null */
32
+ validate?: (value: string) => string | null;
33
+ /** Options for select fields */
34
+ options?: FieldOption[];
35
+ }
36
+ /**
37
+ * Form values keyed by field name
38
+ */
39
+ type RegistrationFormValues = Record<string, string>;
40
+ /**
41
+ * Form errors keyed by field name
42
+ */
43
+ type RegistrationFormErrors = Record<string, string>;
44
+ /**
45
+ * Custom class names for styling form elements
46
+ */
47
+ interface RegistrationFormClassNames {
48
+ /** Wrapper for each form field */
49
+ fieldWrapper?: string;
50
+ /** All labels */
51
+ label?: string;
52
+ /** All input elements */
53
+ input?: string;
54
+ /** Input elements in error state */
55
+ inputError?: string;
56
+ /** Help text below fields */
57
+ helpText?: string;
58
+ /** Error message text */
59
+ errorText?: string;
60
+ /** Submit button */
61
+ button?: string;
62
+ }
63
+ /**
64
+ * Props for the RegistrationForm component
65
+ */
66
+ interface RegistrationFormProps {
67
+ /** Custom field configuration (overrides defaults) */
68
+ fields?: FieldConfig[];
69
+ /** Additional fields to append after default fields */
70
+ additionalFields?: FieldConfig[];
71
+ /** Callback fired when form is submitted with valid values */
72
+ onSubmit: (values: RegistrationFormValues) => void;
73
+ /** Callback fired on every field change */
74
+ onChange?: (values: RegistrationFormValues, isValid: boolean) => void;
75
+ /** Whether to validate on blur (default: true) */
76
+ validateOnBlur?: boolean;
77
+ /** Text for the submit button */
78
+ submitLabel?: string;
79
+ /** Class name for the form element */
80
+ className?: string;
81
+ /** Custom class names for styling individual elements */
82
+ classNames?: RegistrationFormClassNames;
83
+ }
84
+ /**
85
+ * Imperative handle methods exposed via ref
86
+ */
87
+ interface RegistrationFormRef {
88
+ /** Reset all form values and errors */
89
+ reset: () => void;
90
+ /** Programmatically set form values */
91
+ setValues: (values: Partial<RegistrationFormValues>) => void;
92
+ }
2
93
 
3
94
  interface QuestionOption {
4
95
  id: number;
@@ -90,4 +181,65 @@ interface BookingUIConfig {
90
181
  */
91
182
  declare function BookingForm({ questions, onSubmit, submitLabel, className, labelClassName, classNames: classNamesProp, }: BookingFormProps): react_jsx_runtime.JSX.Element;
92
183
 
93
- export { BookingForm, type BookingFormClassNames, type BookingFormProps, type BookingUIConfig, type FormErrors, type FormValues, type Question, type QuestionOption, type QuestionSettings };
184
+ /**
185
+ * A reusable, accessible registration form component.
186
+ *
187
+ * Features:
188
+ * - Customizable fields via props
189
+ * - Built-in validation with blur and submit triggers
190
+ * - Full accessibility support (ARIA attributes, keyboard navigation)
191
+ * - Imperative handle for programmatic control (reset, setValues)
192
+ * - Granular styling via classNames prop
193
+ *
194
+ * @example
195
+ * ```tsx
196
+ * const formRef = useRef<RegistrationFormRef>(null);
197
+ *
198
+ * <RegistrationForm
199
+ * ref={formRef}
200
+ * onSubmit={(values) => console.log(values)}
201
+ * onChange={(values, isValid) => console.log(isValid)}
202
+ * submitLabel="Register"
203
+ * />
204
+ *
205
+ * // Programmatic control
206
+ * formRef.current?.reset();
207
+ * formRef.current?.setValues({ email: 'test@example.com' });
208
+ * ```
209
+ */
210
+ declare const RegistrationForm: React.ForwardRefExoticComponent<RegistrationFormProps & React.RefAttributes<RegistrationFormRef>>;
211
+
212
+ /**
213
+ * Validation helper functions for form fields
214
+ * Each validator returns an error message string if invalid, or null if valid
215
+ */
216
+ /**
217
+ * Validates that a value is not empty
218
+ */
219
+ declare function required(value: string): string | null;
220
+ /**
221
+ * Validates email format (RFC 5322 compliant)
222
+ */
223
+ declare function email(value: string): string | null;
224
+ /**
225
+ * Validates phone number format (international)
226
+ * Accepts formats like: +44 1234 567890, 01onal234 567890, +1-234-567-8900
227
+ */
228
+ declare function phone(value: string): string | null;
229
+ /**
230
+ * Validates UK postcode format
231
+ * Accepts formats like: SW1A 1AA, SW1A1AA, M1 1AA, B33 8TH
232
+ */
233
+ declare function ukPostcode(value: string): string | null;
234
+ /**
235
+ * Creates a minimum length validator
236
+ * @param min - Minimum number of characters required
237
+ */
238
+ declare function minLen(min: number): (value: string) => string | null;
239
+ /**
240
+ * Combines multiple validators into one
241
+ * Returns the first error encountered, or null if all pass
242
+ */
243
+ declare function compose(...validators: Array<(value: string) => string | null>): (value: string) => string | null;
244
+
245
+ export { BookingForm, type BookingFormClassNames, type BookingFormProps, type BookingUIConfig, type FieldConfig, type FieldOption, type FormErrors, type FormValues, type Question, type QuestionOption, type QuestionSettings, RegistrationForm, type RegistrationFormClassNames, type RegistrationFormErrors, type RegistrationFormProps, type RegistrationFormRef, type RegistrationFormValues, compose, email, minLen, phone, required, ukPostcode };