react-vite-themes
Version:
A test/experimental React theme system created for learning purposes. Features atomic design components, SCSS variables, and dark/light theme support. Not intended for production use.
55 lines (54 loc) • 4.17 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import React, { createContext, useContext } from 'react';
import { cn } from '../../../utils';
import { Button } from '../../atoms/Button';
import { useForm } from '../../../hooks/useForm';
// Create form context
const FormContext = createContext(null);
// Hook to use form context
export const useFormContext = () => {
const context = useContext(FormContext);
if (!context) {
throw new Error('useFormContext must be used within a Form component');
}
return context;
};
const FormProvider = ({ children, form }) => {
return (_jsx(FormContext.Provider, { value: form, children: children }));
};
// Function to enhance submit buttons with loading state
const enhanceSubmitButtons = (children, form) => {
return React.Children.map(children, (child) => {
if (!React.isValidElement(child)) {
return child;
}
// If it's a Button with type="submit", enhance it
if (child.type === Button && child.props.type === 'submit') {
return React.cloneElement(child, {
isDisabled: child.props.isDisabled || form.isSubmitting,
isLoading: child.props.isLoading || form.isSubmitting,
children: form.isSubmitting ? 'Submitting...' : child.props.children
});
}
// Recursively process children
if (child.props.children) {
return React.cloneElement(child, {
children: enhanceSubmitButtons(child.props.children, form)
});
}
return child;
});
};
export const Form = ({ children, variant = 'default', onSubmit, isDisabled = false, isLoading = false, className, submitButton = false, cancelButton = false, showActions = true, validationSchema, validateOnChange = false, validateOnBlur = true, showValidationErrors = true, ...props }) => {
// Initialize form with validation
const form = useForm({
validationSchema,
onSubmit,
validateOnChange,
validateOnBlur
});
const formClasses = cn('form', `form--${variant}`, isDisabled && 'form--disabled', isLoading && 'form--loading', className);
// Enhance children with submit button loading state
const enhancedChildren = enhanceSubmitButtons(children, form);
return (_jsx(FormProvider, { form: form, children: _jsxs("form", { className: formClasses, onSubmit: (e) => form.handleSubmit(e), noValidate: true, ...props, children: [_jsx("div", { className: "form__content", children: enhancedChildren }), showActions && (submitButton || cancelButton) && (_jsxs("div", { className: "form__actions", children: [submitButton && (_jsx(Button, { type: "submit", variant: typeof submitButton === 'object' ? submitButton.variant || 'primary' : 'primary', size: typeof submitButton === 'object' ? submitButton.size || 'md' : 'md', isFullWidth: typeof submitButton === 'object' ? submitButton.isFullWidth : false, leftIcon: typeof submitButton === 'object' ? submitButton.leftIcon : undefined, rightIcon: typeof submitButton === 'object' ? submitButton.rightIcon : undefined, isDisabled: isDisabled || form.isSubmitting || (typeof submitButton === 'object' ? submitButton.isDisabled : false), isLoading: isLoading || form.isSubmitting, children: form.isSubmitting ? 'Submitting...' : (typeof submitButton === 'object' ? submitButton.text || 'Submit' : 'Submit') })), cancelButton && (_jsx(Button, { type: "button", variant: typeof cancelButton === 'object' ? cancelButton.variant || 'secondary' : 'secondary', size: typeof cancelButton === 'object' ? cancelButton.size || 'md' : 'md', isFullWidth: typeof cancelButton === 'object' ? cancelButton.isFullWidth : false, leftIcon: typeof cancelButton === 'object' ? cancelButton.leftIcon : undefined, rightIcon: typeof cancelButton === 'object' ? cancelButton.rightIcon : undefined, isDisabled: isDisabled || (typeof cancelButton === 'object' ? cancelButton.isDisabled : false), onClick: typeof cancelButton === 'object' ? cancelButton.onClick : undefined, children: typeof cancelButton === 'object' ? cancelButton.text || 'Cancel' : 'Cancel' }))] }))] }) }));
};