@anri1214/dynamic-forms-mui 0.1.7

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.
@@ -0,0 +1,554 @@
1
+ import { Component } from 'react';
2
+ import { ComponentType } from 'react';
3
+ import { JSX } from 'react/jsx-runtime';
4
+ import { JSXElementConstructor } from 'react';
5
+ import { ReactElement } from 'react';
6
+ import { ReactNode } from 'react';
7
+ import { ReactPortal } from 'react';
8
+ import { SxProps } from '@mui/material';
9
+ import { TextFieldProps } from '@mui/material/TextField';
10
+ import { Theme } from '@mui/material';
11
+ import { z } from 'zod';
12
+ import { ZodType } from 'zod';
13
+
14
+ export declare interface AndCondition {
15
+ and: Condition[];
16
+ }
17
+
18
+ export declare interface ApiClient {
19
+ get<T>(url: string, config?: RequestConfig): Promise<T>;
20
+ }
21
+
22
+ /**
23
+ * Checks if all dependencies have valid values
24
+ */
25
+ export declare function areDependenciesFilled(dependencies: string[], values: Record<string, unknown>): boolean;
26
+
27
+ export declare interface AsyncValidationConfig {
28
+ apiUrl: string;
29
+ queryParams?: QueryParam[];
30
+ debounce?: number;
31
+ message: string;
32
+ }
33
+
34
+ export declare interface AutocompleteFieldConfig extends BaseFieldConfig {
35
+ type: 'autocomplete';
36
+ options?: Option_2[];
37
+ optionsSource?: OptionsSource;
38
+ initialOptions?: Option_2[];
39
+ }
40
+
41
+ export declare interface BaseFieldConfig {
42
+ type: FieldType;
43
+ label: string;
44
+ placeholder?: string;
45
+ helperText?: string;
46
+ defaultValue?: unknown;
47
+ disabled?: boolean;
48
+ showIf?: Condition;
49
+ validation?: ValidationRules;
50
+ }
51
+
52
+ /**
53
+ * Builds URL for options API call
54
+ */
55
+ export declare function buildOptionsUrl(source: OptionsSource, values: Record<string, unknown>, inputValue?: string): string;
56
+
57
+ /**
58
+ * Builds a Zod schema from FormSchema
59
+ * Note: requiredIf and matchField are handled via refine
60
+ */
61
+ export declare function buildZodSchema(schema: FormSchema): z.ZodObject<Record<string, ZodType>>;
62
+
63
+ export declare interface CheckboxFieldConfig extends BaseFieldConfig {
64
+ type: 'checkbox' | 'switch';
65
+ defaultValue?: boolean;
66
+ }
67
+
68
+ export declare type ComponentSize = 'small' | 'medium';
69
+
70
+ export declare type Condition = SimpleCondition | AndCondition | OrCondition;
71
+
72
+ export declare type ConditionOperator = 'equals' | 'notEquals' | 'in' | 'notIn' | 'isEmpty' | 'isNotEmpty' | 'gt' | 'gte' | 'lt' | 'lte';
73
+
74
+ export declare interface DateFieldConfig extends BaseFieldConfig {
75
+ type: 'date' | 'dateRange';
76
+ includeTime?: boolean;
77
+ minDate?: string;
78
+ maxDate?: string;
79
+ format?: string;
80
+ }
81
+
82
+ export declare interface DFAutocompleteProps {
83
+ multiple?: boolean;
84
+ options: Option_2[];
85
+ value?: Option_2 | Option_2[] | null;
86
+ onChange?: (event: unknown, newValue: unknown) => void;
87
+ isOptionEqualToValue?: (option: Option_2, value: Option_2) => boolean;
88
+ label?: string;
89
+ required?: boolean;
90
+ placeholder?: string;
91
+ error?: boolean;
92
+ helperText?: string;
93
+ disabled?: boolean;
94
+ loading?: boolean;
95
+ name?: string;
96
+ onBlur?: () => void;
97
+ size?: ComponentSize;
98
+ ref?: React.Ref<unknown>;
99
+ inputValue?: string;
100
+ onInputChange?: (event: unknown, value: string, reason: string) => void;
101
+ filterOptions?: (options: Option_2[], state: unknown) => Option_2[];
102
+ }
103
+
104
+ export declare interface DFCheckboxProps {
105
+ name?: string;
106
+ label: string;
107
+ required?: boolean;
108
+ checked?: boolean;
109
+ onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
110
+ disabled?: boolean;
111
+ error?: boolean;
112
+ helperText?: string;
113
+ size?: ComponentSize;
114
+ onBlur?: () => void;
115
+ ref?: React.Ref<unknown>;
116
+ }
117
+
118
+ export declare interface DFDatePickerProps {
119
+ value?: Date | null;
120
+ onChange?: (date: Date | null) => void;
121
+ label?: string;
122
+ disabled?: boolean;
123
+ error?: boolean;
124
+ helperText?: string;
125
+ minDate?: Date;
126
+ maxDate?: Date;
127
+ required?: boolean;
128
+ includeTime?: boolean;
129
+ format?: string;
130
+ size?: ComponentSize;
131
+ ref?: React.Ref<HTMLInputElement>;
132
+ }
133
+
134
+ export declare interface DFDateRange {
135
+ start: Date | null;
136
+ end: Date | null;
137
+ }
138
+
139
+ export declare interface DFDateRangePickerProps {
140
+ value?: DFDateRange;
141
+ onChange?: (range: DFDateRange) => void;
142
+ label?: string;
143
+ disabled?: boolean;
144
+ error?: boolean;
145
+ helperText?: string;
146
+ minDate?: Date;
147
+ maxDate?: Date;
148
+ required?: boolean;
149
+ includeTime?: boolean;
150
+ format?: string;
151
+ size?: ComponentSize;
152
+ }
153
+
154
+ export declare interface DFFileUploadProps {
155
+ value?: File | File[] | null;
156
+ onChange?: (files: File | File[] | null) => void;
157
+ onBlur?: () => void;
158
+ multiple?: boolean;
159
+ accept?: string;
160
+ label?: string;
161
+ disabled?: boolean;
162
+ error?: boolean;
163
+ helperText?: string;
164
+ required?: boolean;
165
+ ref?: React.Ref<HTMLInputElement>;
166
+ }
167
+
168
+ export declare interface DFNumberFieldProps {
169
+ name?: string;
170
+ value?: number | null;
171
+ onValueChange?: (value: number | null) => void;
172
+ onBlur?: () => void;
173
+ label?: React.ReactNode;
174
+ required?: boolean;
175
+ placeholder?: string;
176
+ helperText?: React.ReactNode;
177
+ error?: boolean;
178
+ disabled?: boolean;
179
+ min?: number;
180
+ max?: number;
181
+ step?: number;
182
+ size?: ComponentSize;
183
+ ref?: React.Ref<HTMLInputElement>;
184
+ }
185
+
186
+ export declare interface DFRadioGroupProps {
187
+ name?: string;
188
+ label?: string;
189
+ required?: boolean;
190
+ options: {
191
+ label: string;
192
+ value: string;
193
+ }[];
194
+ row?: boolean;
195
+ error?: boolean;
196
+ helperText?: string;
197
+ disabled?: boolean;
198
+ size?: ComponentSize;
199
+ value?: string;
200
+ onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
201
+ onBlur?: () => void;
202
+ ref?: React.Ref<unknown>;
203
+ }
204
+
205
+ export declare interface DFSelectProps {
206
+ name?: string;
207
+ value?: string | number | readonly string[];
208
+ onChange?: (event: {
209
+ target: {
210
+ value: string;
211
+ };
212
+ }) => void;
213
+ onBlur?: () => void;
214
+ label?: React.ReactNode;
215
+ options: Option_2[];
216
+ size?: ComponentSize;
217
+ ref?: React.Ref<unknown>;
218
+ }
219
+
220
+ export declare interface DFSwitchProps {
221
+ name?: string;
222
+ label: string;
223
+ required?: boolean;
224
+ checked?: boolean;
225
+ onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
226
+ disabled?: boolean;
227
+ error?: boolean;
228
+ helperText?: string;
229
+ size?: ComponentSize;
230
+ onBlur?: () => void;
231
+ ref?: React.Ref<unknown>;
232
+ }
233
+
234
+ export declare type DFTextFieldProps = TextFieldProps;
235
+
236
+ export declare function DynamicForm<T extends Record<string, unknown>>({ schema, onSubmit, mode, defaultValues, apiClient: apiClientOverride, size: sizeOverride, sectionSlotProps, children, }: DynamicFormProps<T>): JSX.Element;
237
+
238
+ declare interface DynamicFormProps<T extends Record<string, unknown>> {
239
+ schema: FormSchema;
240
+ onSubmit: (data: T, labelMap: LabelMap) => void | Promise<void>;
241
+ mode?: FormMode;
242
+ defaultValues?: Partial<T>;
243
+ apiClient?: ApiClient;
244
+ size?: ComponentSize;
245
+ sectionSlotProps?: SectionSlotProps;
246
+ children?: React.ReactNode | ((formState: FormState) => React.ReactNode);
247
+ }
248
+
249
+ export declare interface DynamicFormsContextValue {
250
+ apiClient: ApiClient;
251
+ components: UIComponents;
252
+ notifications: NotificationCallbacks;
253
+ size?: ComponentSize;
254
+ sectionSlotProps?: SectionSlotProps;
255
+ }
256
+
257
+ export declare function DynamicFormsProvider({ apiClient, components, size, sectionSlotProps, onError, children, }: DynamicFormsProviderProps): JSX.Element;
258
+
259
+ declare interface DynamicFormsProviderProps {
260
+ apiClient: ApiClient;
261
+ components?: Partial<UIComponents>;
262
+ size?: ComponentSize;
263
+ sectionSlotProps?: SectionSlotProps;
264
+ onError?: (message: string) => void;
265
+ children: React.ReactNode;
266
+ }
267
+
268
+ /**
269
+ * Evaluates a condition against form values
270
+ */
271
+ export declare function evaluateCondition(condition: Condition, values: Record<string, unknown>): boolean;
272
+
273
+ /**
274
+ * Extracts default values from form schema
275
+ * Sets type-appropriate defaults to avoid "undefined" validation errors
276
+ */
277
+ export declare function extractDefaultValues(schema: FormSchema): Record<string, unknown>;
278
+
279
+ /**
280
+ * Extracts field names that options depend on
281
+ */
282
+ export declare function extractOptionsDependencies(source: OptionsSource): string[];
283
+
284
+ declare type FieldComponent = ComponentType<FieldComponentProps>;
285
+
286
+ declare interface FieldComponentProps {
287
+ name: string;
288
+ config: FieldConfig;
289
+ disabled?: boolean;
290
+ }
291
+
292
+ export declare type FieldConfig = TextFieldConfig | NumberFieldConfig | SelectFieldConfig | AutocompleteFieldConfig | CheckboxFieldConfig | RadioFieldConfig | DateFieldConfig | FileFieldConfig;
293
+
294
+ export declare type FieldType = 'text' | 'password' | 'email' | 'number' | 'textarea' | 'select' | 'multiselect' | 'autocomplete' | 'checkbox' | 'radio' | 'switch' | 'date' | 'dateRange' | 'file';
295
+
296
+ export declare interface FileFieldConfig extends BaseFieldConfig {
297
+ type: 'file';
298
+ accept?: string;
299
+ maxSize?: number;
300
+ multiple?: boolean;
301
+ }
302
+
303
+ /**
304
+ * Formats file size in bytes to human-readable format
305
+ *
306
+ * @param bytes - File size in bytes
307
+ * @returns Formatted string with appropriate unit (KB, MB, GB)
308
+ *
309
+ * @example
310
+ * formatFileSize(1024) // "1.00 KB"
311
+ * formatFileSize(1536) // "1.50 KB"
312
+ * formatFileSize(1048576) // "1.00 MB"
313
+ * formatFileSize(5242880) // "5.00 MB"
314
+ */
315
+ export declare function formatFileSize(bytes: number): string;
316
+
317
+ export declare class FormErrorBoundary extends Component<Props, State> {
318
+ constructor(props: Props);
319
+ static getDerivedStateFromError(error: Error): State;
320
+ componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void;
321
+ handleReset: () => void;
322
+ render(): string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | ReactPortal | ReactElement<unknown, string | JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | JSX.Element | null | undefined;
323
+ }
324
+
325
+ /**
326
+ * Defines a single row in the form layout grid.
327
+ * Each row can contain one or more sections rendered side-by-side.
328
+ */
329
+ export declare interface FormLayoutRow {
330
+ /** Section IDs to place in this row */
331
+ sections: string[];
332
+ /** Number of grid columns (defaults to sections.length) */
333
+ columns?: number;
334
+ }
335
+
336
+ export declare type FormMode = 'edit' | 'disabled';
337
+
338
+ export declare interface FormSchema {
339
+ sections: Section[];
340
+ fields: Record<string, FieldConfig>;
341
+ /**
342
+ * Optional layout configuration for arranging sections in a grid.
343
+ * Each entry defines a row with one or more sections side-by-side.
344
+ * If omitted, sections render sequentially (backward compatible).
345
+ *
346
+ * @example
347
+ * layout: [
348
+ * { sections: ['credentials', 'personalInfo'] }, // 2 columns
349
+ * { sections: ['preferences'] }, // full width
350
+ * ]
351
+ */
352
+ layout?: FormLayoutRow[];
353
+ }
354
+
355
+ export declare interface FormState {
356
+ isValid: boolean;
357
+ isSubmitting: boolean;
358
+ }
359
+
360
+ export declare function isEmpty(value: unknown): boolean;
361
+
362
+ export declare type LabelMap = Record<string, Record<string | number, string>>;
363
+
364
+ export declare interface NotificationCallbacks {
365
+ onError?: (message: string) => void;
366
+ }
367
+
368
+ export declare interface NumberFieldConfig extends BaseFieldConfig {
369
+ type: 'number';
370
+ min?: number;
371
+ max?: number;
372
+ step?: number;
373
+ }
374
+
375
+ declare interface Option_2 {
376
+ value: string | number;
377
+ label: string;
378
+ disabled?: boolean;
379
+ }
380
+ export { Option_2 as Option }
381
+
382
+ export declare interface OptionsSource {
383
+ apiUrl: string;
384
+ queryParams?: QueryParam[];
385
+ valueKey?: string;
386
+ labelKey?: string;
387
+ }
388
+
389
+ export declare interface OrCondition {
390
+ or: Condition[];
391
+ }
392
+
393
+ declare interface Props {
394
+ children: ReactNode;
395
+ fallback?: ReactNode;
396
+ onError?: (error: Error, errorInfo: React.ErrorInfo) => void;
397
+ }
398
+
399
+ export declare interface QueryParam {
400
+ key: string;
401
+ dependsOn?: string;
402
+ value?: string;
403
+ dependsOnInput?: boolean;
404
+ }
405
+
406
+ export declare interface RadioFieldConfig extends BaseFieldConfig {
407
+ type: 'radio';
408
+ options?: Option_2[];
409
+ optionsSource?: OptionsSource;
410
+ direction?: 'row' | 'column';
411
+ }
412
+
413
+ export declare function registerFieldComponent(type: FieldType, component: FieldComponent): void;
414
+
415
+ export declare interface RequestConfig {
416
+ params?: Record<string, unknown>;
417
+ signal?: AbortSignal;
418
+ }
419
+
420
+ export declare interface Section {
421
+ id: string;
422
+ title?: string;
423
+ description?: string;
424
+ fields: string[];
425
+ }
426
+
427
+ export declare interface SectionSlotProps {
428
+ root?: {
429
+ sx?: SxProps<Theme>;
430
+ };
431
+ title?: {
432
+ sx?: SxProps<Theme>;
433
+ };
434
+ description?: {
435
+ sx?: SxProps<Theme>;
436
+ };
437
+ content?: {
438
+ sx?: SxProps<Theme>;
439
+ };
440
+ }
441
+
442
+ export declare interface SelectFieldConfig extends BaseFieldConfig {
443
+ type: 'select' | 'multiselect';
444
+ options?: Option_2[];
445
+ optionsSource?: OptionsSource;
446
+ initialOptions?: Option_2[];
447
+ }
448
+
449
+ export declare interface SimpleCondition {
450
+ field: string;
451
+ operator: ConditionOperator;
452
+ value?: unknown;
453
+ }
454
+
455
+ declare interface State {
456
+ hasError: boolean;
457
+ error: Error | null;
458
+ }
459
+
460
+ export declare interface TextFieldConfig extends BaseFieldConfig {
461
+ type: 'text' | 'password' | 'email' | 'textarea';
462
+ autoComplete?: string;
463
+ rows?: number;
464
+ }
465
+
466
+ export declare interface UIComponents {
467
+ TextField: ComponentType<DFTextFieldProps>;
468
+ NumberField: ComponentType<DFNumberFieldProps>;
469
+ Select: ComponentType<DFSelectProps>;
470
+ Autocomplete: ComponentType<DFAutocompleteProps>;
471
+ Checkbox: ComponentType<DFCheckboxProps>;
472
+ Switch: ComponentType<DFSwitchProps>;
473
+ RadioGroup: ComponentType<DFRadioGroupProps>;
474
+ DatePicker: ComponentType<DFDatePickerProps>;
475
+ DateRangePicker: ComponentType<DFDateRangePickerProps>;
476
+ FileUpload: ComponentType<DFFileUploadProps>;
477
+ }
478
+
479
+ export declare function useAsyncValidation(fieldName: string, config: AsyncValidationConfig | undefined): UseAsyncValidationResult;
480
+
481
+ declare interface UseAsyncValidationResult {
482
+ validateDebounced: (value: unknown) => Promise<string | true>;
483
+ validateImmediate: (value: unknown) => Promise<string | true>;
484
+ }
485
+
486
+ export declare function useDynamicFormsContext(): DynamicFormsContextValue;
487
+
488
+ /**
489
+ * Returns a Set of visible field names based on showIf conditions
490
+ */
491
+ export declare function useFieldVisibility(schema: FormSchema): Set<string>;
492
+
493
+ export declare function useOptionsSource(source: OptionsSource | undefined, staticOptions: Option_2[] | undefined, initialOptions?: Option_2[]): UseOptionsSourceResult;
494
+
495
+ declare interface UseOptionsSourceResult {
496
+ options: Option_2[];
497
+ isLoading: boolean;
498
+ error: Error | null;
499
+ inputValue?: string;
500
+ onInputChange?: (event: unknown, value: string, reason: string) => void;
501
+ }
502
+
503
+ export declare interface ValidationMessages {
504
+ required?: string;
505
+ minLength?: string;
506
+ maxLength?: string;
507
+ pattern?: string;
508
+ email?: string;
509
+ url?: string;
510
+ hasUppercase?: string;
511
+ hasLowercase?: string;
512
+ hasNumber?: string;
513
+ hasSpecialChar?: string;
514
+ includes?: string;
515
+ min?: string;
516
+ max?: string;
517
+ invalidDate?: string;
518
+ minDate?: string;
519
+ maxDate?: string;
520
+ invalidRange?: string;
521
+ maxSize?: string;
522
+ fileType?: string;
523
+ minFiles?: string;
524
+ maxFiles?: string;
525
+ matchField?: string;
526
+ asyncValidation?: string;
527
+ }
528
+
529
+ export declare interface ValidationRules {
530
+ required?: boolean;
531
+ requiredIf?: Condition;
532
+ minLength?: number;
533
+ maxLength?: number;
534
+ pattern?: string;
535
+ email?: boolean;
536
+ url?: boolean;
537
+ hasUppercase?: boolean | number;
538
+ hasLowercase?: boolean | number;
539
+ hasNumber?: boolean | number;
540
+ hasSpecialChar?: boolean | number;
541
+ includes?: string;
542
+ min?: number;
543
+ max?: number;
544
+ minDate?: Date;
545
+ maxDate?: Date;
546
+ maxSize?: number;
547
+ minFiles?: number;
548
+ maxFiles?: number;
549
+ matchField?: string;
550
+ asyncValidation?: AsyncValidationConfig;
551
+ messages?: ValidationMessages;
552
+ }
553
+
554
+ export { }