@atlaskit/navigation-system
Version:
The latest navigation system for Atlassian apps.
79 lines (75 loc) • 2.63 kB
JavaScript
import React, { useCallback, useMemo, useState } from 'react';
import { SkipLinksContainer } from '../../components/skip-links/skip-links-container';
import { SkipLinksContext } from './skip-links-context';
const getByDomOrderSortFunction = () => {
const layoutSlots = Array.from(document.querySelectorAll(`[data-layout-slot]`));
return (a, b) => {
var _a$listIndex, _b$listIndex;
const indexA = (_a$listIndex = a.listIndex) !== null && _a$listIndex !== void 0 ? _a$listIndex : layoutSlots.indexOf(document.getElementById(a.id));
const indexB = (_b$listIndex = b.listIndex) !== null && _b$listIndex !== void 0 ? _b$listIndex : layoutSlots.indexOf(document.getElementById(b.id));
/**
* 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;
};
};
/**
* Provider for skip links. Should be rendered at the top level of the application.
*
* - Provides the context to register/unregister skip links
* - Renders the skip links container
*/
export function SkipLinksProvider({
children,
label,
triggerLabel,
testId
}) {
const [links, setLinks] = useState([]);
const registerSkipLink = useCallback(skipLinkData => {
// Don't add duplicate skip links
setLinks(oldLinks => {
if (oldLinks.some(({
id
}) => id === skipLinkData.id)) {
if (process.env.NODE_ENV !== 'production') {
// eslint-disable-next-line no-console
console.warn(`\
Tried registering duplicate skip link for ID '${skipLinkData.id}'.
If you're trying to override a slot skip link label, then use the \`skipLinkLabel\` prop instead.
This error will not be shown in production, and the duplicate skip link will be ignored.`);
}
return oldLinks;
}
return [...oldLinks, skipLinkData].sort(getByDomOrderSortFunction());
});
}, []);
const unregisterSkipLink = useCallback(id => {
setLinks(links => links.filter(link => link.id !== id));
}, []);
const contextValue = useMemo(() => {
const data = {
registerSkipLink,
unregisterSkipLink
};
return data;
}, [registerSkipLink, unregisterSkipLink]);
return /*#__PURE__*/React.createElement(SkipLinksContext.Provider, {
value: contextValue
}, /*#__PURE__*/React.createElement(SkipLinksContainer, {
label: label,
triggerLabel: triggerLabel,
testId: testId,
links: links
}), children);
}