Files
metabuilder/hooks/FormControl.tsx
johndoe6345789 78a54228df feat(hooks): Create centralized hooks npm package
- Added @metabuilder/hooks workspace package at root
- Consolidated 30 React hooks from across codebase into single module
- Implemented conditional exports for tree-shaking support
- Added comprehensive package.json with build/lint/typecheck scripts
- Created README.md documenting hook categories and usage patterns
- Updated root package.json workspaces array to include hooks
- Supports multi-version peer dependencies (React 18/19, Redux 8/9)

Usage:
  import { useDashboardLogic } from '@metabuilder/hooks'
  import { useLoginLogic } from '@metabuilder/hooks/useLoginLogic'

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-01-23 19:17:17 +00:00

115 lines
2.9 KiB
TypeScript

'use client'
import React, { forwardRef, createContext, useContext, useMemo, useId } from 'react'
/**
* FormControl context for sharing state with child components
*/
interface FormControlContextValue {
id?: string
required?: boolean
disabled?: boolean
error?: boolean
filled?: boolean
focused?: boolean
}
const FormControlContext = createContext<FormControlContextValue>({})
/**
* Hook to access FormControl context from child components
*/
export const useFormControl = () => useContext(FormControlContext)
/**
* Props for FormControl component
*/
export interface FormControlProps extends React.HTMLAttributes<HTMLDivElement> {
children?: React.ReactNode
/** Whether the field is required */
required?: boolean
/** Whether the field is disabled */
disabled?: boolean
/** Whether the field has an error */
error?: boolean
/** Full width form control */
fullWidth?: boolean
/** Margin size */
margin?: 'none' | 'dense' | 'normal'
/** Size of the form control */
size?: 'small' | 'medium'
/** Visual variant */
variant?: 'standard' | 'outlined' | 'filled'
/** Whether the input has value (filled state) */
filled?: boolean
/** Whether the input is focused */
focused?: boolean
/** MUI sx prop for styling compatibility */
sx?: Record<string, unknown>
}
/**
* FormControl - Provides context to form input components for consistent state
*
* @example
* ```tsx
* <FormControl required error={hasError}>
* <FormLabel>Email</FormLabel>
* <Input placeholder="Enter email" />
* <FormHelperText>Required field</FormHelperText>
* </FormControl>
* ```
*/
export const FormControl = forwardRef<HTMLDivElement, FormControlProps>(
(
{
children,
required = false,
disabled = false,
error = false,
fullWidth = false,
margin = 'none',
size = 'medium',
variant = 'outlined',
filled = false,
focused = false,
className = '',
sx,
...props
},
ref
) => {
const id = useId()
const contextValue = useMemo(
() => ({ id, required, disabled, error, filled, focused }),
[id, required, disabled, error, filled, focused]
)
return (
<FormControlContext.Provider value={contextValue}>
<div
ref={ref}
className={`
form-control
form-control--${variant}
form-control--${size}
form-control--margin-${margin}
${fullWidth ? 'form-control--full-width' : ''}
${required ? 'form-control--required' : ''}
${disabled ? 'form-control--disabled' : ''}
${error ? 'form-control--error' : ''}
${focused ? 'form-control--focused' : ''}
${className}
`.trim().replace(/\s+/g, ' ')}
{...props}
>
{children}
</div>
</FormControlContext.Provider>
)
}
)
FormControl.displayName = 'FormControl'