@serhiibudianskyi/wui 0.0.5 → 0.0.6

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.
@@ -1,338 +0,0 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- const uploady_1 = require("@rpldy/uploady");
13
- const upload_drop_zone_1 = require("@rpldy/upload-drop-zone");
14
- const upload_button_1 = require("@rpldy/upload-button");
15
- const upload_preview_1 = require("@rpldy/upload-preview");
16
- const react_1 = require("react");
17
- const react_toastify_1 = require("react-toastify");
18
- const filesize_1 = require("filesize");
19
- require("../styles/uploady-ext.css");
20
- const FileField = (0, react_1.forwardRef)(({ value, onChange, className, accept, isMultiple, maxFiles, maxSize }, ref) => {
21
- const height = 200;
22
- // State to store file metadata for preview
23
- const [fileMetadata, setFileMetadata] = (0, react_1.useState)(new Map());
24
- // State to store upload progress for each file
25
- const [uploadProgress, setUploadProgress] = (0, react_1.useState)(new Map());
26
- // Counter for currently uploading files
27
- const uploadingCountRef = (0, react_1.useRef)(0);
28
- // Ref to always have the latest fileMetadata
29
- const fileMetadataRef = (0, react_1.useRef)(new Map());
30
- // Ref for scroll container
31
- const scrollContainerRef = (0, react_1.useRef)(null);
32
- // Update ref whenever fileMetadata changes
33
- (0, react_1.useEffect)(() => {
34
- fileMetadataRef.current = fileMetadata;
35
- }, [fileMetadata]);
36
- // Auto-scroll to the end when new files are added
37
- (0, react_1.useEffect)(() => {
38
- if (scrollContainerRef.current && fileMetadata.size > 0) {
39
- scrollContainerRef.current.scrollTo({
40
- left: scrollContainerRef.current.scrollWidth,
41
- behavior: 'smooth'
42
- });
43
- }
44
- }, [fileMetadata.size]);
45
- // Reset in form
46
- (0, react_1.useEffect)(() => {
47
- const handleFormReset = (event) => {
48
- const form = event.target;
49
- if (form.contains(scrollContainerRef.current)) {
50
- setFileMetadata(new Map());
51
- setUploadProgress(new Map());
52
- uploadingCountRef.current = 0;
53
- // Notify parent component about the value change
54
- onChange === null || onChange === void 0 ? void 0 : onChange(isMultiple ? [] : null);
55
- }
56
- };
57
- // Add reset event listener
58
- window.addEventListener('reset', handleFormReset);
59
- return () => {
60
- // Remove event listener on unmount
61
- window.removeEventListener('reset', handleFormReset);
62
- };
63
- }, [onChange, isMultiple]);
64
- // File filter to prevent duplicates and enforce maxFiles limit
65
- const fileFilter = (0, react_1.useCallback)((file) => {
66
- const currentCount = fileMetadataRef.current.size + uploadingCountRef.current;
67
- // Check file size limit
68
- if (maxSize && file.size > maxSize) {
69
- const sizeMB = (file.size / 1024 / 1024).toFixed(2);
70
- const maxSizeMB = (maxSize / 1024 / 1024).toFixed(2);
71
- react_toastify_1.toast.error(`File '${file.name}' is too large (${sizeMB}MB). Maximum allowed size is ${maxSizeMB}MB. ${file.name} blocked`);
72
- return false;
73
- }
74
- // Check maxFiles limit
75
- if (maxFiles && currentCount >= maxFiles) {
76
- react_toastify_1.toast.error(`Max files limit reached (${maxFiles}): ${file.name} blocked`);
77
- return false;
78
- }
79
- // Check if file already exists
80
- const isDuplicate = Array.from(fileMetadataRef.current.values()).some(meta => meta.originalName === file.name && meta.size === file.size);
81
- if (isDuplicate) {
82
- react_toastify_1.toast.error(`Duplicate file blocked: ${file.name}`);
83
- return false;
84
- }
85
- return true;
86
- }, [maxFiles, maxSize]);
87
- // Upload handler component for file uploads
88
- const UploadHandler = ({ onUploaded }) => {
89
- (0, uploady_1.useItemStartListener)((item) => {
90
- // Increment uploading counter
91
- uploadingCountRef.current++;
92
- setFileMetadata(prev => {
93
- var _a, _b, _c, _d;
94
- const newMap = new Map(prev);
95
- newMap.set(item.id, {
96
- url: item.url,
97
- filename: (_a = item.file) === null || _a === void 0 ? void 0 : _a.name,
98
- originalName: (_b = item.file) === null || _b === void 0 ? void 0 : _b.name,
99
- size: (_c = item.file) === null || _c === void 0 ? void 0 : _c.size,
100
- mimetype: (_d = item.file) === null || _d === void 0 ? void 0 : _d.type
101
- });
102
- return newMap;
103
- });
104
- });
105
- // Listen to upload progress
106
- (0, uploady_1.useItemProgressListener)((item) => {
107
- if (item.completed < 100) {
108
- setUploadProgress(prev => {
109
- const newMap = new Map(prev);
110
- newMap.set(item.id, item.completed);
111
- return newMap;
112
- });
113
- }
114
- else {
115
- // Remove progress when complete
116
- setUploadProgress(prev => {
117
- const newMap = new Map(prev);
118
- newMap.delete(item.id);
119
- return newMap;
120
- });
121
- }
122
- });
123
- (0, uploady_1.useItemErrorListener)((item) => {
124
- var _a, _b;
125
- react_toastify_1.toast.error(((_b = (_a = item === null || item === void 0 ? void 0 : item.uploadResponse) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.error) || 'Upload failed');
126
- // Remove preview and progress for errored item
127
- setFileMetadata(prev => {
128
- const newMap = new Map(prev);
129
- newMap.delete(item.id);
130
- return newMap;
131
- });
132
- setUploadProgress(prev => {
133
- const newMap = new Map(prev);
134
- newMap.delete(item.id);
135
- return newMap;
136
- });
137
- // Decrement uploading counter
138
- uploadingCountRef.current = Math.max(0, uploadingCountRef.current - 1);
139
- });
140
- (0, uploady_1.useItemFinishListener)((item) => {
141
- var _a, _b;
142
- // Decrement uploading counter
143
- uploadingCountRef.current = Math.max(0, uploadingCountRef.current - 1);
144
- if (item.state === 'finished') {
145
- const responseData = (_a = item.uploadResponse) === null || _a === void 0 ? void 0 : _a.data;
146
- const url = (_b = responseData === null || responseData === void 0 ? void 0 : responseData.url) !== null && _b !== void 0 ? _b : null;
147
- // If no URL is returned, stop processing
148
- if (!url) {
149
- return;
150
- }
151
- // Store file metadata for preview
152
- setFileMetadata(prev => {
153
- const newMap = new Map(prev);
154
- if (newMap.has(item.id)) {
155
- newMap.set(item.id, Object.assign(Object.assign({}, newMap.get(item.id)), { url: responseData === null || responseData === void 0 ? void 0 : responseData.url, filename: responseData === null || responseData === void 0 ? void 0 : responseData.filename, originalName: responseData === null || responseData === void 0 ? void 0 : responseData.originalName, size: responseData === null || responseData === void 0 ? void 0 : responseData.size, mimetype: responseData === null || responseData === void 0 ? void 0 : responseData.mimetype, isUploading: false }));
156
- }
157
- return newMap;
158
- });
159
- // For multiple files, append to existing array
160
- if (isMultiple) {
161
- const currentValue = Array.isArray(value) ? value : [];
162
- onUploaded([...currentValue, url]);
163
- }
164
- else {
165
- onUploaded(url);
166
- }
167
- }
168
- });
169
- return null;
170
- };
171
- // Custom preview component for uploaded files
172
- const cleanupAllFiles = () => {
173
- // Use ref to get the latest fileMetadata
174
- const filenames = Array.from(fileMetadataRef.current.values()).map(meta => meta.filename);
175
- if (filenames.length === 0) {
176
- return;
177
- }
178
- // Try sendBeacon first (most reliable)
179
- const blob = new Blob([JSON.stringify({ filenames })], { type: 'application/json' });
180
- if (navigator.sendBeacon('/api/upload/temp/cleanup', blob)) {
181
- // Cleanup request sent via beacon
182
- return;
183
- }
184
- // Fallback to fetch with keepalive
185
- fetch('/api/upload/temp/cleanup', {
186
- method: 'POST',
187
- headers: { 'Content-Type': 'application/json' },
188
- body: JSON.stringify({ filenames }),
189
- keepalive: true // Important for page unload
190
- }).catch(error => console.error('Cleanup failed:', error));
191
- };
192
- // Cleanup all temp files on component unmount
193
- (0, react_1.useEffect)(() => {
194
- const handleBeforeUnload = (_) => {
195
- cleanupAllFiles();
196
- };
197
- window.addEventListener('beforeunload', handleBeforeUnload);
198
- return () => {
199
- window.removeEventListener('beforeunload', handleBeforeUnload);
200
- cleanupAllFiles();
201
- };
202
- }, []);
203
- // Preview container wrapper component
204
- const PreviewContainer = ({ children }) => (<div className={`d-flex border rounded position-relative align-items-center justify-content-center rounded overflow-hidden flex-shrink-0 ${isMultiple ? 'me-2' : ''}`} style={{
205
- height: `${height}px`,
206
- maxWidth: `${height}px`
207
- }}>
208
- {children}
209
- </div>);
210
- // Custom preview component
211
- const CustomPreview = (props) => {
212
- var _a;
213
- const { id, url, name, removePreview } = props;
214
- const metadata = fileMetadata.get(id);
215
- if (!metadata) {
216
- return null;
217
- }
218
- // Hook to abort upload
219
- const abortItem = (0, uploady_1.useAbortItem)();
220
- const handleCancel = () => {
221
- console.log('Cancelling upload for item id:', id);
222
- // Abort the upload
223
- abortItem(id);
224
- // Remove from preview
225
- removePreview === null || removePreview === void 0 ? void 0 : removePreview();
226
- // Remove from progress
227
- setUploadProgress(prev => {
228
- const newMap = new Map(prev);
229
- newMap.delete(id);
230
- return newMap;
231
- });
232
- // Decrement counter
233
- uploadingCountRef.current = Math.max(0, uploadingCountRef.current - 1);
234
- react_toastify_1.toast.info('Upload cancelled');
235
- };
236
- const handleRemove = () => __awaiter(void 0, void 0, void 0, function* () {
237
- // Remove from preview
238
- removePreview === null || removePreview === void 0 ? void 0 : removePreview();
239
- const metadata = fileMetadata.get(id);
240
- // Remove from metadata immediately
241
- setFileMetadata(prev => {
242
- const newMap = new Map(prev);
243
- newMap.delete(id);
244
- return newMap;
245
- });
246
- try {
247
- yield fetch(`/api/upload/temp/${metadata === null || metadata === void 0 ? void 0 : metadata.filename}`, {
248
- method: 'DELETE'
249
- });
250
- }
251
- catch (error) {
252
- console.error('Failed to delete temp file:', error);
253
- }
254
- finally {
255
- // Remove from form value
256
- const newValue = (isMultiple && Array.isArray(value)) ?
257
- // Find and remove the filename associated with this preview item
258
- // Note: We need to track the mapping between preview id and filename
259
- value.filter((url) => url !== (metadata === null || metadata === void 0 ? void 0 : metadata.url)) :
260
- null;
261
- onChange === null || onChange === void 0 ? void 0 : onChange(newValue);
262
- }
263
- });
264
- // Determine if file is an image
265
- const isImage = (_a = metadata === null || metadata === void 0 ? void 0 : metadata.mimetype) === null || _a === void 0 ? void 0 : _a.startsWith('image/');
266
- // Get upload progress for this file
267
- const progress = uploadProgress.get(id);
268
- const isUploading = progress !== undefined;
269
- return (<PreviewContainer>
270
- {/* Preview content */}
271
- {isImage ? (<img className='object-fit-cover h-100' src={url} alt={name || 'Preview'}/>) : (<div className='d-flex flex-column align-items-center justify-content-center p-3 text-center w-100' style={{
272
- minWidth: `${height / 1.35}px`
273
- }}>
274
- <svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" fill="currentColor" viewBox="0 0 16 16">
275
- <path d="M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5L14 4.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5h-2z"/>
276
- <text x="50%" y="65%" textAnchor="middle" fontSize="3" fontWeight="bold" fill="currentColor">
277
- {(() => {
278
- const filename = (metadata === null || metadata === void 0 ? void 0 : metadata.originalName) || name || '';
279
- const parts = filename.split('.');
280
- return parts.length > 1 ? parts[parts.length - 1].toUpperCase() : 'FILE';
281
- })()}
282
- </text>
283
- </svg>
284
- <div className='mt-2 small'>
285
- {(0, filesize_1.filesize)((metadata === null || metadata === void 0 ? void 0 : metadata.size) || 0, { base: 2, standard: "jedec" })}
286
- </div>
287
- </div>)}
288
-
289
- {/* Preview cancel button */}
290
- <button type='button' className='btn btn-close bg-danger p-2 btn-sm position-absolute top-0 end-0 m-2' aria-label='Close' onClick={(e) => {
291
- e.stopPropagation();
292
- if (isUploading) {
293
- handleCancel();
294
- }
295
- else {
296
- handleRemove();
297
- }
298
- }} title='Remove File'/>
299
-
300
- {/* Preview footer (title/progress) */}
301
- <div className='position-absolute bottom-0 start-0 end-0 bg-dark bg-opacity-75 text-white py-2 text-truncate small d-flex align-items-center'>
302
- {isUploading && (<div className='progress rounded-0 position-absolute w-100 left-0 bottom-0' style={{ height: '3px' }}>
303
- <div className='progress-bar progress-bar-striped progress-bar-animated bg-primary' role='progressbar' style={{ width: `${progress}%` }} aria-valuenow={progress} aria-valuemin={0} aria-valuemax={100}/>
304
- </div>)}
305
- <span className='px-3 w-100 d-inline-block text-truncate'>
306
- {isUploading ? `${Math.round(progress || 0)}% - ` : ''}
307
- {name}
308
- </span>
309
- </div>
310
- </PreviewContainer>);
311
- };
312
- return (<uploady_1.default destination={{
313
- url: '/api/upload/temp',
314
- filesParamName: 'file'
315
- }} multiple={isMultiple} accept={accept} fileFilter={fileFilter} concurrent={isMultiple} maxConcurrent={maxFiles}>
316
- <UploadHandler onUploaded={(payload) => {
317
- onChange === null || onChange === void 0 ? void 0 : onChange(payload);
318
- }}/>
319
-
320
- <upload_drop_zone_1.default className={`${className || ''}`} onDragOverClassName='drag-over'>
321
- <div ref={scrollContainerRef} className='d-flex align-items-center overflow-x-auto overflow-y-hidden'>
322
- <upload_preview_1.default rememberPreviousBatches={true} PreviewComponent={CustomPreview} fallbackUrl='data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" width="100" height="100"%3E%3Crect width="100" height="100" fill="%23ddd"/%3E%3Ctext x="50%25" y="50%25" text-anchor="middle" dy=".3em" fill="%23999"%3EImage%3C/text%3E%3C/svg%3E'/>
323
- {(!maxFiles || fileMetadata.size + uploadingCountRef.current < maxFiles) && (<upload_button_1.default className='border-0 bg-transparent p-0 cursor-pointer flex-shrink-0' extraProps={{ type: 'button' }}>
324
- <PreviewContainer>
325
- <div className='text-center p-3'>
326
- <div className='fw-bold'>Upload File</div>
327
- <div className='text-muted small mt-1'>Click or drag</div>
328
- </div>
329
- </PreviewContainer>
330
- </upload_button_1.default>)}
331
- </div>
332
- </upload_drop_zone_1.default>
333
-
334
- {/* Upload Preview for images */}
335
- </uploady_1.default>);
336
- });
337
- FileField.displayName = 'FileField';
338
- exports.default = FileField;
@@ -1,8 +0,0 @@
1
- import type { Form as FormType } from '../types/Form';
2
- interface FormProps {
3
- form: FormType;
4
- onSubmit: (data: any) => Promise<void>;
5
- showReset?: boolean;
6
- }
7
- export default function Form({ form, onSubmit, showReset }: FormProps): JSX.Element;
8
- export {};
@@ -1,100 +0,0 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.default = Form;
13
- const react_hook_form_1 = require("react-hook-form");
14
- const zod_1 = require("@hookform/resolvers/zod");
15
- const react_toastify_1 = require("react-toastify");
16
- const Field_1 = require("./Field");
17
- function Form({ form, onSubmit, showReset = false }) {
18
- // Initialize react-hook-form with zod resolver
19
- const { register, handleSubmit, reset, trigger, clearErrors, control, formState: { touchedFields, isSubmitting, isValid, isDirty } } = (0, react_hook_form_1.useForm)({
20
- resolver: (0, zod_1.zodResolver)(form.schema),
21
- mode: 'onChange',
22
- defaultValues: form.defaultValues
23
- });
24
- // Handle form submission
25
- const handleFormSubmit = (data) => __awaiter(this, void 0, void 0, function* () {
26
- try {
27
- yield onSubmit(data);
28
- reset(data);
29
- }
30
- catch (error) {
31
- react_toastify_1.toast.error('Form submission failed');
32
- }
33
- });
34
- const validateFormFields = (field) => __awaiter(this, void 0, void 0, function* () {
35
- const fieldNames = Object.values(form.sections)
36
- .flatMap(section => Object.values(section.fields))
37
- .map(f => f.name);
38
- const currentIndex = fieldNames.indexOf(field.name);
39
- // Trigger validation for all fields before the current one
40
- const beforeFields = fieldNames.slice(0, currentIndex + 1);
41
- beforeFields.forEach(name => trigger(name));
42
- // Clear errors for untouched fields after the current one
43
- const afterFields = fieldNames.slice(currentIndex + 1);
44
- const untouchedAfterFields = afterFields.filter(name => !touchedFields[name]);
45
- clearErrors(untouchedAfterFields);
46
- });
47
- const getFieldRegister = (field) => {
48
- const baseRegister = register(field.name, {
49
- valueAsNumber: field.type === 'number'
50
- });
51
- return Object.assign(Object.assign({}, baseRegister), { onFocus: (_) => __awaiter(this, void 0, void 0, function* () {
52
- // Call form field validations by a specific order
53
- yield validateFormFields(field);
54
- }), onChange: (event) => __awaiter(this, void 0, void 0, function* () {
55
- // Call the base onChange handler
56
- yield baseRegister.onChange(event);
57
- // Trigger re-validation for specified fields
58
- for (const revalidateFieldName of field.revalidates) {
59
- yield trigger(revalidateFieldName);
60
- }
61
- }) });
62
- };
63
- // Render a single field
64
- const renderField = (field) => {
65
- const fieldRegister = getFieldRegister(field);
66
- return (<Field_1.default key={field.name} field={field} register={fieldRegister} control={control}/>);
67
- };
68
- // Render section
69
- const renderSection = (section) => {
70
- return (<div className={`${section.className} mb-4`}>
71
- <div className='card'>
72
- <div className='card-header'>
73
- {section.title && <h3>{section.title}</h3>}
74
- </div>
75
- <div className='card-body'>
76
- <div className='row g-3'>
77
- {Object.values(section.fields).map(field => renderField(field))}
78
- </div>
79
- </div>
80
- </div>
81
- </div>);
82
- };
83
- // Render form buttons
84
- const renderButtons = () => {
85
- return (<div className='d-flex gap-2'>
86
- <button type='submit' className='btn btn-primary' disabled={!isDirty || !isValid || isSubmitting}>
87
- {isSubmitting ? 'Submitting...' : 'Submit'}
88
- </button>
89
- {showReset && (<button type='button' className='btn btn-secondary' onClick={() => reset()} disabled={!isDirty || isSubmitting}>
90
- Reset
91
- </button>)}
92
- </div>);
93
- };
94
- return (<form className='row' onSubmit={handleSubmit(handleFormSubmit)} noValidate>
95
- {/* Render form fields */}
96
- {form.sections.map(section => renderSection(section))}
97
- {/* Render buttons */}
98
- {renderButtons()}
99
- </form>);
100
- }
@@ -1,82 +0,0 @@
1
- import { z } from 'zod';
2
- export type FieldType = 'text' | 'email' | 'password' | 'number' | 'checkbox' | 'date' | 'datetime-local' | 'time' | 'radio' | 'select' | 'async-select' | 'creatable-select' | 'async-creatable-select' | 'textarea' | 'file';
3
- export interface Option {
4
- label: string;
5
- value: string;
6
- }
7
- export interface FieldConfig {
8
- type: FieldType;
9
- name: string;
10
- label: string;
11
- placeholder?: string;
12
- isReadOnly?: boolean;
13
- isDisabled?: boolean;
14
- isRequired?: boolean;
15
- min?: number | string;
16
- max?: number | string;
17
- revalidates?: string[];
18
- step?: number;
19
- options?: Option[];
20
- isMultiple?: boolean;
21
- maxSize?: number;
22
- accept?: string;
23
- maxFiles?: number;
24
- loadOptions?: (search: string) => Promise<Option[]>;
25
- validate?: (values: Record<string, any>, ctx: z.RefinementCtx) => void;
26
- normalize?: (value: unknown) => unknown;
27
- className?: string;
28
- attrs?: Record<string, any>;
29
- }
30
- export declare class Field<T = any> {
31
- protected readonly _config: FieldConfig;
32
- readonly schema: z.ZodSchema<T>;
33
- constructor(config: FieldConfig, schema: z.ZodSchema<T>);
34
- get type(): FieldType;
35
- get name(): string;
36
- get label(): string;
37
- get placeholder(): string;
38
- get isReadOnly(): boolean;
39
- get isDisabled(): boolean;
40
- get isRequired(): boolean;
41
- get min(): string | number | undefined;
42
- get max(): string | number | undefined;
43
- get revalidates(): string[];
44
- get step(): number | undefined;
45
- get options(): Option[];
46
- get isMultiple(): boolean;
47
- get maxSize(): number | undefined;
48
- get accept(): string | undefined;
49
- get maxFiles(): number;
50
- get loadOptions(): ((search: string) => Promise<Option[]>) | undefined;
51
- get className(): string;
52
- get attrs(): Record<string, any>;
53
- getNormalizedValue(value: unknown): T;
54
- runValidation(values: Record<string, any>, ctx: z.RefinementCtx): void;
55
- getDefaultValue(): T;
56
- }
57
- export declare class FieldFactory {
58
- private static createStringSchema;
59
- private static createEmailSchema;
60
- static text(name: string, label: string, config?: Partial<FieldConfig>): Field<string>;
61
- static email(config: Partial<FieldConfig>): Field<string>;
62
- static password(config: Partial<FieldConfig>): Field<string>;
63
- static textarea(name: string, label: string, config?: Partial<FieldConfig>): Field<string>;
64
- private static createNumberSchema;
65
- static number(name: string, label: string, config?: Partial<FieldConfig>): Field<number | undefined>;
66
- private static createCheckboxSchema;
67
- static checkbox(name: string, label: string, config?: Partial<FieldConfig>): Field<boolean>;
68
- private static createDateSchema;
69
- static date(name: string, label: string, config?: Partial<FieldConfig>): Field<Date | undefined>;
70
- private static createDateTimeLocalSchema;
71
- static datetimeLocal(name: string, label: string, config?: Partial<FieldConfig>): Field<Date | undefined>;
72
- private static createTimeSchema;
73
- static time(name: string, label: string, config?: Partial<FieldConfig>): Field<string | undefined>;
74
- static radio(name: string, label: string, options: Option[], config?: Partial<FieldConfig>): Field<string>;
75
- private static createSelectSchema;
76
- static select(name: string, label: string, options: Option[], config?: Partial<FieldConfig>): Field<Option | Option[] | null>;
77
- static asyncSelect(name: string, label: string, loadOptions: (search: string) => Promise<Option[]>, config?: Partial<FieldConfig>): Field<Option | Option[] | null>;
78
- static creatableSelect(name: string, label: string, options: Option[], config?: Partial<FieldConfig>): Field<Option | Option[] | null>;
79
- static asyncCreatableSelect(name: string, label: string, loadOptions: (search: string) => Promise<Option[]>, config?: Partial<FieldConfig>): Field<Option | Option[] | null>;
80
- private static createFileSchema;
81
- static file(name: string, label: string, config?: Partial<FieldConfig>): Field<string | string[] | null>;
82
- }