@a13y/react 0.1.0
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.
- package/LICENSE +21 -0
- package/README.md +241 -0
- package/dist/components/index.d.ts +374 -0
- package/dist/components/index.js +849 -0
- package/dist/components/index.js.map +1 -0
- package/dist/hooks/index.d.ts +725 -0
- package/dist/hooks/index.js +648 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +1875 -0
- package/dist/index.js.map +1 -0
- package/dist/patterns/index.d.ts +539 -0
- package/dist/patterns/index.js +1170 -0
- package/dist/patterns/index.js.map +1 -0
- package/dist/use-accessible-button-B0syf-Az.d.ts +83 -0
- package/package.json +101 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/hooks/use-accessible-button.ts","../../src/hooks/use-focus-trap.ts","../../src/hooks/use-accessible-dialog.ts","../../src/hooks/use-keyboard-navigation.ts","../../src/hooks/use-accessible-form.ts","../../src/hooks/use-form-field.ts"],"names":["useRef","useEffect","useCallback","useState","isValid","useId","announce"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @a13y/react - useAccessibleButton\n * Type-safe button hook with keyboard support\n */\n\nimport type { AriaRole } from 'react';\nimport { useCallback, useEffect, useRef } from 'react';\n\n/**\n * Button press event (mouse or keyboard)\n */\nexport interface PressEvent {\n type: 'mouse' | 'keyboard';\n key?: string;\n}\n\n/**\n * Props for useAccessibleButton\n */\nexport interface UseAccessibleButtonProps {\n /**\n * Accessible label for the button\n * Required if button content is not text (e.g., icon-only)\n */\n label?: string;\n\n /**\n * Press handler - called on click or Enter/Space\n */\n onPress: (event: PressEvent) => void;\n\n /**\n * Whether the button is disabled\n */\n isDisabled?: boolean;\n\n /**\n * ARIA role override\n * @default 'button'\n */\n role?: Extract<AriaRole, 'button' | 'link'>;\n\n /**\n * Element type - only 'button' or 'a' allowed\n * @default 'button'\n */\n elementType?: 'button' | 'a';\n}\n\n/**\n * Button props returned by the hook\n */\nexport interface AccessibleButtonProps {\n role: AriaRole;\n tabIndex: number;\n 'aria-label'?: string;\n 'aria-disabled'?: boolean;\n disabled?: boolean;\n onPointerDown: (event: React.PointerEvent) => void;\n onKeyDown: (event: React.KeyboardEvent) => void;\n}\n\n/**\n * Return type\n */\nexport interface UseAccessibleButtonReturn {\n buttonProps: AccessibleButtonProps;\n isPressed: boolean;\n}\n\n/**\n * Hook for creating accessible buttons\n *\n * Features:\n * - Keyboard support (Enter, Space)\n * - Disabled state handling\n * - Automatic ARIA attributes\n * - Development-time validation\n *\n * @example\n * ```tsx\n * const { buttonProps } = useAccessibleButton({\n * label: 'Delete item',\n * onPress: () => console.log('Pressed!'),\n * });\n *\n * return <button {...buttonProps}>🗑️</button>;\n * ```\n */\nexport const useAccessibleButton = (props: UseAccessibleButtonProps): UseAccessibleButtonReturn => {\n const { label, onPress, isDisabled = false, role = 'button', elementType = 'button' } = props;\n\n const buttonRef = useRef<HTMLElement | null>(null);\n const isPressedRef = useRef(false);\n\n // Development-time validation\n useEffect(() => {\n if (typeof __DEV__ !== 'undefined' && __DEV__) {\n import('@a13y/devtools/runtime/invariants').then(\n ({ assertHasAccessibleName, assertKeyboardAccessible }) => {\n if (buttonRef.current) {\n // Validate accessible name\n assertHasAccessibleName(buttonRef.current, 'useAccessibleButton');\n\n // Validate keyboard accessibility\n assertKeyboardAccessible(buttonRef.current, 'useAccessibleButton');\n }\n }\n );\n }\n }, []);\n\n const handlePress = useCallback(\n (event: PressEvent) => {\n if (isDisabled) {\n return;\n }\n onPress(event);\n },\n [onPress, isDisabled]\n );\n\n const handlePointerDown = useCallback(\n (event: React.PointerEvent) => {\n if (isDisabled) {\n event.preventDefault();\n return;\n }\n\n isPressedRef.current = true;\n handlePress({ type: 'mouse' });\n },\n [handlePress, isDisabled]\n );\n\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent) => {\n if (isDisabled) {\n return;\n }\n\n // Enter or Space activates button\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n handlePress({ type: 'keyboard', key: event.key });\n }\n },\n [handlePress, isDisabled]\n );\n\n const buttonProps: AccessibleButtonProps = {\n role,\n tabIndex: isDisabled ? -1 : 0,\n 'aria-label': label,\n 'aria-disabled': isDisabled ? true : undefined,\n disabled: elementType === 'button' ? isDisabled : undefined,\n onPointerDown: handlePointerDown,\n onKeyDown: handleKeyDown,\n };\n\n return {\n buttonProps,\n isPressed: isPressedRef.current,\n };\n};\n","/**\n * @a13y/react - useFocusTrap\n * Focus trap hook for modals and dialogs\n */\n\nimport type { FocusTrap } from '@a13y/core/runtime/focus';\nimport { useEffect, useRef } from 'react';\n\n/**\n * Props for useFocusTrap\n */\nexport interface UseFocusTrapProps {\n /**\n * Whether the focus trap is active\n */\n isActive: boolean;\n\n /**\n * Callback when Escape key is pressed\n */\n onEscape?: () => void;\n\n /**\n * Whether to restore focus when trap is deactivated\n * @default true\n */\n restoreFocus?: boolean;\n\n /**\n * Whether to auto-focus first element when activated\n * @default true\n */\n autoFocus?: boolean;\n}\n\n/**\n * Return type\n */\nexport interface UseFocusTrapReturn {\n /**\n * Ref to attach to the container element\n */\n trapRef: React.RefObject<HTMLElement | null>;\n}\n\n/**\n * Hook for creating focus traps\n *\n * Features:\n * - Traps Tab/Shift+Tab within container\n * - Handles Escape key\n * - Restores focus on deactivation\n * - Auto-focuses first element\n * - Development-time validation\n *\n * @example\n * ```tsx\n * const { trapRef } = useFocusTrap({\n * isActive: isOpen,\n * onEscape: () => setIsOpen(false),\n * });\n *\n * return (\n * <div ref={trapRef} role=\"dialog\">\n * <button>Close</button>\n * </div>\n * );\n * ```\n */\nexport const useFocusTrap = (props: UseFocusTrapProps): UseFocusTrapReturn => {\n const { isActive, onEscape, restoreFocus = true, autoFocus = true } = props;\n\n const trapRef = useRef<HTMLElement>(null);\n const focusTrapRef = useRef<FocusTrap | null>(null);\n const previousFocusRef = useRef<HTMLElement | null>(null);\n\n useEffect(() => {\n if (!isActive || !trapRef.current) {\n return;\n }\n\n // Save previous focus\n if (restoreFocus) {\n previousFocusRef.current = document.activeElement as HTMLElement;\n }\n\n // Create focus trap\n import('@a13y/core/runtime/focus').then(({ createFocusTrap }) => {\n if (!trapRef.current) {\n return;\n }\n\n const options: import('@a13y/core/runtime/focus').FocusTrapOptions = {\n returnFocus: false,\n onEscape: onEscape,\n };\n\n // Only set initialFocus if autoFocus is enabled\n if (autoFocus) {\n // undefined means auto-focus first focusable element\n options.initialFocus = undefined;\n }\n\n const trap = createFocusTrap(trapRef.current, options);\n\n trap.activate();\n focusTrapRef.current = trap;\n\n // Development-time validation\n if (typeof __DEV__ !== 'undefined' && __DEV__) {\n import('@a13y/devtools/runtime/validators').then(({ focusValidator }) => {\n if (trapRef.current) {\n focusValidator.validateFocusTrap(trapRef.current, true);\n }\n });\n }\n });\n\n // Cleanup\n return () => {\n if (focusTrapRef.current) {\n focusTrapRef.current.deactivate();\n focusTrapRef.current = null;\n }\n\n // Restore focus\n if (restoreFocus && previousFocusRef.current) {\n previousFocusRef.current.focus();\n\n // Validate focus restoration in dev\n if (typeof __DEV__ !== 'undefined' && __DEV__) {\n import('@a13y/devtools/runtime/validators').then(({ focusValidator }) => {\n if (previousFocusRef.current) {\n focusValidator.expectFocusRestoration(\n previousFocusRef.current,\n 'focus trap deactivation'\n );\n }\n });\n }\n }\n };\n }, [isActive, onEscape, restoreFocus, autoFocus]);\n\n return {\n trapRef,\n };\n};\n","/**\n * @a13y/react - useAccessibleDialog\n * Type-safe dialog/modal hook with full ARIA support\n */\n\nimport type { AriaRole } from 'react';\nimport { useEffect, useId, useRef } from 'react';\nimport { useFocusTrap } from './use-focus-trap';\n\n/**\n * Props for useAccessibleDialog\n */\nexport interface UseAccessibleDialogProps {\n /**\n * Whether the dialog is open\n */\n isOpen: boolean;\n\n /**\n * Callback when dialog should close\n * Called on Escape key or backdrop click\n */\n onClose: () => void;\n\n /**\n * Dialog title - REQUIRED for accessibility\n * This becomes the aria-labelledby target\n */\n title: string;\n\n /**\n * Optional dialog description\n * This becomes the aria-describedby target\n */\n description?: string;\n\n /**\n * ARIA role\n * @default 'dialog'\n */\n role?: Extract<AriaRole, 'dialog' | 'alertdialog'>;\n\n /**\n * Whether dialog is modal (blocking)\n * @default true\n */\n isModal?: boolean;\n\n /**\n * Whether clicking backdrop closes dialog\n * @default true\n */\n closeOnBackdropClick?: boolean;\n}\n\n/**\n * Dialog container props\n */\nexport interface DialogContainerProps {\n ref: React.RefObject<HTMLElement | null>;\n role: AriaRole;\n 'aria-labelledby': string;\n 'aria-describedby'?: string;\n 'aria-modal': boolean;\n tabIndex: -1;\n}\n\n/**\n * Title props\n */\nexport interface DialogTitleProps {\n id: string;\n}\n\n/**\n * Description props\n */\nexport interface DialogDescriptionProps {\n id: string;\n}\n\n/**\n * Backdrop props\n */\nexport interface DialogBackdropProps {\n onClick: () => void;\n 'aria-hidden': true;\n}\n\n/**\n * Return type\n */\nexport interface UseAccessibleDialogReturn {\n dialogProps: DialogContainerProps;\n titleProps: DialogTitleProps;\n descriptionProps: DialogDescriptionProps | null;\n backdropProps: DialogBackdropProps | null;\n close: () => void;\n}\n\n/**\n * Hook for creating accessible dialogs/modals\n *\n * Features:\n * - Focus trap with Tab/Shift+Tab cycling\n * - Escape key to close\n * - Focus restoration on close\n * - ARIA attributes (modal, labelledby, describedby)\n * - Backdrop click handling\n * - Development-time validation\n *\n * @example\n * ```tsx\n * const { dialogProps, titleProps, descriptionProps, backdropProps } =\n * useAccessibleDialog({\n * isOpen,\n * onClose: () => setIsOpen(false),\n * title: 'Delete Item',\n * description: 'This action cannot be undone',\n * });\n *\n * if (!isOpen) return null;\n *\n * return (\n * <>\n * <div {...backdropProps} />\n * <div {...dialogProps}>\n * <h2 {...titleProps}>Delete Item</h2>\n * <p {...descriptionProps}>This action cannot be undone</p>\n * <button onClick={close}>Cancel</button>\n * </div>\n * </>\n * );\n * ```\n */\nexport const useAccessibleDialog = (props: UseAccessibleDialogProps): UseAccessibleDialogReturn => {\n const {\n isOpen,\n onClose,\n title,\n description,\n role = 'dialog',\n isModal = true,\n closeOnBackdropClick = true,\n } = props;\n\n // Compile-time validation: title is required\n if (typeof __DEV__ !== 'undefined' && __DEV__) {\n if (!title || title.trim().length === 0) {\n throw new Error(\n '@a13y/react [useAccessibleDialog]: \"title\" prop is required for accessibility'\n );\n }\n }\n\n const dialogRef = useRef<HTMLElement>(null);\n const titleId = useId();\n const descriptionId = useId();\n\n // Focus trap\n const { trapRef } = useFocusTrap({\n isActive: isOpen,\n onEscape: onClose,\n restoreFocus: true,\n autoFocus: true,\n });\n\n // Sync refs (trapRef and dialogRef point to same element)\n useEffect(() => {\n if (dialogRef.current && trapRef.current !== dialogRef.current) {\n (trapRef as React.MutableRefObject<HTMLElement | null>).current = dialogRef.current;\n }\n }, [trapRef]);\n\n // Body scroll lock when modal is open\n useEffect(() => {\n if (!isOpen || !isModal) {\n return;\n }\n\n const originalOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n\n return () => {\n document.body.style.overflow = originalOverflow;\n };\n }, [isOpen, isModal]);\n\n // Development-time validation\n useEffect(() => {\n if (typeof __DEV__ !== 'undefined' && __DEV__ && isOpen) {\n import('@a13y/devtools/runtime/invariants').then(\n ({ assertHasAccessibleName, assertValidAriaAttributes }) => {\n if (dialogRef.current) {\n assertHasAccessibleName(dialogRef.current, 'useAccessibleDialog');\n assertValidAriaAttributes(dialogRef.current);\n }\n }\n );\n }\n }, [isOpen]);\n\n const dialogProps: DialogContainerProps = {\n ref: dialogRef,\n role,\n 'aria-labelledby': titleId,\n 'aria-describedby': description ? descriptionId : undefined,\n 'aria-modal': isModal,\n tabIndex: -1,\n };\n\n const titleProps: DialogTitleProps = {\n id: titleId,\n };\n\n const descriptionProps: DialogDescriptionProps | null = description\n ? { id: descriptionId }\n : null;\n\n const backdropProps: DialogBackdropProps | null =\n closeOnBackdropClick && isModal\n ? {\n onClick: onClose,\n 'aria-hidden': true,\n }\n : null;\n\n return {\n dialogProps,\n titleProps,\n descriptionProps,\n backdropProps,\n close: onClose,\n };\n};\n","/**\n * @a13y/react - useKeyboardNavigation\n * Roving tabindex keyboard navigation hook\n */\n\nimport type { NavigationDirection } from '@a13y/core/runtime/keyboard';\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\n/**\n * Navigation orientation\n */\nexport type Orientation = 'horizontal' | 'vertical' | 'both';\n\n/**\n * Props for useKeyboardNavigation\n */\nexport interface UseKeyboardNavigationProps {\n /**\n * Navigation orientation\n * - 'horizontal': Arrow Left/Right\n * - 'vertical': Arrow Up/Down\n * - 'both': All arrow keys\n */\n orientation: Orientation;\n\n /**\n * Whether to loop at boundaries\n * @default false\n */\n loop?: boolean;\n\n /**\n * Callback when navigation occurs\n */\n onNavigate?: (index: number) => void;\n\n /**\n * Initial focused index\n * @default 0\n */\n defaultIndex?: number;\n\n /**\n * Controlled current index\n */\n currentIndex?: number;\n}\n\n/**\n * Item props for navigable items\n */\nexport interface NavigableItemProps {\n ref: (element: HTMLElement | null) => void;\n tabIndex: number;\n onKeyDown: (event: React.KeyboardEvent) => void;\n 'data-index': number;\n}\n\n/**\n * Return type\n */\nexport interface UseKeyboardNavigationReturn {\n /**\n * Current focused index\n */\n currentIndex: number;\n\n /**\n * Navigate to specific index\n */\n setCurrentIndex: (index: number) => void;\n\n /**\n * Get props for navigable item\n */\n getItemProps: (index: number) => NavigableItemProps;\n\n /**\n * Container props\n */\n containerProps: {\n role: 'toolbar' | 'listbox' | 'menu';\n 'aria-orientation': Orientation;\n };\n}\n\n/**\n * Hook for keyboard navigation with roving tabindex\n *\n * Features:\n * - Arrow key navigation\n * - Home/End navigation\n * - Roving tabindex pattern\n * - Automatic focus management\n * - Development-time validation\n *\n * @example\n * ```tsx\n * const { containerProps, getItemProps, currentIndex } =\n * useKeyboardNavigation({\n * orientation: 'horizontal',\n * loop: true,\n * });\n *\n * return (\n * <div {...containerProps}>\n * {items.map((item, index) => (\n * <button key={index} {...getItemProps(index)}>\n * {item.label}\n * </button>\n * ))}\n * </div>\n * );\n * ```\n */\nexport const useKeyboardNavigation = (\n props: UseKeyboardNavigationProps\n): UseKeyboardNavigationReturn => {\n const {\n orientation,\n loop = false,\n onNavigate,\n defaultIndex = 0,\n currentIndex: controlledIndex,\n } = props;\n\n const isControlled = controlledIndex !== undefined;\n const [uncontrolledIndex, setUncontrolledIndex] = useState(defaultIndex);\n const currentIndex = isControlled ? controlledIndex : uncontrolledIndex;\n\n const itemsRef = useRef<Map<number, HTMLElement>>(new Map());\n const containerRef = useRef<HTMLElement | null>(null);\n\n // Update current index\n const setCurrentIndex = useCallback(\n (index: number) => {\n if (!isControlled) {\n setUncontrolledIndex(index);\n }\n onNavigate?.(index);\n\n // Focus the element\n const element = itemsRef.current.get(index);\n if (element) {\n element.focus();\n }\n },\n [isControlled, onNavigate]\n );\n\n // Navigate in direction\n const navigate = useCallback(\n (direction: NavigationDirection) => {\n const itemCount = itemsRef.current.size;\n if (itemCount === 0) {\n return;\n }\n\n let nextIndex = currentIndex;\n\n switch (direction) {\n case 'forward':\n nextIndex = currentIndex + 1;\n if (nextIndex >= itemCount) {\n nextIndex = loop ? 0 : itemCount - 1;\n }\n break;\n\n case 'backward':\n nextIndex = currentIndex - 1;\n if (nextIndex < 0) {\n nextIndex = loop ? itemCount - 1 : 0;\n }\n break;\n\n case 'first':\n nextIndex = 0;\n break;\n\n case 'last':\n nextIndex = itemCount - 1;\n break;\n }\n\n if (nextIndex !== currentIndex) {\n setCurrentIndex(nextIndex);\n }\n },\n [currentIndex, loop, setCurrentIndex]\n );\n\n // Handle keyboard events\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent) => {\n const { key } = event;\n\n let direction: NavigationDirection | null = null;\n\n // Arrow keys\n if (key === 'ArrowRight') {\n if (orientation === 'horizontal' || orientation === 'both') {\n direction = 'forward';\n }\n } else if (key === 'ArrowLeft') {\n if (orientation === 'horizontal' || orientation === 'both') {\n direction = 'backward';\n }\n } else if (key === 'ArrowDown') {\n if (orientation === 'vertical' || orientation === 'both') {\n direction = 'forward';\n }\n } else if (key === 'ArrowUp') {\n if (orientation === 'vertical' || orientation === 'both') {\n direction = 'backward';\n }\n }\n\n // Home/End\n else if (key === 'Home') {\n direction = 'first';\n } else if (key === 'End') {\n direction = 'last';\n }\n\n if (direction) {\n event.preventDefault();\n navigate(direction);\n }\n },\n [orientation, navigate]\n );\n\n // Get props for individual item\n const getItemProps = useCallback(\n (index: number): NavigableItemProps => {\n return {\n ref: (element: HTMLElement | null) => {\n if (element) {\n itemsRef.current.set(index, element);\n } else {\n itemsRef.current.delete(index);\n }\n },\n tabIndex: index === currentIndex ? 0 : -1,\n onKeyDown: handleKeyDown,\n 'data-index': index,\n };\n },\n [currentIndex, handleKeyDown]\n );\n\n // Development-time validation\n useEffect(() => {\n if (typeof __DEV__ !== 'undefined' && __DEV__) {\n import('@a13y/devtools/runtime/validators').then(({ keyboardValidator }) => {\n // Validate container\n if (containerRef.current) {\n keyboardValidator.validateContainer(containerRef.current);\n }\n\n // Validate roving tabindex\n const container = Array.from(itemsRef.current.values())[0]?.parentElement;\n if (container) {\n keyboardValidator.validateRovingTabindex(container);\n }\n });\n }\n }, []);\n\n const containerProps = {\n role: 'toolbar' as const,\n 'aria-orientation': orientation,\n };\n\n return {\n currentIndex,\n setCurrentIndex,\n getItemProps,\n containerProps,\n };\n};\n","/**\n * @a13y/react - useAccessibleForm Hook\n * Form management with accessibility built-in\n */\n\nimport { announce } from '@a13y/core/runtime/announce';\nimport { useCallback, useRef, useState } from 'react';\n\n/**\n * Field-level validation function\n */\nexport type FieldValidator<T> = (value: T) => string | true;\n\n/**\n * Form-level validation function (for cross-field validation)\n */\nexport type FormValidator<T> = (values: T) => Record<string, string> | null;\n\n/**\n * Field configuration\n */\nexport interface FieldConfig<T> {\n /**\n * Initial value\n */\n initialValue: T;\n\n /**\n * Validation function (optional)\n * Return true if valid, or error message if invalid\n */\n validate?: FieldValidator<T>;\n\n /**\n * Required field\n * @default false\n */\n required?: boolean;\n\n /**\n * Custom required message\n */\n requiredMessage?: string;\n}\n\n/**\n * Form configuration\n */\nexport interface FormConfig<T extends Record<string, unknown>> {\n /**\n * Field configurations\n */\n fields: {\n [K in keyof T]: FieldConfig<T[K]>;\n };\n\n /**\n * Form-level validation (optional)\n * For cross-field validation\n */\n validate?: FormValidator<T>;\n\n /**\n * Called when form is successfully submitted\n */\n onSubmit: (values: T) => void | Promise<void>;\n\n /**\n * Auto-focus first error on validation failure\n * @default true\n */\n autoFocusError?: boolean;\n\n /**\n * Announce errors to screen readers\n * @default true\n */\n announceErrors?: boolean;\n\n /**\n * Validate on blur\n * @default true\n */\n validateOnBlur?: boolean;\n\n /**\n * Validate on change (after first blur)\n * @default true\n */\n validateOnChange?: boolean;\n}\n\n/**\n * Form state\n */\nexport interface FormState<T extends Record<string, unknown>> {\n /**\n * Current form values\n */\n values: T;\n\n /**\n * Field errors\n */\n errors: Partial<Record<keyof T, string>>;\n\n /**\n * Fields that have been touched (blurred at least once)\n */\n touched: Partial<Record<keyof T, boolean>>;\n\n /**\n * Is form submitting\n */\n isSubmitting: boolean;\n\n /**\n * Is form valid (no errors)\n */\n isValid: boolean;\n\n /**\n * Has form been submitted at least once\n */\n hasSubmitted: boolean;\n}\n\n/**\n * Field props for binding to input elements\n */\nexport interface FieldProps<T> {\n name: string;\n value: T;\n onChange: (value: T) => void;\n onBlur: () => void;\n 'aria-invalid': boolean;\n 'aria-describedby'?: string;\n 'aria-required'?: boolean;\n}\n\n/**\n * Form return value\n */\nexport interface UseAccessibleFormReturn<T extends Record<string, unknown>> {\n /**\n * Form state\n */\n state: FormState<T>;\n\n /**\n * Get props for a field\n */\n getFieldProps: <K extends keyof T>(\n name: K,\n options?: { 'aria-describedby'?: string }\n ) => FieldProps<T[K]>;\n\n /**\n * Set field value programmatically\n */\n setFieldValue: <K extends keyof T>(name: K, value: T[K]) => void;\n\n /**\n * Set field error programmatically\n */\n setFieldError: <K extends keyof T>(name: K, error: string) => void;\n\n /**\n * Set multiple field errors at once\n */\n setErrors: (errors: Partial<Record<keyof T, string>>) => void;\n\n /**\n * Validate a single field\n */\n validateField: <K extends keyof T>(name: K) => boolean;\n\n /**\n * Validate entire form\n */\n validateForm: () => boolean;\n\n /**\n * Handle form submit\n */\n handleSubmit: (e?: React.FormEvent) => void;\n\n /**\n * Reset form to initial values\n */\n reset: () => void;\n\n /**\n * Clear all errors\n */\n clearErrors: () => void;\n\n /**\n * Field refs for focus management\n */\n fieldRefs: Map<keyof T, HTMLElement>;\n}\n\n/**\n * useAccessibleForm Hook\n *\n * Comprehensive form management with accessibility built-in:\n * - Automatic error announcements to screen readers\n * - Auto-focus first error field on validation failure\n * - Required field validation\n * - Field-level and form-level validation\n * - aria-invalid and aria-describedby management\n * - Touch tracking for better UX\n *\n * Pattern Explanation:\n * - Each field gets automatic ARIA attributes\n * - Errors are announced via screen reader\n * - First error field receives focus on submit\n * - Validation can run on blur or change\n * - Required fields enforced via TypeScript\n *\n * @example\n * ```tsx\n * const form = useAccessibleForm({\n * fields: {\n * email: {\n * initialValue: '',\n * required: true,\n * validate: (value) => {\n * if (!value.includes('@')) return 'Invalid email';\n * return true;\n * },\n * },\n * password: {\n * initialValue: '',\n * required: true,\n * validate: (value) => {\n * if (value.length < 8) return 'Password must be at least 8 characters';\n * return true;\n * },\n * },\n * },\n * onSubmit: (values) => {\n * console.log('Form submitted:', values);\n * },\n * });\n *\n * return (\n * <form onSubmit={form.handleSubmit}>\n * <input {...form.getFieldProps('email')} type=\"email\" />\n * {form.state.errors.email && (\n * <span id=\"email-error\">{form.state.errors.email}</span>\n * )}\n * </form>\n * );\n * ```\n */\nexport const useAccessibleForm = <T extends Record<string, unknown>>(\n config: FormConfig<T>\n): UseAccessibleFormReturn<T> => {\n const {\n fields,\n validate: formValidator,\n onSubmit,\n autoFocusError = true,\n announceErrors = true,\n validateOnBlur = true,\n validateOnChange = true,\n } = config;\n\n // Initialize form values from field configs\n const initialValues = Object.keys(fields).reduce((acc, key) => {\n acc[key as keyof T] = fields[key as keyof T].initialValue;\n return acc;\n }, {} as T);\n\n const [values, setValues] = useState<T>(initialValues);\n const [errors, setErrors] = useState<Partial<Record<keyof T, string>>>({});\n const [touched, setTouched] = useState<Partial<Record<keyof T, boolean>>>({});\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [hasSubmitted, setHasSubmitted] = useState(false);\n\n // Field refs for focus management\n const fieldRefs = useRef<Map<keyof T, HTMLElement>>(new Map());\n\n // Validate a single field\n const validateField = useCallback(\n <K extends keyof T>(name: K): boolean => {\n const fieldConfig = fields[name];\n const value = values[name];\n\n // Check required\n if (fieldConfig.required) {\n const isEmpty =\n value === '' ||\n value === null ||\n value === undefined ||\n (Array.isArray(value) && value.length === 0);\n\n if (isEmpty) {\n const errorMessage = fieldConfig.requiredMessage || `${String(name)} is required`;\n setErrors((prev) => ({ ...prev, [name]: errorMessage }));\n return false;\n }\n }\n\n // Run custom validator\n if (fieldConfig.validate) {\n const result = fieldConfig.validate(value);\n if (result !== true) {\n setErrors((prev) => ({ ...prev, [name]: result }));\n return false;\n }\n }\n\n // Clear error if valid\n setErrors((prev) => {\n const newErrors = { ...prev };\n delete newErrors[name];\n return newErrors;\n });\n return true;\n },\n [fields, values]\n );\n\n // Validate entire form\n const validateForm = useCallback((): boolean => {\n let isValid = true;\n const newErrors: Partial<Record<keyof T, string>> = {};\n\n // Validate all fields\n for (const name of Object.keys(fields) as Array<keyof T>) {\n const fieldConfig = fields[name];\n const value = values[name];\n\n // Check required\n if (fieldConfig.required) {\n const isEmpty =\n value === '' ||\n value === null ||\n value === undefined ||\n (Array.isArray(value) && value.length === 0);\n\n if (isEmpty) {\n const errorMessage = fieldConfig.requiredMessage || `${String(name)} is required`;\n newErrors[name] = errorMessage;\n isValid = false;\n continue;\n }\n }\n\n // Run custom validator\n if (fieldConfig.validate) {\n const result = fieldConfig.validate(value);\n if (result !== true) {\n newErrors[name] = result;\n isValid = false;\n }\n }\n }\n\n // Run form-level validator\n if (formValidator) {\n const formErrors = formValidator(values);\n if (formErrors) {\n Object.assign(newErrors, formErrors);\n isValid = false;\n }\n }\n\n setErrors(newErrors);\n return isValid;\n }, [fields, values, formValidator]);\n\n // Set field value\n const setFieldValue = useCallback(<K extends keyof T>(name: K, value: T[K]) => {\n setValues((prev) => ({ ...prev, [name]: value }));\n }, []);\n\n // Set field error\n const setFieldError = useCallback(<K extends keyof T>(name: K, error: string) => {\n setErrors((prev) => ({ ...prev, [name]: error }));\n }, []);\n\n // Get field props\n const getFieldProps = useCallback(\n <K extends keyof T>(name: K, options?: { 'aria-describedby'?: string }): FieldProps<T[K]> => {\n const fieldConfig = fields[name];\n const hasError = !!errors[name];\n const errorId = `${String(name)}-error`;\n\n return {\n name: String(name),\n value: values[name],\n onChange: (value: T[K]) => {\n setFieldValue(name, value);\n // Validate on change if field has been touched\n if (validateOnChange && touched[name]) {\n validateField(name);\n }\n },\n onBlur: () => {\n setTouched((prev) => ({ ...prev, [name]: true }));\n if (validateOnBlur) {\n validateField(name);\n }\n },\n 'aria-invalid': hasError,\n 'aria-describedby': hasError\n ? options?.['aria-describedby']\n ? `${errorId} ${options['aria-describedby']}`\n : errorId\n : options?.['aria-describedby'],\n 'aria-required': fieldConfig.required,\n };\n },\n [\n fields,\n values,\n errors,\n touched,\n setFieldValue,\n validateField,\n validateOnBlur,\n validateOnChange,\n ]\n );\n\n // Handle form submit\n const handleSubmit = useCallback(\n async (e?: React.FormEvent) => {\n e?.preventDefault();\n\n setHasSubmitted(true);\n const isValid = validateForm();\n\n if (!isValid) {\n // Count errors\n const errorCount = Object.keys(errors).length;\n\n // Announce errors to screen reader\n if (announceErrors) {\n const errorMessage =\n errorCount === 1\n ? 'Form has 1 error. Please correct it and try again.'\n : `Form has ${errorCount} errors. Please correct them and try again.`;\n announce(errorMessage, { politeness: 'assertive' });\n }\n\n // Focus first error field\n if (autoFocusError) {\n const firstErrorField = Object.keys(errors)[0] as keyof T;\n const fieldElement = fieldRefs.current.get(firstErrorField);\n if (fieldElement) {\n fieldElement.focus();\n }\n }\n\n return;\n }\n\n // Submit form\n setIsSubmitting(true);\n try {\n await onSubmit(values);\n announce('Form submitted successfully', { politeness: 'polite' });\n } catch (error) {\n if (announceErrors) {\n announce('Form submission failed. Please try again.', {\n politeness: 'assertive',\n });\n }\n throw error;\n } finally {\n setIsSubmitting(false);\n }\n },\n [validateForm, errors, announceErrors, autoFocusError, onSubmit, values]\n );\n\n // Reset form\n const reset = useCallback(() => {\n setValues(initialValues);\n setErrors({});\n setTouched({});\n setHasSubmitted(false);\n }, [initialValues]);\n\n // Clear all errors\n const clearErrors = useCallback(() => {\n setErrors({});\n }, []);\n\n const isValid = Object.keys(errors).length === 0;\n\n return {\n state: {\n values,\n errors,\n touched,\n isSubmitting,\n isValid,\n hasSubmitted,\n },\n getFieldProps,\n setFieldValue,\n setFieldError,\n setErrors,\n validateField,\n validateForm,\n handleSubmit,\n reset,\n clearErrors,\n fieldRefs: fieldRefs.current,\n };\n};\n","/**\n * @a13y/react - useFormField Hook\n * Individual form field management with accessibility built-in\n */\n\nimport { announce } from '@a13y/core/runtime/announce';\nimport { useCallback, useEffect, useId, useRef, useState } from 'react';\n\n/**\n * Props for useFormField\n */\nexport interface UseFormFieldProps<T = string> {\n /**\n * Field label (required for accessibility)\n * This will be used as the accessible name\n */\n label: string;\n\n /**\n * Initial field value\n */\n initialValue?: T;\n\n /**\n * Validation function\n * Return true if valid, or error message if invalid\n */\n validate?: (value: T) => string | true;\n\n /**\n * Is field required\n * @default false\n */\n required?: boolean;\n\n /**\n * Custom required message\n */\n requiredMessage?: string;\n\n /**\n * Help text to display\n */\n helpText?: string;\n\n /**\n * Validate on blur\n * @default true\n */\n validateOnBlur?: boolean;\n\n /**\n * Validate on change (after first blur)\n * @default true\n */\n validateOnChange?: boolean;\n\n /**\n * Announce errors to screen readers\n * @default true\n */\n announceErrors?: boolean;\n\n /**\n * Called when value changes\n */\n onChange?: (value: T) => void;\n\n /**\n * Called when field is blurred\n */\n onBlur?: () => void;\n}\n\n/**\n * Return value from useFormField\n */\nexport interface UseFormFieldReturn<T = string> {\n /**\n * Field ID (generated)\n */\n id: string;\n\n /**\n * Label ID (generated)\n */\n labelId: string;\n\n /**\n * Error message ID (generated)\n */\n errorId: string;\n\n /**\n * Help text ID (generated)\n */\n helpTextId: string;\n\n /**\n * Current field value\n */\n value: T;\n\n /**\n * Current error message (if any)\n */\n error: string | null;\n\n /**\n * Has field been touched (blurred at least once)\n */\n isTouched: boolean;\n\n /**\n * Is field valid\n */\n isValid: boolean;\n\n /**\n * Set field value\n */\n setValue: (value: T) => void;\n\n /**\n * Set field error\n */\n setError: (error: string | null) => void;\n\n /**\n * Validate field\n */\n validate: () => boolean;\n\n /**\n * Clear error\n */\n clearError: () => void;\n\n /**\n * Reset field to initial value\n */\n reset: () => void;\n\n /**\n * Props for label element\n */\n labelProps: {\n id: string;\n htmlFor: string;\n };\n\n /**\n * Props for input element\n */\n inputProps: {\n id: string;\n name: string;\n value: T;\n onChange: (value: T) => void;\n onBlur: () => void;\n 'aria-labelledby': string;\n 'aria-describedby'?: string;\n 'aria-invalid': boolean;\n 'aria-required'?: boolean;\n ref: React.RefObject<HTMLInputElement | null>;\n };\n\n /**\n * Props for error message element\n */\n errorProps: {\n id: string;\n role: 'alert';\n 'aria-live': 'polite';\n };\n\n /**\n * Props for help text element\n */\n helpTextProps: {\n id: string;\n };\n\n /**\n * Field ref for focus management\n */\n fieldRef: React.RefObject<HTMLInputElement | null>;\n}\n\n/**\n * useFormField Hook\n *\n * Manages a single form field with accessibility built-in:\n * - Required label via TypeScript\n * - Automatic ARIA attributes\n * - Error announcements to screen readers\n * - Help text support\n * - Validation on blur/change\n * - ID generation for ARIA relationships\n *\n * Pattern Explanation:\n * - Label is required (enforced at compile-time)\n * - aria-labelledby automatically connects label to input\n * - aria-describedby automatically connects errors and help text\n * - aria-invalid automatically set when error exists\n * - Errors announced to screen readers when they appear\n *\n * @example\n * ```tsx\n * const emailField = useFormField({\n * label: 'Email Address',\n * required: true,\n * validate: (value) => {\n * if (!value.includes('@')) return 'Invalid email address';\n * return true;\n * },\n * helpText: 'We will never share your email',\n * });\n *\n * return (\n * <div>\n * <label {...emailField.labelProps}>{emailField.label}</label>\n * <input\n * {...emailField.inputProps}\n * type=\"email\"\n * onChange={(e) => emailField.inputProps.onChange(e.target.value)}\n * />\n * {emailField.helpText && (\n * <span {...emailField.helpTextProps}>{emailField.helpText}</span>\n * )}\n * {emailField.error && (\n * <span {...emailField.errorProps}>{emailField.error}</span>\n * )}\n * </div>\n * );\n * ```\n */\nexport const useFormField = <T = string>(props: UseFormFieldProps<T>): UseFormFieldReturn<T> => {\n const {\n label,\n initialValue = '' as T,\n validate: validator,\n required = false,\n requiredMessage,\n helpText,\n validateOnBlur = true,\n validateOnChange = true,\n announceErrors = true,\n onChange,\n onBlur,\n } = props;\n\n // Development-time validation\n if (typeof __DEV__ !== 'undefined' && __DEV__) {\n if (!label || label.trim().length === 0) {\n throw new Error('@a13y/react [useFormField]: \"label\" prop is required for accessibility');\n }\n }\n\n const [value, setValue] = useState<T>(initialValue);\n const [error, setError] = useState<string | null>(null);\n const [isTouched, setIsTouched] = useState(false);\n\n const fieldRef = useRef<HTMLInputElement>(null);\n\n // Generate unique IDs\n const id = useId();\n const labelId = `${id}-label`;\n const errorId = `${id}-error`;\n const helpTextId = `${id}-help`;\n\n // Validate field\n const validate = useCallback((): boolean => {\n // Check required\n if (required) {\n const isEmpty =\n value === '' ||\n value === null ||\n value === undefined ||\n (Array.isArray(value) && value.length === 0);\n\n if (isEmpty) {\n const errorMessage = requiredMessage || `${label} is required`;\n setError(errorMessage);\n return false;\n }\n }\n\n // Run custom validator\n if (validator) {\n const result = validator(value);\n if (result !== true) {\n setError(result);\n return false;\n }\n }\n\n // Clear error if valid\n setError(null);\n return true;\n }, [value, required, validator, label, requiredMessage]);\n\n // Announce error to screen reader when it changes\n useEffect(() => {\n if (error && isTouched && announceErrors) {\n announce(error, { politeness: 'assertive', delay: 100 });\n }\n }, [error, isTouched, announceErrors]);\n\n // Handle value change\n const handleChange = useCallback(\n (newValue: T) => {\n setValue(newValue);\n onChange?.(newValue);\n\n // Validate on change if field has been touched\n if (validateOnChange && isTouched) {\n // Validate in next tick to ensure state is updated\n setTimeout(() => validate(), 0);\n }\n },\n [onChange, validateOnChange, isTouched, validate]\n );\n\n // Handle blur\n const handleBlur = useCallback(() => {\n setIsTouched(true);\n onBlur?.();\n\n if (validateOnBlur) {\n validate();\n }\n }, [onBlur, validateOnBlur, validate]);\n\n // Clear error\n const clearError = useCallback(() => {\n setError(null);\n }, []);\n\n // Reset field\n const reset = useCallback(() => {\n setValue(initialValue);\n setError(null);\n setIsTouched(false);\n }, [initialValue]);\n\n const isValid = error === null;\n\n // Build aria-describedby\n const describedBy = [helpText ? helpTextId : null, error ? errorId : null]\n .filter(Boolean)\n .join(' ');\n\n return {\n id,\n labelId,\n errorId,\n helpTextId,\n value,\n error,\n isTouched,\n isValid,\n setValue: handleChange,\n setError,\n validate,\n clearError,\n reset,\n labelProps: {\n id: labelId,\n htmlFor: id,\n },\n inputProps: {\n id,\n name: id,\n value,\n onChange: handleChange,\n onBlur: handleBlur,\n 'aria-labelledby': labelId,\n 'aria-describedby': describedBy || undefined,\n 'aria-invalid': !isValid,\n 'aria-required': required ? true : undefined,\n ref: fieldRef,\n },\n errorProps: {\n id: errorId,\n role: 'alert',\n 'aria-live': 'polite',\n },\n helpTextProps: {\n id: helpTextId,\n },\n fieldRef,\n };\n};\n\n/**\n * Helper type to ensure label is provided\n * Use this in component props to enforce accessible labels\n */\nexport type RequireLabel<T> = T & {\n label: string;\n};\n"]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export { AccessibleButton, AccessibleDialog, AccessibleMenu, AccessibleModal, AccessibleTabs, ButtonComponentProps, ButtonVariant, DialogComponentProps, MenuComponentProps, MenuItem, ModalComponentProps, Tab, TabsComponentProps } from './components/index.js';
|
|
2
|
+
export { A as AccessibleButtonProps, P as PressEvent, U as UseAccessibleButtonProps, a as UseAccessibleButtonReturn, u as useAccessibleButton } from './use-accessible-button-B0syf-Az.js';
|
|
3
|
+
export { DialogBackdropProps, DialogContainerProps, DialogDescriptionProps, DialogTitleProps, FieldConfig, FieldProps, FieldValidator, FormConfig, FormState, FormValidator, NavigableItemProps, RequireLabel, UseAccessibleDialogProps, UseAccessibleDialogReturn, UseAccessibleFormReturn, UseFocusTrapProps, UseFocusTrapReturn, UseFormFieldProps, UseFormFieldReturn, UseKeyboardNavigationProps, UseKeyboardNavigationReturn, useAccessibleDialog, useAccessibleForm, useFocusTrap, useFormField, useKeyboardNavigation } from './hooks/index.js';
|
|
4
|
+
export { DialogStackProvider, DialogStackProviderProps, InfiniteList, InfiniteListProps, NestedMenu, NestedMenuItem, NestedMenuProps, VirtualizedList, VirtualizedListProps, Wizard, WizardProps, WizardStep, useDialogStack, useWizard } from './patterns/index.js';
|
|
5
|
+
import 'react/jsx-runtime';
|
|
6
|
+
import 'react';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @a13y/react
|
|
10
|
+
* Type-safe React hooks and components for accessibility
|
|
11
|
+
* @packageDocumentation
|
|
12
|
+
*/
|
|
13
|
+
declare const VERSION: "0.0.0";
|
|
14
|
+
|
|
15
|
+
export { VERSION };
|