@atlaskit/page-layout
Version:
A collection of components which let you compose an application's page layout.
55 lines (53 loc) • 1.79 kB
JavaScript
import React, { useRef, useState } from 'react';
import { PAGE_LAYOUT_SLOT_SELECTOR } from '../common/constants';
import { SkipLinksContext } from './skip-link-context';
const byDOMOrder = (a, b) => {
var _a$listIndex, _b$listIndex;
const elems = Array.from(document.querySelectorAll(`[${PAGE_LAYOUT_SLOT_SELECTOR}]`));
const elemA = document.getElementById(a.id);
const elemB = document.getElementById(b.id);
const indexA = (_a$listIndex = a.listIndex) !== null && _a$listIndex !== void 0 ? _a$listIndex : elems.indexOf(elemA);
const indexB = (_b$listIndex = b.listIndex) !== null && _b$listIndex !== void 0 ? _b$listIndex : elems.indexOf(elemB);
/**
* If they are tied it is because one (or both) is
* a custom skiplink with a set index.
*
* Give the custom skiplink priority.
*/
if (indexA === indexB) {
if (a.listIndex !== undefined) {
return -1;
} else {
return 1;
}
}
return indexA - indexB;
};
// eslint-disable-next-line @repo/internal/react/require-jsdoc
export const SkipLinksController = ({
children
}) => {
const [links, setLinks] = useState([]);
const registerSkipLink = useRef(skipLinkData => {
// Don't add duplicate SkipLinks
setLinks(oldLinks => {
if (oldLinks.some(({
id
}) => id === skipLinkData.id)) {
return oldLinks;
}
return [...oldLinks, skipLinkData].sort(byDOMOrder);
});
});
const unregisterSkipLink = useRef(id => {
setLinks(links => links.filter(link => link.id !== id));
});
const context = {
registerSkipLink: registerSkipLink.current,
skipLinksData: links,
unregisterSkipLink: unregisterSkipLink.current
};
return /*#__PURE__*/React.createElement(SkipLinksContext.Provider, {
value: context
}, children);
};