@proveanything/smartlinks-form-renderer
Version:
SmartLinks form renderer and editor — render forms from JSON schema or build them with the visual editor
157 lines (153 loc) • 5.04 kB
TypeScript
interface SchemaFormFieldCondition {
targetFieldId: string;
operator: 'equals' | 'not_equals' | 'contains' | 'not_contains' | 'greater_than' | 'less_than' | 'is_empty' | 'is_not_empty' | 'is_true' | 'is_false';
value?: any;
logicalOperator?: 'AND' | 'OR';
}
interface TableColumn {
id: string;
title: string;
type: 'string' | 'number' | 'boolean' | 'date';
required?: boolean;
width?: string;
}
interface SchemaFormField {
type: 'string' | 'number' | 'integer' | 'boolean' | 'array' | 'object' | 'table';
title?: string;
description?: string;
default?: any;
enum?: any[];
enumNames?: string[];
format?: 'email' | 'date' | 'date-time' | 'uri' | 'textarea' | 'file' | 'select' | 'radio' | 'combobox' | 'checkbox' | 'switch' | 'checkboxes' | 'multiselect';
minimum?: number;
maximum?: number;
minLength?: number;
maxLength?: number;
pattern?: string;
items?: SchemaFormField;
properties?: Record<string, SchemaFormField>;
required?: string[];
conditions?: SchemaFormFieldCondition[];
showWhen?: 'all' | 'any';
columns?: TableColumn[];
minRows?: number;
maxRows?: number;
}
interface SchemaFormUIConfig {
'ui:widget'?: 'text' | 'textarea' | 'select' | 'radio' | 'checkboxes' | 'file' | 'email' | 'date' | 'number' | 'checkbox' | 'switch' | 'combobox' | 'multiselect' | 'table';
'ui:placeholder'?: string;
'ui:help'?: string;
'ui:disabled'?: boolean;
'ui:options'?: {
label?: boolean;
rows?: number;
accept?: string;
};
'ui:order'?: string[];
}
interface SchemaFormUISchema {
[key: string]: SchemaFormUIConfig | SchemaFormUISchema;
}
interface SchemaFormConfig {
id?: string;
title: string;
description: string;
schema: {
type: 'object';
properties: Record<string, SchemaFormField>;
required?: string[];
};
uiSchema: SchemaFormUISchema;
storage: Record<string, 'private' | 'public' | 'proof' | 'personal'>;
settings: {
allowMultipleSubmissions: boolean;
requireAuthentication: boolean;
showProgressBar: boolean;
submitButtonText: string;
successMessage: string;
};
styling: {
theme: 'default' | 'modern' | 'minimal';
primaryColor: string;
backgroundColor: string;
};
fieldOrder?: string[];
createdAt?: string;
updatedAt?: string;
}
interface FormEditorValidationResult {
valid: boolean;
errors: string[];
}
interface FormEditorState {
formConfig: SchemaFormConfig;
setFormConfig: React.Dispatch<React.SetStateAction<SchemaFormConfig>>;
fieldOrder: string[];
validate: () => FormEditorValidationResult;
generateUniqueId: (baseLabel?: string) => string;
addField: () => void;
updateField: (fieldId: string, updates: Partial<SchemaFormField>) => void;
updateFieldUI: (fieldId: string, uiUpdates: any) => void;
updateFieldStorage: (fieldId: string, storage: 'private' | 'public' | 'proof' | 'personal') => void;
updateFieldId: (oldId: string, newId: string) => FormEditorValidationResult;
removeField: (fieldId: string) => void;
toggleRequired: (fieldId: string, required: boolean) => void;
reorderFields: (newFieldOrder: string[]) => void;
}
interface FormEditorStateOptions {
existingForm?: SchemaFormConfig;
isCreating: boolean;
}
interface FormEditorActionsOptions {
formConfig: SchemaFormConfig;
setFormConfig: React.Dispatch<React.SetStateAction<SchemaFormConfig>>;
}
/**
* Core form editor state management hook.
*
* Provides all field CRUD operations, validation, reordering, and ID management.
* This hook has zero UI dependencies — consuming apps handle their own toast/notification layer.
*
* @example
* ```tsx
* const editor = useFormEditorState({ isCreating: true });
*
* // Add a field
* editor.addField();
*
* // Validate before save
* const result = editor.validate();
* if (!result.valid) {
* showToast(result.errors[0]);
* }
* ```
*/
declare const useFormEditorState: ({ existingForm, isCreating, }: FormEditorStateOptions) => FormEditorState;
/**
* Form editor action utilities for import/export.
*
* Returns pure results — consuming apps handle their own toast/notification layer.
*
* @example
* ```tsx
* const actions = useFormEditorActions({ formConfig, setFormConfig });
*
* // Export schema as JSON file download
* actions.exportSchema();
*
* // Import: wire to a file input's onChange
* <input type="file" onChange={(e) => {
* const result = actions.importSchema(e);
* if (result.success) showToast('Imported!');
* else showToast(result.error, 'error');
* }} />
* ```
*/
declare const useFormEditorActions: ({ formConfig, setFormConfig }: FormEditorActionsOptions) => {
exportSchema: () => void;
importSchema: (event: React.ChangeEvent<HTMLInputElement>) => {
success: boolean;
error?: string;
};
};
export { useFormEditorActions, useFormEditorState };