@opensourceframework/react-a11y-utils
Advanced tools
+11
-0
| # Changelog | ||
| ## 0.1.1 | ||
| ### Patch Changes | ||
| - 9bbe919: fix: resolve code quality issues across multiple packages | ||
| - react-a11y-utils: rename CSSProperties to A11yCSSProperties to avoid shadowing React's type | ||
| - seeded-rng: add error logging in catch block instead of silently swallowing errors | ||
| - next-csrf: return null for missing cookies (instead of empty string) to distinguish from empty values | ||
| - next-csrf: fix HttpError constructor to have proper default status value | ||
| - next-csrf: add @returns type info to nextCsrf() function JSDoc | ||
| ## 0.1.0 | ||
@@ -4,0 +15,0 @@ |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * React Accessibility Utilities\n * Helper functions and hooks for building accessible React applications\n * @module @opensourceframework/react-a11y-utils\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Standard accessibility props that can be spread onto elements\n */\nexport interface AccessibilityProps {\n 'aria-activedescendant'?: string;\n 'aria-atomic'?: 'true' | 'false';\n 'aria-autocomplete'?: 'inline' | 'list' | 'both' | 'none';\n 'aria-busy'?: 'true' | 'false';\n 'aria-checked'?: 'true' | 'false' | 'mixed';\n 'aria-colcount'?: number;\n 'aria-colindex'?: number;\n 'aria-colspan'?: number;\n 'aria-controls'?: string;\n 'aria-current'?: 'page' | 'step' | 'location' | 'date' | 'time' | 'true' | 'false';\n 'aria-describedby'?: string;\n 'aria-details'?: string;\n 'aria-disabled'?: 'true' | 'false';\n 'aria-dropeffect'?: 'copy' | 'execute' | 'link' | 'move' | 'none' | 'popup';\n 'aria-errormessage'?: string;\n 'aria-expanded'?: 'true' | 'false';\n 'aria-flowto'?: string;\n 'aria-grabbed'?: 'true' | 'false';\n 'aria-haspopup'?: 'false' | 'true' | 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog';\n 'aria-hidden'?: 'true' | 'false';\n 'aria-invalid'?: 'true' | 'false' | 'grammar' | 'spelling';\n 'aria-keyshortcuts'?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'aria-level'?: number;\n 'aria-live'?: 'off' | 'polite' | 'assertive';\n 'aria-modal'?: 'true' | 'false';\n 'aria-multiline'?: 'true' | 'false';\n 'aria-multiselectable'?: 'true' | 'false';\n 'aria-orientation'?: 'horizontal' | 'vertical';\n 'aria-owns'?: string;\n 'aria-placeholder'?: string;\n 'aria-posinset'?: number;\n 'aria-pressed'?: 'true' | 'false' | 'mixed';\n 'aria-readonly'?: 'true' | 'false';\n 'aria-relevant'?: 'additions' | 'removals' | 'text' | 'all';\n 'aria-required'?: 'true' | 'false';\n 'aria-roledescription'?: string;\n 'aria-rowcount'?: number;\n 'aria-rowindex'?: number;\n 'aria-rowspan'?: number;\n 'aria-selected'?: 'true' | 'false';\n 'aria-setsize'?: number;\n 'aria-sort'?: 'ascending' | 'descending' | 'none' | 'other';\n 'aria-valuemax'?: number;\n 'aria-valuemin'?: number;\n 'aria-valuenow'?: number;\n 'aria-valuetext'?: string;\n role?: string;\n tabIndex?: number;\n}\n\n/**\n * Props for live region elements\n */\nexport interface LiveRegionProps extends AccessibilityProps {\n 'aria-live'?: 'off' | 'polite' | 'assertive';\n 'aria-atomic'?: 'true' | 'false';\n 'aria-relevant'?: 'additions' | 'removals' | 'text' | 'all';\n 'aria-busy'?: 'true' | 'false';\n}\n\n/**\n * Options for creating live region props\n */\nexport interface LiveRegionOptions {\n /** Whether the entire region should be announced (true) or just changes (false) */\n atomic?: boolean;\n /** What types of changes are relevant */\n relevant?: 'additions' | 'removals' | 'text' | 'all';\n /** Whether the region is currently being updated */\n busy?: boolean;\n /** How assertive the announcement should be */\n live?: 'polite' | 'assertive';\n}\n\n/**\n * Props for disclosure elements (expand/collapse)\n */\nexport interface DisclosureProps extends AccessibilityProps {\n 'aria-expanded': 'true' | 'false';\n 'aria-controls': string;\n}\n\n/**\n * Props for toggle buttons with pressed state\n */\nexport interface PressedProps extends AccessibilityProps {\n 'aria-pressed': 'true' | 'false' | 'mixed';\n}\n\n/**\n * Props for selectable elements\n */\nexport interface SelectedProps extends AccessibilityProps {\n 'aria-selected': 'true' | 'false';\n}\n\n/**\n * Props for checkable elements\n */\nexport interface CheckedProps extends AccessibilityProps {\n 'aria-checked': 'true' | 'false' | 'mixed';\n}\n\n/**\n * CSS Properties type for style objects\n */\nexport type CSSProperties = Record<string, string | number | undefined>;\n\n// ============================================================================\n// Screen Reader Utilities\n// ============================================================================\n\n/**\n * CSS styles for screen-reader-only content\n * Elements with these styles are visually hidden but accessible to screen readers\n *\n * @example\n * ```tsx\n * <span style={srOnly}>Skip to main content</span>\n * ```\n */\nexport const srOnly: CSSProperties = {\n position: 'absolute',\n width: '1px',\n height: '1px',\n padding: '0',\n margin: '-1px',\n overflow: 'hidden',\n clip: 'rect(0, 0, 0, 0)',\n whiteSpace: 'nowrap',\n borderWidth: '0',\n};\n\n/**\n * CSS styles for making hidden content visible when focused\n * Use for skip links that should appear on focus\n *\n * @example\n * ```tsx\n * <a href=\"#main\" style={srOnlyFocusable}>Skip to main content</a>\n * ```\n */\nexport const srOnlyFocusable: CSSProperties = {\n position: 'absolute',\n width: 'auto',\n height: 'auto',\n padding: '1rem',\n margin: '0',\n overflow: 'visible',\n clip: 'auto',\n whiteSpace: 'normal',\n};\n\n// ============================================================================\n// ARIA Props Factories\n// ============================================================================\n\n/**\n * Props for decorative elements that should be hidden from screen readers\n *\n * @example\n * ```tsx\n * <img src=\"decoration.png\" alt=\"\" {...decorative} />\n * ```\n */\nexport const decorative: AccessibilityProps = {\n 'aria-hidden': 'true',\n};\n\n/**\n * Props for disabled interactive elements\n * Provides proper accessibility for disabled elements\n *\n * @example\n * ```tsx\n * <button {...disabledProps} onClick={handleClick}>Disabled</button>\n * ```\n */\nexport const disabledProps: AccessibilityProps = {\n 'aria-disabled': 'true',\n tabIndex: -1,\n};\n\n/**\n * Props for status messages (polite announcements)\n *\n * @example\n * ```tsx\n * <div {...statusMessageProps}>Changes saved successfully</div>\n * ```\n */\nexport const statusMessageProps: AccessibilityProps = {\n role: 'status',\n 'aria-live': 'polite',\n};\n\n/**\n * Props for alert messages (assertive announcements)\n *\n * @example\n * ```tsx\n * <div {...alertMessageProps}>Error: Please fill in all required fields</div>\n * ```\n */\nexport const alertMessageProps: AccessibilityProps = {\n role: 'alert',\n 'aria-live': 'assertive',\n};\n\n// ============================================================================\n// Factory Functions\n// ============================================================================\n\n/**\n * Creates props for live regions\n * Live regions announce changes to screen readers\n *\n * @param options - Configuration options for the live region\n * @returns Accessibility props for the live region\n *\n * @example\n * ```tsx\n * <div {...createLiveRegion({ atomic: true, live: 'polite' })}>\n * {message}\n * </div>\n * ```\n */\nexport function createLiveRegion(\n options: LiveRegionOptions = {}\n): LiveRegionProps {\n const {\n atomic = false,\n relevant = 'additions',\n busy = false,\n live = 'polite',\n } = options;\n\n return {\n 'aria-live': live,\n 'aria-atomic': atomic ? 'true' : 'false',\n 'aria-relevant': relevant,\n 'aria-busy': busy ? 'true' : 'false',\n };\n}\n\n/**\n * Creates props for skip links\n * Skip links allow keyboard users to bypass navigation\n *\n * @param targetId - The ID of the target element to skip to\n * @returns Props for the skip link element\n *\n * @example\n * ```tsx\n * <a {...createSkipLinkProps('main-content')}>Skip to main content</a>\n * // ...\n * <main id=\"main-content\">...</main>\n * ```\n */\nexport function createSkipLinkProps(targetId: string): {\n href: string;\n tabIndex: number;\n} {\n return {\n href: `#${targetId}`,\n tabIndex: 0,\n };\n}\n\n/**\n * Creates props for elements that expand/collapse content\n *\n * @param expanded - Whether the content is currently expanded\n * @param controlsId - The ID of the element being controlled\n * @returns Accessibility props for the disclosure trigger\n *\n * @example\n * ```tsx\n * <button {...createDisclosureProps(isOpen, 'panel-id')} onClick={toggle}>\n * Toggle Panel\n * </button>\n * <div id=\"panel-id\" hidden={!isOpen}>Panel content</div>\n * ```\n */\nexport function createDisclosureProps(\n expanded: boolean,\n controlsId: string\n): DisclosureProps {\n return {\n 'aria-expanded': expanded ? 'true' : 'false',\n 'aria-controls': controlsId,\n };\n}\n\n/**\n * Creates props for toggle buttons with pressed state\n *\n * @param pressed - Whether the button is currently pressed\n * @returns Accessibility props for the toggle button\n *\n * @example\n * ```tsx\n * <button {...createPressedProps(isActive)} onClick={toggle}>\n * Toggle Feature\n * </button>\n * ```\n */\nexport function createPressedProps(pressed: boolean): PressedProps {\n return {\n 'aria-pressed': pressed ? 'true' : 'false',\n };\n}\n\n/**\n * Creates props for elements with selected state\n *\n * @param selected - Whether the element is currently selected\n * @returns Accessibility props for the selectable element\n *\n * @example\n * ```tsx\n * <li {...createSelectedProps(isSelected)} role=\"option\">\n * Option 1\n * </li>\n * ```\n */\nexport function createSelectedProps(selected: boolean): SelectedProps {\n return {\n 'aria-selected': selected ? 'true' : 'false',\n };\n}\n\n/**\n * Creates props for elements with checked state\n *\n * @param checked - Whether the element is checked (true), unchecked (false), or indeterminate ('mixed')\n * @returns Accessibility props for the checkable element\n *\n * @example\n * ```tsx\n * <div {...createCheckedProps(checked)} role=\"checkbox\" tabIndex={0}>\n * {checked ? '✓' : ''}\n * </div>\n * ```\n */\nexport function createCheckedProps(\n checked: boolean | 'mixed'\n): CheckedProps {\n return {\n 'aria-checked': typeof checked === 'string' ? checked : (checked ? 'true' : 'false'),\n };\n}\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Combines multiple accessibility props objects\n * Later props override earlier ones for the same keys\n *\n * @param props - Array of accessibility props to merge\n * @returns Combined accessibility props\n *\n * @example\n * ```tsx\n * <div {...mergeA11yProps(statusMessageProps, { 'aria-label': 'Status' })}>\n * {message}\n * </div>\n * ```\n */\nexport function mergeA11yProps(\n ...props: AccessibilityProps[]\n): AccessibilityProps {\n return Object.assign({}, ...props);\n}\n\n/**\n * Creates props for a dialog/modal trigger\n *\n * @param dialogId - The ID of the dialog element\n * @param isOpen - Whether the dialog is currently open\n * @returns Accessibility props for the dialog trigger\n *\n * @example\n * ```tsx\n * <button {...createDialogTriggerProps('my-dialog', isOpen)}>\n * Open Dialog\n * </button>\n * ```\n */\nexport function createDialogTriggerProps(\n dialogId: string,\n isOpen: boolean\n): AccessibilityProps {\n return {\n 'aria-haspopup': 'dialog',\n 'aria-controls': dialogId,\n 'aria-expanded': isOpen ? 'true' : 'false',\n };\n}\n\n/**\n * Creates props for a required form field\n *\n * @param required - Whether the field is required\n * @param invalid - Whether the field value is invalid\n * @returns Accessibility props for the form field\n *\n * @example\n * ```tsx\n * <input {...createFormFieldProps(true, hasError)} />\n * ```\n */\nexport function createFormFieldProps(\n required: boolean,\n invalid: boolean = false\n): AccessibilityProps {\n const props: AccessibilityProps = {\n 'aria-required': required ? 'true' : 'false',\n };\n \n if (invalid) {\n props['aria-invalid'] = 'true';\n }\n \n return props;\n}\n\n/**\n * Creates props for describing an element with another element\n *\n * @param describedById - The ID of the element that describes this element\n * @returns Accessibility props with aria-describedby\n *\n * @example\n * ```tsx\n * <input {...createDescribedByProps('error-message')} />\n * <span id=\"error-message\">This field is required</span>\n * ```\n */\nexport function createDescribedByProps(\n describedById: string\n): AccessibilityProps {\n return {\n 'aria-describedby': describedById,\n };\n}\n\n/**\n * Creates props for labeling an element with another element\n *\n * @param labelledById - The ID of the element that labels this element\n * @returns Accessibility props with aria-labelledby\n *\n * @example\n * ```tsx\n * <div {...createLabelledByProps('panel-title')} role=\"region\">\n * <h2 id=\"panel-title\">Panel Title</h2>\n * Panel content\n * </div>\n * ```\n */\nexport function createLabelledByProps(\n labelledById: string\n): AccessibilityProps {\n return {\n 'aria-labelledby': labelledById,\n };\n}\n"]} | ||
| {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * React Accessibility Utilities\n * Helper functions and hooks for building accessible React applications\n * @module @opensourceframework/react-a11y-utils\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Standard accessibility props that can be spread onto elements\n */\nexport interface AccessibilityProps {\n 'aria-activedescendant'?: string;\n 'aria-atomic'?: 'true' | 'false';\n 'aria-autocomplete'?: 'inline' | 'list' | 'both' | 'none';\n 'aria-busy'?: 'true' | 'false';\n 'aria-checked'?: 'true' | 'false' | 'mixed';\n 'aria-colcount'?: number;\n 'aria-colindex'?: number;\n 'aria-colspan'?: number;\n 'aria-controls'?: string;\n 'aria-current'?: 'page' | 'step' | 'location' | 'date' | 'time' | 'true' | 'false';\n 'aria-describedby'?: string;\n 'aria-details'?: string;\n 'aria-disabled'?: 'true' | 'false';\n 'aria-dropeffect'?: 'copy' | 'execute' | 'link' | 'move' | 'none' | 'popup';\n 'aria-errormessage'?: string;\n 'aria-expanded'?: 'true' | 'false';\n 'aria-flowto'?: string;\n 'aria-grabbed'?: 'true' | 'false';\n 'aria-haspopup'?: 'false' | 'true' | 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog';\n 'aria-hidden'?: 'true' | 'false';\n 'aria-invalid'?: 'true' | 'false' | 'grammar' | 'spelling';\n 'aria-keyshortcuts'?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'aria-level'?: number;\n 'aria-live'?: 'off' | 'polite' | 'assertive';\n 'aria-modal'?: 'true' | 'false';\n 'aria-multiline'?: 'true' | 'false';\n 'aria-multiselectable'?: 'true' | 'false';\n 'aria-orientation'?: 'horizontal' | 'vertical';\n 'aria-owns'?: string;\n 'aria-placeholder'?: string;\n 'aria-posinset'?: number;\n 'aria-pressed'?: 'true' | 'false' | 'mixed';\n 'aria-readonly'?: 'true' | 'false';\n 'aria-relevant'?: 'additions' | 'removals' | 'text' | 'all';\n 'aria-required'?: 'true' | 'false';\n 'aria-roledescription'?: string;\n 'aria-rowcount'?: number;\n 'aria-rowindex'?: number;\n 'aria-rowspan'?: number;\n 'aria-selected'?: 'true' | 'false';\n 'aria-setsize'?: number;\n 'aria-sort'?: 'ascending' | 'descending' | 'none' | 'other';\n 'aria-valuemax'?: number;\n 'aria-valuemin'?: number;\n 'aria-valuenow'?: number;\n 'aria-valuetext'?: string;\n role?: string;\n tabIndex?: number;\n}\n\n/**\n * Props for live region elements\n */\nexport interface LiveRegionProps extends AccessibilityProps {\n 'aria-live'?: 'off' | 'polite' | 'assertive';\n 'aria-atomic'?: 'true' | 'false';\n 'aria-relevant'?: 'additions' | 'removals' | 'text' | 'all';\n 'aria-busy'?: 'true' | 'false';\n}\n\n/**\n * Options for creating live region props\n */\nexport interface LiveRegionOptions {\n /** Whether the entire region should be announced (true) or just changes (false) */\n atomic?: boolean;\n /** What types of changes are relevant */\n relevant?: 'additions' | 'removals' | 'text' | 'all';\n /** Whether the region is currently being updated */\n busy?: boolean;\n /** How assertive the announcement should be */\n live?: 'polite' | 'assertive';\n}\n\n/**\n * Props for disclosure elements (expand/collapse)\n */\nexport interface DisclosureProps extends AccessibilityProps {\n 'aria-expanded': 'true' | 'false';\n 'aria-controls': string;\n}\n\n/**\n * Props for toggle buttons with pressed state\n */\nexport interface PressedProps extends AccessibilityProps {\n 'aria-pressed': 'true' | 'false' | 'mixed';\n}\n\n/**\n * Props for selectable elements\n */\nexport interface SelectedProps extends AccessibilityProps {\n 'aria-selected': 'true' | 'false';\n}\n\n/**\n * Props for checkable elements\n */\nexport interface CheckedProps extends AccessibilityProps {\n 'aria-checked': 'true' | 'false' | 'mixed';\n}\n\n/**\n * CSS Properties type for style objects\n */\nexport type A11yCSSProperties = Record<string, string | number | undefined>;\n\n// ============================================================================\n// Screen Reader Utilities\n// ============================================================================\n\n/**\n * CSS styles for screen-reader-only content\n * Elements with these styles are visually hidden but accessible to screen readers\n *\n * @example\n * ```tsx\n * <span style={srOnly}>Skip to main content</span>\n * ```\n */\nexport const srOnly: A11yCSSProperties = {\n position: 'absolute',\n width: '1px',\n height: '1px',\n padding: '0',\n margin: '-1px',\n overflow: 'hidden',\n clip: 'rect(0, 0, 0, 0)',\n whiteSpace: 'nowrap',\n borderWidth: '0',\n};\n\n/**\n * CSS styles for making hidden content visible when focused\n * Use for skip links that should appear on focus\n *\n * @example\n * ```tsx\n * <a href=\"#main\" style={srOnlyFocusable}>Skip to main content</a>\n * ```\n */\nexport const srOnlyFocusable: A11yCSSProperties = {\n position: 'absolute',\n width: 'auto',\n height: 'auto',\n padding: '1rem',\n margin: '0',\n overflow: 'visible',\n clip: 'auto',\n whiteSpace: 'normal',\n};\n\n// ============================================================================\n// ARIA Props Factories\n// ============================================================================\n\n/**\n * Props for decorative elements that should be hidden from screen readers\n *\n * @example\n * ```tsx\n * <img src=\"decoration.png\" alt=\"\" {...decorative} />\n * ```\n */\nexport const decorative: AccessibilityProps = {\n 'aria-hidden': 'true',\n};\n\n/**\n * Props for disabled interactive elements\n * Provides proper accessibility for disabled elements\n *\n * @example\n * ```tsx\n * <button {...disabledProps} onClick={handleClick}>Disabled</button>\n * ```\n */\nexport const disabledProps: AccessibilityProps = {\n 'aria-disabled': 'true',\n tabIndex: -1,\n};\n\n/**\n * Props for status messages (polite announcements)\n *\n * @example\n * ```tsx\n * <div {...statusMessageProps}>Changes saved successfully</div>\n * ```\n */\nexport const statusMessageProps: AccessibilityProps = {\n role: 'status',\n 'aria-live': 'polite',\n};\n\n/**\n * Props for alert messages (assertive announcements)\n *\n * @example\n * ```tsx\n * <div {...alertMessageProps}>Error: Please fill in all required fields</div>\n * ```\n */\nexport const alertMessageProps: AccessibilityProps = {\n role: 'alert',\n 'aria-live': 'assertive',\n};\n\n// ============================================================================\n// Factory Functions\n// ============================================================================\n\n/**\n * Creates props for live regions\n * Live regions announce changes to screen readers\n *\n * @param options - Configuration options for the live region\n * @returns Accessibility props for the live region\n *\n * @example\n * ```tsx\n * <div {...createLiveRegion({ atomic: true, live: 'polite' })}>\n * {message}\n * </div>\n * ```\n */\nexport function createLiveRegion(\n options: LiveRegionOptions = {}\n): LiveRegionProps {\n const {\n atomic = false,\n relevant = 'additions',\n busy = false,\n live = 'polite',\n } = options;\n\n return {\n 'aria-live': live,\n 'aria-atomic': atomic ? 'true' : 'false',\n 'aria-relevant': relevant,\n 'aria-busy': busy ? 'true' : 'false',\n };\n}\n\n/**\n * Creates props for skip links\n * Skip links allow keyboard users to bypass navigation\n *\n * @param targetId - The ID of the target element to skip to\n * @returns Props for the skip link element\n *\n * @example\n * ```tsx\n * <a {...createSkipLinkProps('main-content')}>Skip to main content</a>\n * // ...\n * <main id=\"main-content\">...</main>\n * ```\n */\nexport function createSkipLinkProps(targetId: string): {\n href: string;\n tabIndex: number;\n} {\n return {\n href: `#${targetId}`,\n tabIndex: 0,\n };\n}\n\n/**\n * Creates props for elements that expand/collapse content\n *\n * @param expanded - Whether the content is currently expanded\n * @param controlsId - The ID of the element being controlled\n * @returns Accessibility props for the disclosure trigger\n *\n * @example\n * ```tsx\n * <button {...createDisclosureProps(isOpen, 'panel-id')} onClick={toggle}>\n * Toggle Panel\n * </button>\n * <div id=\"panel-id\" hidden={!isOpen}>Panel content</div>\n * ```\n */\nexport function createDisclosureProps(\n expanded: boolean,\n controlsId: string\n): DisclosureProps {\n return {\n 'aria-expanded': expanded ? 'true' : 'false',\n 'aria-controls': controlsId,\n };\n}\n\n/**\n * Creates props for toggle buttons with pressed state\n *\n * @param pressed - Whether the button is currently pressed\n * @returns Accessibility props for the toggle button\n *\n * @example\n * ```tsx\n * <button {...createPressedProps(isActive)} onClick={toggle}>\n * Toggle Feature\n * </button>\n * ```\n */\nexport function createPressedProps(pressed: boolean): PressedProps {\n return {\n 'aria-pressed': pressed ? 'true' : 'false',\n };\n}\n\n/**\n * Creates props for elements with selected state\n *\n * @param selected - Whether the element is currently selected\n * @returns Accessibility props for the selectable element\n *\n * @example\n * ```tsx\n * <li {...createSelectedProps(isSelected)} role=\"option\">\n * Option 1\n * </li>\n * ```\n */\nexport function createSelectedProps(selected: boolean): SelectedProps {\n return {\n 'aria-selected': selected ? 'true' : 'false',\n };\n}\n\n/**\n * Creates props for elements with checked state\n *\n * @param checked - Whether the element is checked (true), unchecked (false), or indeterminate ('mixed')\n * @returns Accessibility props for the checkable element\n *\n * @example\n * ```tsx\n * <div {...createCheckedProps(checked)} role=\"checkbox\" tabIndex={0}>\n * {checked ? '✓' : ''}\n * </div>\n * ```\n */\nexport function createCheckedProps(\n checked: boolean | 'mixed'\n): CheckedProps {\n return {\n 'aria-checked': typeof checked === 'string' ? checked : (checked ? 'true' : 'false'),\n };\n}\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Combines multiple accessibility props objects\n * Later props override earlier ones for the same keys\n *\n * @param props - Array of accessibility props to merge\n * @returns Combined accessibility props\n *\n * @example\n * ```tsx\n * <div {...mergeA11yProps(statusMessageProps, { 'aria-label': 'Status' })}>\n * {message}\n * </div>\n * ```\n */\nexport function mergeA11yProps(\n ...props: AccessibilityProps[]\n): AccessibilityProps {\n return Object.assign({}, ...props);\n}\n\n/**\n * Creates props for a dialog/modal trigger\n *\n * @param dialogId - The ID of the dialog element\n * @param isOpen - Whether the dialog is currently open\n * @returns Accessibility props for the dialog trigger\n *\n * @example\n * ```tsx\n * <button {...createDialogTriggerProps('my-dialog', isOpen)}>\n * Open Dialog\n * </button>\n * ```\n */\nexport function createDialogTriggerProps(\n dialogId: string,\n isOpen: boolean\n): AccessibilityProps {\n return {\n 'aria-haspopup': 'dialog',\n 'aria-controls': dialogId,\n 'aria-expanded': isOpen ? 'true' : 'false',\n };\n}\n\n/**\n * Creates props for a required form field\n *\n * @param required - Whether the field is required\n * @param invalid - Whether the field value is invalid\n * @returns Accessibility props for the form field\n *\n * @example\n * ```tsx\n * <input {...createFormFieldProps(true, hasError)} />\n * ```\n */\nexport function createFormFieldProps(\n required: boolean,\n invalid: boolean = false\n): AccessibilityProps {\n const props: AccessibilityProps = {\n 'aria-required': required ? 'true' : 'false',\n };\n \n if (invalid) {\n props['aria-invalid'] = 'true';\n }\n \n return props;\n}\n\n/**\n * Creates props for describing an element with another element\n *\n * @param describedById - The ID of the element that describes this element\n * @returns Accessibility props with aria-describedby\n *\n * @example\n * ```tsx\n * <input {...createDescribedByProps('error-message')} />\n * <span id=\"error-message\">This field is required</span>\n * ```\n */\nexport function createDescribedByProps(\n describedById: string\n): AccessibilityProps {\n return {\n 'aria-describedby': describedById,\n };\n}\n\n/**\n * Creates props for labeling an element with another element\n *\n * @param labelledById - The ID of the element that labels this element\n * @returns Accessibility props with aria-labelledby\n *\n * @example\n * ```tsx\n * <div {...createLabelledByProps('panel-title')} role=\"region\">\n * <h2 id=\"panel-title\">Panel Title</h2>\n * Panel content\n * </div>\n * ```\n */\nexport function createLabelledByProps(\n labelledById: string\n): AccessibilityProps {\n return {\n 'aria-labelledby': labelledById,\n };\n}\n"]} |
+4
-4
@@ -111,3 +111,3 @@ /** | ||
| */ | ||
| type CSSProperties = Record<string, string | number | undefined>; | ||
| type A11yCSSProperties = Record<string, string | number | undefined>; | ||
| /** | ||
@@ -122,3 +122,3 @@ * CSS styles for screen-reader-only content | ||
| */ | ||
| declare const srOnly: CSSProperties; | ||
| declare const srOnly: A11yCSSProperties; | ||
| /** | ||
@@ -133,3 +133,3 @@ * CSS styles for making hidden content visible when focused | ||
| */ | ||
| declare const srOnlyFocusable: CSSProperties; | ||
| declare const srOnlyFocusable: A11yCSSProperties; | ||
| /** | ||
@@ -335,2 +335,2 @@ * Props for decorative elements that should be hidden from screen readers | ||
| export { type AccessibilityProps, type CSSProperties, type CheckedProps, type DisclosureProps, type LiveRegionOptions, type LiveRegionProps, type PressedProps, type SelectedProps, alertMessageProps, createCheckedProps, createDescribedByProps, createDialogTriggerProps, createDisclosureProps, createFormFieldProps, createLabelledByProps, createLiveRegion, createPressedProps, createSelectedProps, createSkipLinkProps, decorative, disabledProps, mergeA11yProps, srOnly, srOnlyFocusable, statusMessageProps }; | ||
| export { type A11yCSSProperties, type AccessibilityProps, type CheckedProps, type DisclosureProps, type LiveRegionOptions, type LiveRegionProps, type PressedProps, type SelectedProps, alertMessageProps, createCheckedProps, createDescribedByProps, createDialogTriggerProps, createDisclosureProps, createFormFieldProps, createLabelledByProps, createLiveRegion, createPressedProps, createSelectedProps, createSkipLinkProps, decorative, disabledProps, mergeA11yProps, srOnly, srOnlyFocusable, statusMessageProps }; |
+4
-4
@@ -111,3 +111,3 @@ /** | ||
| */ | ||
| type CSSProperties = Record<string, string | number | undefined>; | ||
| type A11yCSSProperties = Record<string, string | number | undefined>; | ||
| /** | ||
@@ -122,3 +122,3 @@ * CSS styles for screen-reader-only content | ||
| */ | ||
| declare const srOnly: CSSProperties; | ||
| declare const srOnly: A11yCSSProperties; | ||
| /** | ||
@@ -133,3 +133,3 @@ * CSS styles for making hidden content visible when focused | ||
| */ | ||
| declare const srOnlyFocusable: CSSProperties; | ||
| declare const srOnlyFocusable: A11yCSSProperties; | ||
| /** | ||
@@ -335,2 +335,2 @@ * Props for decorative elements that should be hidden from screen readers | ||
| export { type AccessibilityProps, type CSSProperties, type CheckedProps, type DisclosureProps, type LiveRegionOptions, type LiveRegionProps, type PressedProps, type SelectedProps, alertMessageProps, createCheckedProps, createDescribedByProps, createDialogTriggerProps, createDisclosureProps, createFormFieldProps, createLabelledByProps, createLiveRegion, createPressedProps, createSelectedProps, createSkipLinkProps, decorative, disabledProps, mergeA11yProps, srOnly, srOnlyFocusable, statusMessageProps }; | ||
| export { type A11yCSSProperties, type AccessibilityProps, type CheckedProps, type DisclosureProps, type LiveRegionOptions, type LiveRegionProps, type PressedProps, type SelectedProps, alertMessageProps, createCheckedProps, createDescribedByProps, createDialogTriggerProps, createDisclosureProps, createFormFieldProps, createLabelledByProps, createLiveRegion, createPressedProps, createSelectedProps, createSkipLinkProps, decorative, disabledProps, mergeA11yProps, srOnly, srOnlyFocusable, statusMessageProps }; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * React Accessibility Utilities\n * Helper functions and hooks for building accessible React applications\n * @module @opensourceframework/react-a11y-utils\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Standard accessibility props that can be spread onto elements\n */\nexport interface AccessibilityProps {\n 'aria-activedescendant'?: string;\n 'aria-atomic'?: 'true' | 'false';\n 'aria-autocomplete'?: 'inline' | 'list' | 'both' | 'none';\n 'aria-busy'?: 'true' | 'false';\n 'aria-checked'?: 'true' | 'false' | 'mixed';\n 'aria-colcount'?: number;\n 'aria-colindex'?: number;\n 'aria-colspan'?: number;\n 'aria-controls'?: string;\n 'aria-current'?: 'page' | 'step' | 'location' | 'date' | 'time' | 'true' | 'false';\n 'aria-describedby'?: string;\n 'aria-details'?: string;\n 'aria-disabled'?: 'true' | 'false';\n 'aria-dropeffect'?: 'copy' | 'execute' | 'link' | 'move' | 'none' | 'popup';\n 'aria-errormessage'?: string;\n 'aria-expanded'?: 'true' | 'false';\n 'aria-flowto'?: string;\n 'aria-grabbed'?: 'true' | 'false';\n 'aria-haspopup'?: 'false' | 'true' | 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog';\n 'aria-hidden'?: 'true' | 'false';\n 'aria-invalid'?: 'true' | 'false' | 'grammar' | 'spelling';\n 'aria-keyshortcuts'?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'aria-level'?: number;\n 'aria-live'?: 'off' | 'polite' | 'assertive';\n 'aria-modal'?: 'true' | 'false';\n 'aria-multiline'?: 'true' | 'false';\n 'aria-multiselectable'?: 'true' | 'false';\n 'aria-orientation'?: 'horizontal' | 'vertical';\n 'aria-owns'?: string;\n 'aria-placeholder'?: string;\n 'aria-posinset'?: number;\n 'aria-pressed'?: 'true' | 'false' | 'mixed';\n 'aria-readonly'?: 'true' | 'false';\n 'aria-relevant'?: 'additions' | 'removals' | 'text' | 'all';\n 'aria-required'?: 'true' | 'false';\n 'aria-roledescription'?: string;\n 'aria-rowcount'?: number;\n 'aria-rowindex'?: number;\n 'aria-rowspan'?: number;\n 'aria-selected'?: 'true' | 'false';\n 'aria-setsize'?: number;\n 'aria-sort'?: 'ascending' | 'descending' | 'none' | 'other';\n 'aria-valuemax'?: number;\n 'aria-valuemin'?: number;\n 'aria-valuenow'?: number;\n 'aria-valuetext'?: string;\n role?: string;\n tabIndex?: number;\n}\n\n/**\n * Props for live region elements\n */\nexport interface LiveRegionProps extends AccessibilityProps {\n 'aria-live'?: 'off' | 'polite' | 'assertive';\n 'aria-atomic'?: 'true' | 'false';\n 'aria-relevant'?: 'additions' | 'removals' | 'text' | 'all';\n 'aria-busy'?: 'true' | 'false';\n}\n\n/**\n * Options for creating live region props\n */\nexport interface LiveRegionOptions {\n /** Whether the entire region should be announced (true) or just changes (false) */\n atomic?: boolean;\n /** What types of changes are relevant */\n relevant?: 'additions' | 'removals' | 'text' | 'all';\n /** Whether the region is currently being updated */\n busy?: boolean;\n /** How assertive the announcement should be */\n live?: 'polite' | 'assertive';\n}\n\n/**\n * Props for disclosure elements (expand/collapse)\n */\nexport interface DisclosureProps extends AccessibilityProps {\n 'aria-expanded': 'true' | 'false';\n 'aria-controls': string;\n}\n\n/**\n * Props for toggle buttons with pressed state\n */\nexport interface PressedProps extends AccessibilityProps {\n 'aria-pressed': 'true' | 'false' | 'mixed';\n}\n\n/**\n * Props for selectable elements\n */\nexport interface SelectedProps extends AccessibilityProps {\n 'aria-selected': 'true' | 'false';\n}\n\n/**\n * Props for checkable elements\n */\nexport interface CheckedProps extends AccessibilityProps {\n 'aria-checked': 'true' | 'false' | 'mixed';\n}\n\n/**\n * CSS Properties type for style objects\n */\nexport type CSSProperties = Record<string, string | number | undefined>;\n\n// ============================================================================\n// Screen Reader Utilities\n// ============================================================================\n\n/**\n * CSS styles for screen-reader-only content\n * Elements with these styles are visually hidden but accessible to screen readers\n *\n * @example\n * ```tsx\n * <span style={srOnly}>Skip to main content</span>\n * ```\n */\nexport const srOnly: CSSProperties = {\n position: 'absolute',\n width: '1px',\n height: '1px',\n padding: '0',\n margin: '-1px',\n overflow: 'hidden',\n clip: 'rect(0, 0, 0, 0)',\n whiteSpace: 'nowrap',\n borderWidth: '0',\n};\n\n/**\n * CSS styles for making hidden content visible when focused\n * Use for skip links that should appear on focus\n *\n * @example\n * ```tsx\n * <a href=\"#main\" style={srOnlyFocusable}>Skip to main content</a>\n * ```\n */\nexport const srOnlyFocusable: CSSProperties = {\n position: 'absolute',\n width: 'auto',\n height: 'auto',\n padding: '1rem',\n margin: '0',\n overflow: 'visible',\n clip: 'auto',\n whiteSpace: 'normal',\n};\n\n// ============================================================================\n// ARIA Props Factories\n// ============================================================================\n\n/**\n * Props for decorative elements that should be hidden from screen readers\n *\n * @example\n * ```tsx\n * <img src=\"decoration.png\" alt=\"\" {...decorative} />\n * ```\n */\nexport const decorative: AccessibilityProps = {\n 'aria-hidden': 'true',\n};\n\n/**\n * Props for disabled interactive elements\n * Provides proper accessibility for disabled elements\n *\n * @example\n * ```tsx\n * <button {...disabledProps} onClick={handleClick}>Disabled</button>\n * ```\n */\nexport const disabledProps: AccessibilityProps = {\n 'aria-disabled': 'true',\n tabIndex: -1,\n};\n\n/**\n * Props for status messages (polite announcements)\n *\n * @example\n * ```tsx\n * <div {...statusMessageProps}>Changes saved successfully</div>\n * ```\n */\nexport const statusMessageProps: AccessibilityProps = {\n role: 'status',\n 'aria-live': 'polite',\n};\n\n/**\n * Props for alert messages (assertive announcements)\n *\n * @example\n * ```tsx\n * <div {...alertMessageProps}>Error: Please fill in all required fields</div>\n * ```\n */\nexport const alertMessageProps: AccessibilityProps = {\n role: 'alert',\n 'aria-live': 'assertive',\n};\n\n// ============================================================================\n// Factory Functions\n// ============================================================================\n\n/**\n * Creates props for live regions\n * Live regions announce changes to screen readers\n *\n * @param options - Configuration options for the live region\n * @returns Accessibility props for the live region\n *\n * @example\n * ```tsx\n * <div {...createLiveRegion({ atomic: true, live: 'polite' })}>\n * {message}\n * </div>\n * ```\n */\nexport function createLiveRegion(\n options: LiveRegionOptions = {}\n): LiveRegionProps {\n const {\n atomic = false,\n relevant = 'additions',\n busy = false,\n live = 'polite',\n } = options;\n\n return {\n 'aria-live': live,\n 'aria-atomic': atomic ? 'true' : 'false',\n 'aria-relevant': relevant,\n 'aria-busy': busy ? 'true' : 'false',\n };\n}\n\n/**\n * Creates props for skip links\n * Skip links allow keyboard users to bypass navigation\n *\n * @param targetId - The ID of the target element to skip to\n * @returns Props for the skip link element\n *\n * @example\n * ```tsx\n * <a {...createSkipLinkProps('main-content')}>Skip to main content</a>\n * // ...\n * <main id=\"main-content\">...</main>\n * ```\n */\nexport function createSkipLinkProps(targetId: string): {\n href: string;\n tabIndex: number;\n} {\n return {\n href: `#${targetId}`,\n tabIndex: 0,\n };\n}\n\n/**\n * Creates props for elements that expand/collapse content\n *\n * @param expanded - Whether the content is currently expanded\n * @param controlsId - The ID of the element being controlled\n * @returns Accessibility props for the disclosure trigger\n *\n * @example\n * ```tsx\n * <button {...createDisclosureProps(isOpen, 'panel-id')} onClick={toggle}>\n * Toggle Panel\n * </button>\n * <div id=\"panel-id\" hidden={!isOpen}>Panel content</div>\n * ```\n */\nexport function createDisclosureProps(\n expanded: boolean,\n controlsId: string\n): DisclosureProps {\n return {\n 'aria-expanded': expanded ? 'true' : 'false',\n 'aria-controls': controlsId,\n };\n}\n\n/**\n * Creates props for toggle buttons with pressed state\n *\n * @param pressed - Whether the button is currently pressed\n * @returns Accessibility props for the toggle button\n *\n * @example\n * ```tsx\n * <button {...createPressedProps(isActive)} onClick={toggle}>\n * Toggle Feature\n * </button>\n * ```\n */\nexport function createPressedProps(pressed: boolean): PressedProps {\n return {\n 'aria-pressed': pressed ? 'true' : 'false',\n };\n}\n\n/**\n * Creates props for elements with selected state\n *\n * @param selected - Whether the element is currently selected\n * @returns Accessibility props for the selectable element\n *\n * @example\n * ```tsx\n * <li {...createSelectedProps(isSelected)} role=\"option\">\n * Option 1\n * </li>\n * ```\n */\nexport function createSelectedProps(selected: boolean): SelectedProps {\n return {\n 'aria-selected': selected ? 'true' : 'false',\n };\n}\n\n/**\n * Creates props for elements with checked state\n *\n * @param checked - Whether the element is checked (true), unchecked (false), or indeterminate ('mixed')\n * @returns Accessibility props for the checkable element\n *\n * @example\n * ```tsx\n * <div {...createCheckedProps(checked)} role=\"checkbox\" tabIndex={0}>\n * {checked ? '✓' : ''}\n * </div>\n * ```\n */\nexport function createCheckedProps(\n checked: boolean | 'mixed'\n): CheckedProps {\n return {\n 'aria-checked': typeof checked === 'string' ? checked : (checked ? 'true' : 'false'),\n };\n}\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Combines multiple accessibility props objects\n * Later props override earlier ones for the same keys\n *\n * @param props - Array of accessibility props to merge\n * @returns Combined accessibility props\n *\n * @example\n * ```tsx\n * <div {...mergeA11yProps(statusMessageProps, { 'aria-label': 'Status' })}>\n * {message}\n * </div>\n * ```\n */\nexport function mergeA11yProps(\n ...props: AccessibilityProps[]\n): AccessibilityProps {\n return Object.assign({}, ...props);\n}\n\n/**\n * Creates props for a dialog/modal trigger\n *\n * @param dialogId - The ID of the dialog element\n * @param isOpen - Whether the dialog is currently open\n * @returns Accessibility props for the dialog trigger\n *\n * @example\n * ```tsx\n * <button {...createDialogTriggerProps('my-dialog', isOpen)}>\n * Open Dialog\n * </button>\n * ```\n */\nexport function createDialogTriggerProps(\n dialogId: string,\n isOpen: boolean\n): AccessibilityProps {\n return {\n 'aria-haspopup': 'dialog',\n 'aria-controls': dialogId,\n 'aria-expanded': isOpen ? 'true' : 'false',\n };\n}\n\n/**\n * Creates props for a required form field\n *\n * @param required - Whether the field is required\n * @param invalid - Whether the field value is invalid\n * @returns Accessibility props for the form field\n *\n * @example\n * ```tsx\n * <input {...createFormFieldProps(true, hasError)} />\n * ```\n */\nexport function createFormFieldProps(\n required: boolean,\n invalid: boolean = false\n): AccessibilityProps {\n const props: AccessibilityProps = {\n 'aria-required': required ? 'true' : 'false',\n };\n \n if (invalid) {\n props['aria-invalid'] = 'true';\n }\n \n return props;\n}\n\n/**\n * Creates props for describing an element with another element\n *\n * @param describedById - The ID of the element that describes this element\n * @returns Accessibility props with aria-describedby\n *\n * @example\n * ```tsx\n * <input {...createDescribedByProps('error-message')} />\n * <span id=\"error-message\">This field is required</span>\n * ```\n */\nexport function createDescribedByProps(\n describedById: string\n): AccessibilityProps {\n return {\n 'aria-describedby': describedById,\n };\n}\n\n/**\n * Creates props for labeling an element with another element\n *\n * @param labelledById - The ID of the element that labels this element\n * @returns Accessibility props with aria-labelledby\n *\n * @example\n * ```tsx\n * <div {...createLabelledByProps('panel-title')} role=\"region\">\n * <h2 id=\"panel-title\">Panel Title</h2>\n * Panel content\n * </div>\n * ```\n */\nexport function createLabelledByProps(\n labelledById: string\n): AccessibilityProps {\n return {\n 'aria-labelledby': labelledById,\n };\n}\n"]} | ||
| {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;AAyIO,IAAM,MAAA,GAA4B;AAAA,EACvC,QAAA,EAAU,UAAA;AAAA,EACV,KAAA,EAAO,KAAA;AAAA,EACP,MAAA,EAAQ,KAAA;AAAA,EACR,OAAA,EAAS,GAAA;AAAA,EACT,MAAA,EAAQ,MAAA;AAAA,EACR,QAAA,EAAU,QAAA;AAAA,EACV,IAAA,EAAM,kBAAA;AAAA,EACN,UAAA,EAAY,QAAA;AAAA,EACZ,WAAA,EAAa;AACf;AAWO,IAAM,eAAA,GAAqC;AAAA,EAChD,QAAA,EAAU,UAAA;AAAA,EACV,KAAA,EAAO,MAAA;AAAA,EACP,MAAA,EAAQ,MAAA;AAAA,EACR,OAAA,EAAS,MAAA;AAAA,EACT,MAAA,EAAQ,GAAA;AAAA,EACR,QAAA,EAAU,SAAA;AAAA,EACV,IAAA,EAAM,MAAA;AAAA,EACN,UAAA,EAAY;AACd;AAcO,IAAM,UAAA,GAAiC;AAAA,EAC5C,aAAA,EAAe;AACjB;AAWO,IAAM,aAAA,GAAoC;AAAA,EAC/C,eAAA,EAAiB,MAAA;AAAA,EACjB,QAAA,EAAU;AACZ;AAUO,IAAM,kBAAA,GAAyC;AAAA,EACpD,IAAA,EAAM,QAAA;AAAA,EACN,WAAA,EAAa;AACf;AAUO,IAAM,iBAAA,GAAwC;AAAA,EACnD,IAAA,EAAM,OAAA;AAAA,EACN,WAAA,EAAa;AACf;AAoBO,SAAS,gBAAA,CACd,OAAA,GAA6B,EAAC,EACb;AACjB,EAAA,MAAM;AAAA,IACJ,MAAA,GAAS,KAAA;AAAA,IACT,QAAA,GAAW,WAAA;AAAA,IACX,IAAA,GAAO,KAAA;AAAA,IACP,IAAA,GAAO;AAAA,GACT,GAAI,OAAA;AAEJ,EAAA,OAAO;AAAA,IACL,WAAA,EAAa,IAAA;AAAA,IACb,aAAA,EAAe,SAAS,MAAA,GAAS,OAAA;AAAA,IACjC,eAAA,EAAiB,QAAA;AAAA,IACjB,WAAA,EAAa,OAAO,MAAA,GAAS;AAAA,GAC/B;AACF;AAgBO,SAAS,oBAAoB,QAAA,EAGlC;AACA,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,IAAI,QAAQ,CAAA,CAAA;AAAA,IAClB,QAAA,EAAU;AAAA,GACZ;AACF;AAiBO,SAAS,qBAAA,CACd,UACA,UAAA,EACiB;AACjB,EAAA,OAAO;AAAA,IACL,eAAA,EAAiB,WAAW,MAAA,GAAS,OAAA;AAAA,IACrC,eAAA,EAAiB;AAAA,GACnB;AACF;AAeO,SAAS,mBAAmB,OAAA,EAAgC;AACjE,EAAA,OAAO;AAAA,IACL,cAAA,EAAgB,UAAU,MAAA,GAAS;AAAA,GACrC;AACF;AAeO,SAAS,oBAAoB,QAAA,EAAkC;AACpE,EAAA,OAAO;AAAA,IACL,eAAA,EAAiB,WAAW,MAAA,GAAS;AAAA,GACvC;AACF;AAeO,SAAS,mBACd,OAAA,EACc;AACd,EAAA,OAAO;AAAA,IACL,gBAAgB,OAAO,OAAA,KAAY,QAAA,GAAW,OAAA,GAAW,UAAU,MAAA,GAAS;AAAA,GAC9E;AACF;AAoBO,SAAS,kBACX,KAAA,EACiB;AACpB,EAAA,OAAO,MAAA,CAAO,MAAA,CAAO,EAAC,EAAG,GAAG,KAAK,CAAA;AACnC;AAgBO,SAAS,wBAAA,CACd,UACA,MAAA,EACoB;AACpB,EAAA,OAAO;AAAA,IACL,eAAA,EAAiB,QAAA;AAAA,IACjB,eAAA,EAAiB,QAAA;AAAA,IACjB,eAAA,EAAiB,SAAS,MAAA,GAAS;AAAA,GACrC;AACF;AAcO,SAAS,oBAAA,CACd,QAAA,EACA,OAAA,GAAmB,KAAA,EACC;AACpB,EAAA,MAAM,KAAA,GAA4B;AAAA,IAChC,eAAA,EAAiB,WAAW,MAAA,GAAS;AAAA,GACvC;AAEA,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,KAAA,CAAM,cAAc,CAAA,GAAI,MAAA;AAAA,EAC1B;AAEA,EAAA,OAAO,KAAA;AACT;AAcO,SAAS,uBACd,aAAA,EACoB;AACpB,EAAA,OAAO;AAAA,IACL,kBAAA,EAAoB;AAAA,GACtB;AACF;AAgBO,SAAS,sBACd,YAAA,EACoB;AACpB,EAAA,OAAO;AAAA,IACL,iBAAA,EAAmB;AAAA,GACrB;AACF","file":"index.js","sourcesContent":["/**\n * React Accessibility Utilities\n * Helper functions and hooks for building accessible React applications\n * @module @opensourceframework/react-a11y-utils\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Standard accessibility props that can be spread onto elements\n */\nexport interface AccessibilityProps {\n 'aria-activedescendant'?: string;\n 'aria-atomic'?: 'true' | 'false';\n 'aria-autocomplete'?: 'inline' | 'list' | 'both' | 'none';\n 'aria-busy'?: 'true' | 'false';\n 'aria-checked'?: 'true' | 'false' | 'mixed';\n 'aria-colcount'?: number;\n 'aria-colindex'?: number;\n 'aria-colspan'?: number;\n 'aria-controls'?: string;\n 'aria-current'?: 'page' | 'step' | 'location' | 'date' | 'time' | 'true' | 'false';\n 'aria-describedby'?: string;\n 'aria-details'?: string;\n 'aria-disabled'?: 'true' | 'false';\n 'aria-dropeffect'?: 'copy' | 'execute' | 'link' | 'move' | 'none' | 'popup';\n 'aria-errormessage'?: string;\n 'aria-expanded'?: 'true' | 'false';\n 'aria-flowto'?: string;\n 'aria-grabbed'?: 'true' | 'false';\n 'aria-haspopup'?: 'false' | 'true' | 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog';\n 'aria-hidden'?: 'true' | 'false';\n 'aria-invalid'?: 'true' | 'false' | 'grammar' | 'spelling';\n 'aria-keyshortcuts'?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'aria-level'?: number;\n 'aria-live'?: 'off' | 'polite' | 'assertive';\n 'aria-modal'?: 'true' | 'false';\n 'aria-multiline'?: 'true' | 'false';\n 'aria-multiselectable'?: 'true' | 'false';\n 'aria-orientation'?: 'horizontal' | 'vertical';\n 'aria-owns'?: string;\n 'aria-placeholder'?: string;\n 'aria-posinset'?: number;\n 'aria-pressed'?: 'true' | 'false' | 'mixed';\n 'aria-readonly'?: 'true' | 'false';\n 'aria-relevant'?: 'additions' | 'removals' | 'text' | 'all';\n 'aria-required'?: 'true' | 'false';\n 'aria-roledescription'?: string;\n 'aria-rowcount'?: number;\n 'aria-rowindex'?: number;\n 'aria-rowspan'?: number;\n 'aria-selected'?: 'true' | 'false';\n 'aria-setsize'?: number;\n 'aria-sort'?: 'ascending' | 'descending' | 'none' | 'other';\n 'aria-valuemax'?: number;\n 'aria-valuemin'?: number;\n 'aria-valuenow'?: number;\n 'aria-valuetext'?: string;\n role?: string;\n tabIndex?: number;\n}\n\n/**\n * Props for live region elements\n */\nexport interface LiveRegionProps extends AccessibilityProps {\n 'aria-live'?: 'off' | 'polite' | 'assertive';\n 'aria-atomic'?: 'true' | 'false';\n 'aria-relevant'?: 'additions' | 'removals' | 'text' | 'all';\n 'aria-busy'?: 'true' | 'false';\n}\n\n/**\n * Options for creating live region props\n */\nexport interface LiveRegionOptions {\n /** Whether the entire region should be announced (true) or just changes (false) */\n atomic?: boolean;\n /** What types of changes are relevant */\n relevant?: 'additions' | 'removals' | 'text' | 'all';\n /** Whether the region is currently being updated */\n busy?: boolean;\n /** How assertive the announcement should be */\n live?: 'polite' | 'assertive';\n}\n\n/**\n * Props for disclosure elements (expand/collapse)\n */\nexport interface DisclosureProps extends AccessibilityProps {\n 'aria-expanded': 'true' | 'false';\n 'aria-controls': string;\n}\n\n/**\n * Props for toggle buttons with pressed state\n */\nexport interface PressedProps extends AccessibilityProps {\n 'aria-pressed': 'true' | 'false' | 'mixed';\n}\n\n/**\n * Props for selectable elements\n */\nexport interface SelectedProps extends AccessibilityProps {\n 'aria-selected': 'true' | 'false';\n}\n\n/**\n * Props for checkable elements\n */\nexport interface CheckedProps extends AccessibilityProps {\n 'aria-checked': 'true' | 'false' | 'mixed';\n}\n\n/**\n * CSS Properties type for style objects\n */\nexport type A11yCSSProperties = Record<string, string | number | undefined>;\n\n// ============================================================================\n// Screen Reader Utilities\n// ============================================================================\n\n/**\n * CSS styles for screen-reader-only content\n * Elements with these styles are visually hidden but accessible to screen readers\n *\n * @example\n * ```tsx\n * <span style={srOnly}>Skip to main content</span>\n * ```\n */\nexport const srOnly: A11yCSSProperties = {\n position: 'absolute',\n width: '1px',\n height: '1px',\n padding: '0',\n margin: '-1px',\n overflow: 'hidden',\n clip: 'rect(0, 0, 0, 0)',\n whiteSpace: 'nowrap',\n borderWidth: '0',\n};\n\n/**\n * CSS styles for making hidden content visible when focused\n * Use for skip links that should appear on focus\n *\n * @example\n * ```tsx\n * <a href=\"#main\" style={srOnlyFocusable}>Skip to main content</a>\n * ```\n */\nexport const srOnlyFocusable: A11yCSSProperties = {\n position: 'absolute',\n width: 'auto',\n height: 'auto',\n padding: '1rem',\n margin: '0',\n overflow: 'visible',\n clip: 'auto',\n whiteSpace: 'normal',\n};\n\n// ============================================================================\n// ARIA Props Factories\n// ============================================================================\n\n/**\n * Props for decorative elements that should be hidden from screen readers\n *\n * @example\n * ```tsx\n * <img src=\"decoration.png\" alt=\"\" {...decorative} />\n * ```\n */\nexport const decorative: AccessibilityProps = {\n 'aria-hidden': 'true',\n};\n\n/**\n * Props for disabled interactive elements\n * Provides proper accessibility for disabled elements\n *\n * @example\n * ```tsx\n * <button {...disabledProps} onClick={handleClick}>Disabled</button>\n * ```\n */\nexport const disabledProps: AccessibilityProps = {\n 'aria-disabled': 'true',\n tabIndex: -1,\n};\n\n/**\n * Props for status messages (polite announcements)\n *\n * @example\n * ```tsx\n * <div {...statusMessageProps}>Changes saved successfully</div>\n * ```\n */\nexport const statusMessageProps: AccessibilityProps = {\n role: 'status',\n 'aria-live': 'polite',\n};\n\n/**\n * Props for alert messages (assertive announcements)\n *\n * @example\n * ```tsx\n * <div {...alertMessageProps}>Error: Please fill in all required fields</div>\n * ```\n */\nexport const alertMessageProps: AccessibilityProps = {\n role: 'alert',\n 'aria-live': 'assertive',\n};\n\n// ============================================================================\n// Factory Functions\n// ============================================================================\n\n/**\n * Creates props for live regions\n * Live regions announce changes to screen readers\n *\n * @param options - Configuration options for the live region\n * @returns Accessibility props for the live region\n *\n * @example\n * ```tsx\n * <div {...createLiveRegion({ atomic: true, live: 'polite' })}>\n * {message}\n * </div>\n * ```\n */\nexport function createLiveRegion(\n options: LiveRegionOptions = {}\n): LiveRegionProps {\n const {\n atomic = false,\n relevant = 'additions',\n busy = false,\n live = 'polite',\n } = options;\n\n return {\n 'aria-live': live,\n 'aria-atomic': atomic ? 'true' : 'false',\n 'aria-relevant': relevant,\n 'aria-busy': busy ? 'true' : 'false',\n };\n}\n\n/**\n * Creates props for skip links\n * Skip links allow keyboard users to bypass navigation\n *\n * @param targetId - The ID of the target element to skip to\n * @returns Props for the skip link element\n *\n * @example\n * ```tsx\n * <a {...createSkipLinkProps('main-content')}>Skip to main content</a>\n * // ...\n * <main id=\"main-content\">...</main>\n * ```\n */\nexport function createSkipLinkProps(targetId: string): {\n href: string;\n tabIndex: number;\n} {\n return {\n href: `#${targetId}`,\n tabIndex: 0,\n };\n}\n\n/**\n * Creates props for elements that expand/collapse content\n *\n * @param expanded - Whether the content is currently expanded\n * @param controlsId - The ID of the element being controlled\n * @returns Accessibility props for the disclosure trigger\n *\n * @example\n * ```tsx\n * <button {...createDisclosureProps(isOpen, 'panel-id')} onClick={toggle}>\n * Toggle Panel\n * </button>\n * <div id=\"panel-id\" hidden={!isOpen}>Panel content</div>\n * ```\n */\nexport function createDisclosureProps(\n expanded: boolean,\n controlsId: string\n): DisclosureProps {\n return {\n 'aria-expanded': expanded ? 'true' : 'false',\n 'aria-controls': controlsId,\n };\n}\n\n/**\n * Creates props for toggle buttons with pressed state\n *\n * @param pressed - Whether the button is currently pressed\n * @returns Accessibility props for the toggle button\n *\n * @example\n * ```tsx\n * <button {...createPressedProps(isActive)} onClick={toggle}>\n * Toggle Feature\n * </button>\n * ```\n */\nexport function createPressedProps(pressed: boolean): PressedProps {\n return {\n 'aria-pressed': pressed ? 'true' : 'false',\n };\n}\n\n/**\n * Creates props for elements with selected state\n *\n * @param selected - Whether the element is currently selected\n * @returns Accessibility props for the selectable element\n *\n * @example\n * ```tsx\n * <li {...createSelectedProps(isSelected)} role=\"option\">\n * Option 1\n * </li>\n * ```\n */\nexport function createSelectedProps(selected: boolean): SelectedProps {\n return {\n 'aria-selected': selected ? 'true' : 'false',\n };\n}\n\n/**\n * Creates props for elements with checked state\n *\n * @param checked - Whether the element is checked (true), unchecked (false), or indeterminate ('mixed')\n * @returns Accessibility props for the checkable element\n *\n * @example\n * ```tsx\n * <div {...createCheckedProps(checked)} role=\"checkbox\" tabIndex={0}>\n * {checked ? '✓' : ''}\n * </div>\n * ```\n */\nexport function createCheckedProps(\n checked: boolean | 'mixed'\n): CheckedProps {\n return {\n 'aria-checked': typeof checked === 'string' ? checked : (checked ? 'true' : 'false'),\n };\n}\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Combines multiple accessibility props objects\n * Later props override earlier ones for the same keys\n *\n * @param props - Array of accessibility props to merge\n * @returns Combined accessibility props\n *\n * @example\n * ```tsx\n * <div {...mergeA11yProps(statusMessageProps, { 'aria-label': 'Status' })}>\n * {message}\n * </div>\n * ```\n */\nexport function mergeA11yProps(\n ...props: AccessibilityProps[]\n): AccessibilityProps {\n return Object.assign({}, ...props);\n}\n\n/**\n * Creates props for a dialog/modal trigger\n *\n * @param dialogId - The ID of the dialog element\n * @param isOpen - Whether the dialog is currently open\n * @returns Accessibility props for the dialog trigger\n *\n * @example\n * ```tsx\n * <button {...createDialogTriggerProps('my-dialog', isOpen)}>\n * Open Dialog\n * </button>\n * ```\n */\nexport function createDialogTriggerProps(\n dialogId: string,\n isOpen: boolean\n): AccessibilityProps {\n return {\n 'aria-haspopup': 'dialog',\n 'aria-controls': dialogId,\n 'aria-expanded': isOpen ? 'true' : 'false',\n };\n}\n\n/**\n * Creates props for a required form field\n *\n * @param required - Whether the field is required\n * @param invalid - Whether the field value is invalid\n * @returns Accessibility props for the form field\n *\n * @example\n * ```tsx\n * <input {...createFormFieldProps(true, hasError)} />\n * ```\n */\nexport function createFormFieldProps(\n required: boolean,\n invalid: boolean = false\n): AccessibilityProps {\n const props: AccessibilityProps = {\n 'aria-required': required ? 'true' : 'false',\n };\n \n if (invalid) {\n props['aria-invalid'] = 'true';\n }\n \n return props;\n}\n\n/**\n * Creates props for describing an element with another element\n *\n * @param describedById - The ID of the element that describes this element\n * @returns Accessibility props with aria-describedby\n *\n * @example\n * ```tsx\n * <input {...createDescribedByProps('error-message')} />\n * <span id=\"error-message\">This field is required</span>\n * ```\n */\nexport function createDescribedByProps(\n describedById: string\n): AccessibilityProps {\n return {\n 'aria-describedby': describedById,\n };\n}\n\n/**\n * Creates props for labeling an element with another element\n *\n * @param labelledById - The ID of the element that labels this element\n * @returns Accessibility props with aria-labelledby\n *\n * @example\n * ```tsx\n * <div {...createLabelledByProps('panel-title')} role=\"region\">\n * <h2 id=\"panel-title\">Panel Title</h2>\n * Panel content\n * </div>\n * ```\n */\nexport function createLabelledByProps(\n labelledById: string\n): AccessibilityProps {\n return {\n 'aria-labelledby': labelledById,\n };\n}\n"]} |
+22
-14
| { | ||
| "name": "@opensourceframework/react-a11y-utils", | ||
| "version": "0.1.0", | ||
| "version": "0.1.1", | ||
| "description": "React accessibility utility functions and hooks for building accessible user interfaces", | ||
@@ -40,2 +40,12 @@ "keywords": [ | ||
| ], | ||
| "scripts": { | ||
| "build": "tsup", | ||
| "dev": "tsup --watch", | ||
| "lint": "eslint src/", | ||
| "typecheck": "tsc --noEmit", | ||
| "test": "vitest run", | ||
| "test:watch": "vitest", | ||
| "test:coverage": "vitest run --coverage", | ||
| "clean": "rm -rf dist coverage node_modules" | ||
| }, | ||
| "devDependencies": { | ||
@@ -52,24 +62,22 @@ "@types/node": "^22.0.0", | ||
| }, | ||
| "peerDependenciesMeta": { | ||
| "react": { | ||
| "optional": true | ||
| } | ||
| }, | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "git+https://github.com/opensourceframework/opensourceframework.git", | ||
| "url": "git+https://github.com/riceharvest/opensourceframework.git", | ||
| "directory": "packages/react-a11y-utils" | ||
| }, | ||
| "bugs": { | ||
| "url": "https://github.com/opensourceframework/opensourceframework/issues?q=is%3Aissue+is%3Aopen+react-a11y-utils" | ||
| "url": "https://github.com/riceharvest/opensourceframework/issues?q=is%3Aissue+is%3Aopen+react-a11y-utils" | ||
| }, | ||
| "homepage": "https://github.com/opensourceframework/opensourceframework/tree/main/packages/react-a11y-utils#readme", | ||
| "homepage": "https://github.com/riceharvest/opensourceframework/tree/main/packages/react-a11y-utils#readme", | ||
| "publishConfig": { | ||
| "access": "public" | ||
| }, | ||
| "scripts": { | ||
| "build": "tsup", | ||
| "dev": "tsup --watch", | ||
| "lint": "eslint src/", | ||
| "typecheck": "tsc --noEmit", | ||
| "test": "vitest run", | ||
| "test:watch": "vitest", | ||
| "test:coverage": "vitest run --coverage", | ||
| "clean": "rm -rf dist coverage node_modules" | ||
| "engines": { | ||
| "node": ">=18.0.0" | ||
| } | ||
| } | ||
| } |
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
70244
0.98%0
-100%1
-50%