zod-form-kit
Version:
UI-agnostic form generation library based on Zod schemas with extensible adapter pattern
78 lines (77 loc) • 7.56 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
// Material-UI field renderers (example implementation)
// Note: This is a conceptual example - actual Material-UI components would need to be imported
function MaterialUIStringField({ name, label, value = '', onChange, error, required, options = {}, className = '' }) {
return (_jsxs("div", { className: `mui-field string-field ${className}`, children: [_jsxs("label", { htmlFor: name, className: "mui-label", children: [label, required && _jsx("span", { className: "required", children: "*" })] }), _jsx("input", { id: name, name: name, type: getInputType(options.format), value: value, onChange: (e) => onChange(e.target.value), minLength: options.minLength, maxLength: options.maxLength, pattern: options.pattern?.source, className: `mui-input ${error ? 'error' : ''}`, required: required, readOnly: options.readonly }), error && _jsx("span", { className: "mui-error", children: error })] }));
}
function MaterialUINumberField({ name, label, value = 0, onChange, error, required, options = {}, className = '' }) {
return (_jsxs("div", { className: `mui-field number-field ${className}`, children: [_jsxs("label", { htmlFor: name, className: "mui-label", children: [label, required && _jsx("span", { className: "required", children: "*" })] }), _jsx("input", { id: name, name: name, type: "number", value: value, onChange: (e) => onChange(Number(e.target.value)), min: options.min, max: options.max, step: options.step, className: `mui-input ${error ? 'error' : ''}`, required: required, readOnly: options.readonly }), error && _jsx("span", { className: "mui-error", children: error })] }));
}
function MaterialUIBooleanField({ name, label, value = false, onChange, error, required, className = '' }) {
return (_jsxs("div", { className: `mui-field boolean-field ${className}`, children: [_jsxs("label", { className: "mui-label", children: [_jsx("input", { type: "checkbox", name: name, checked: value, onChange: (e) => onChange(e.target.checked), required: required, className: error ? 'error' : '' }), label, required && _jsx("span", { className: "required", children: "*" })] }), error && _jsx("span", { className: "mui-error", children: error })] }));
}
function MaterialUIDateField({ name, label, value = null, onChange, error, required, className = '' }) {
const dateValue = value ? value.toISOString().split('T')[0] : '';
return (_jsxs("div", { className: `mui-field date-field ${className}`, children: [_jsxs("label", { htmlFor: name, className: "mui-label", children: [label, required && _jsx("span", { className: "required", children: "*" })] }), _jsx("input", { id: name, name: name, type: "date", value: dateValue, onChange: (e) => onChange(e.target.value ? new Date(e.target.value) : null), className: `mui-input ${error ? 'error' : ''}`, required: required }), error && _jsx("span", { className: "mui-error", children: error })] }));
}
function MaterialUIArrayField({ name: _name, label, value = [], onChange, error, required, itemSchema, errors: _errors, path, options = {}, className = '' }) {
const addItem = () => {
const newValue = [...value, getDefaultValue(itemSchema)];
onChange(path, newValue);
};
const removeItem = (index) => {
const newValue = value.filter((_, i) => i !== index);
onChange(path, newValue);
};
const canAddMore = !options.maxLength || value.length < options.maxLength;
const canRemove = !options.minLength || value.length > options.minLength;
return (_jsxs("div", { className: `mui-field array-field ${className}`, children: [_jsxs("div", { className: "mui-array-header", children: [_jsxs("label", { className: "mui-label", children: [label, required && _jsx("span", { className: "required", children: "*" })] }), _jsx("button", { type: "button", onClick: addItem, disabled: !canAddMore, className: "mui-add-button", children: "Add Item" })] }), _jsx("div", { className: "mui-array-items", children: value.map((_item, index) => (_jsxs("div", { className: "mui-array-item", children: [_jsx("div", { className: "mui-item-content", children: _jsxs("span", { children: ["Item ", index + 1] }) }), canRemove && (_jsx("button", { type: "button", onClick: () => removeItem(index), className: "mui-remove-button", children: "Remove" }))] }, index))) }), error && _jsx("span", { className: "mui-error", children: error })] }));
}
function MaterialUIObjectField({ name: _name, label, value: _value = {}, onChange: _onChange, error, required, properties, errors: _errors, path: _path, className = '' }) {
return (_jsxs("div", { className: `mui-field object-field ${className}`, children: [label && (_jsxs("div", { className: "mui-object-label", children: [label, required && _jsx("span", { className: "required", children: "*" })] })), _jsx("div", { className: "mui-object-properties", children: Object.entries(properties).map(([_key, _schema]) => {
return (_jsxs("div", { className: "mui-property-field", children: [_jsx("label", { className: "mui-property-label", children: _key }), _jsxs("span", { children: ["Property: ", _key] })] }, _key));
}) }), error && _jsx("span", { className: "mui-error", children: error })] }));
}
function MaterialUIDiscriminatedUnionField({ name: _name, label, value = {}, onChange, error, required, discriminator, variants, errors: _errors, path, className = '' }) {
const currentVariant = value[discriminator];
const variantOptions = Object.keys(variants);
const handleVariantChange = (newVariant) => {
const newValue = { [discriminator]: newVariant };
onChange(path, newValue);
};
return (_jsxs("div", { className: `mui-field discriminated-union-field ${className}`, children: [label && (_jsxs("div", { className: "mui-union-label", children: [label, required && _jsx("span", { className: "required", children: "*" })] })), _jsxs("div", { className: "mui-variant-selector", children: [_jsx("label", { className: "mui-label", children: "Type" }), _jsxs("select", { value: currentVariant || '', onChange: (e) => handleVariantChange(e.target.value), className: "mui-input", children: [_jsx("option", { value: "", children: "Select type..." }), variantOptions.map((variant) => (_jsx("option", { value: variant, children: variant }, variant)))] })] }), currentVariant && variants[currentVariant] && (_jsx("div", { className: "mui-variant-fields", children: _jsxs("span", { children: ["Variant: ", currentVariant] }) })), error && _jsx("span", { className: "mui-error", children: error })] }));
}
// Helper functions
function getInputType(format) {
switch (format) {
case 'email': return 'email';
case 'url': return 'url';
default: return 'text';
}
}
function getDefaultValue(schema) {
if (schema.defaultValue !== undefined)
return schema.defaultValue;
switch (schema.type) {
case 'string': return '';
case 'number': return 0;
case 'boolean': return false;
case 'date': return new Date();
case 'array': return [];
case 'object': return {};
default: return null;
}
}
// Material-UI Adapter
export const materialUIAdapter = {
name: 'material-ui',
components: {
string: MaterialUIStringField,
number: MaterialUINumberField,
boolean: MaterialUIBooleanField,
date: MaterialUIDateField,
array: MaterialUIArrayField,
object: MaterialUIObjectField,
discriminatedUnion: MaterialUIDiscriminatedUnionField
}
};