one-click-accessibility/modules/scanner/assets/js/components/heading-structure/heading-tree.js
VasylD ad2174ffe3
[APP-1792] Add headings structure (#406)
* New: Add the heading structure components [APP-1792] (#391)

* New: Add the new rules [APP-1792]

* New: Add the BE integration [APP-1792]

* Fix: Fix QA issues [APP-1792]

* merge latest dev

* merge latest dev

* merge latest dev

* merge latest dev

* merge latest dev

* merge latest dev

* add reset to initial

---------

Co-authored-by: Pavlo Kniazevych <139438463+pkniazevych@users.noreply.github.com>
Co-authored-by: Kniazevych <pavlok@elementor.red>
2025-09-24 09:47:57 +02:00

72 lines
2.1 KiB
JavaScript

import HeadingStructureHeadingTreeList from '@ea11y-apps/scanner/components/heading-structure/heading-tree-list';
import HeadingStructureHeadingTreeListItem from '@ea11y-apps/scanner/components/heading-structure/heading-tree-list-item';
import HeadingStructureHeadingTreeLoader from '@ea11y-apps/scanner/components/heading-structure/heading-tree-loader';
import { useHeadingStructureContext } from '@ea11y-apps/scanner/context/heading-structure-context';
import { keyForNode } from '@ea11y-apps/scanner/utils/page-headings';
import { useEffect, useCallback } from '@wordpress/element';
const HeadingStructureHeadingTree = () => {
const {
isLoading,
expandedKey,
pageHeadings,
updateHeadingsTree,
toggleHeading,
} = useHeadingStructureContext();
useEffect(() => {
updateHeadingsTree();
}, []);
/**
* @param {import('../../types/heading').Ea11yHeading[]} headings
* @param {number | false} nestedId
* @return {JSX.Element} React element to render.
*/
const renderPageHeadings = useCallback(
(headings, nestedId) => {
const children = headings.flatMap((heading, i) => {
const key = keyForNode(heading.node);
const item = (
<HeadingStructureHeadingTreeListItem
key={key}
id={key}
level={heading.level}
content={heading.content}
node={heading.node}
status={heading.status}
violation={heading.violationCode}
isExpanded={expandedKey === key}
toggleHeading={() => toggleHeading(heading.node)}
/>
);
if (heading.children.length) {
const subHeaders = renderPageHeadings(heading.children, i);
return [item, subHeaders];
}
return [item];
});
const list = <HeadingStructureHeadingTreeList children={children} />;
if (false !== nestedId) {
return <li key={`heading-structure-${nestedId}-nested`}>{list}</li>;
}
return list;
},
[expandedKey, toggleHeading, keyForNode],
);
if (!pageHeadings.length && isLoading) {
return <HeadingStructureHeadingTreeLoader />;
}
return renderPageHeadings(pageHeadings, false);
};
export default HeadingStructureHeadingTree;