All files / disclosure disclosure.ts

100% Statements 67/67
100% Branches 21/21
100% Functions 13/13
100% Lines 67/67

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 681x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 4x 4x 4x 4x 4x 11x 11x 11x 11x 20x 20x 11x 11x 11x 9x 9x 11x 11x 11x 5x 5x 11x 20x 20x 11x 20x 20x 11x 20x 20x 11x 20x 20x 11x 20x 20x 11x 11x 11x  
import { JSX, createUniqueId, mergeProps } from "solid-js";
import { access } from "@solid-primitives/utils";
import { createControllableBooleanSignal } from "@solid-aria/utils";
 
import type { AriaDisclosure, DisclosureArguments, DisclosureDefaultArguments } from "./types";
 
const defaultArgs: DisclosureDefaultArguments = {
	isButtonElement: true,
	defaultVisible: false
};
 
/**
 * Creates a Diclosure bindings according to the WAI-ARIA specification.
 *
 * @link https://www.w3.org/WAI/ARIA/apg/patterns/disclosure
 */
export function createDisclosure(args?: DisclosureArguments): AriaDisclosure {
	const local = mergeProps(defaultArgs, args);
 
	const [isVisible, setVisible] = createControllableBooleanSignal({
		value: () => access(local.isVisible),
		defaultValue: () => !!access(local.defaultVisible),
		onChange: (value) => local.onVisibilityChange?.(value)
	});
 
	const ariaControls = createUniqueId();
 
	const onKeyDown: JSX.EventHandlerUnion<HTMLElement, KeyboardEvent> = (event) => {
		if (event.key === "Enter" || event.key === " ") {
			event.preventDefault();
			setVisible(!isVisible());
		}
	};
 
	return {
		state: {
			get isVisible() {
				return isVisible();
			}
		},
		contentProps: {
			get id() {
				return local.id ?? ariaControls;
			}
		},
		toggleProps: {
			onClick() {
				setVisible(!isVisible());
			},
			get onKeyDown() {
				return onKeyDown;
			},
			get tabindex() {
				return !local.isButtonElement ? 0 : undefined;
			},
			get "aria-controls"() {
				return "id" in local ? local.id : ariaControls;
			},
			get "aria-expanded"() {
				return isVisible();
			},
			get role() {
				return !local.isButtonElement ? "button" : undefined;
			}
		}
	};
}