import { css } from '@emotion/react';
import { spacing } from '@expo/styleguide-base';
import { useMemo } from 'react';
import { HeadingEntry, useHeadingsObserver } from './useHeadingObserver';
import { LayoutScroll, useAutoScrollTo } from '~/ui/components/Layout';
import { A, CALLOUT } from '~/ui/components/Text';
type TableOfContentsLinkProps = HeadingEntry & {
isActive?: boolean;
};
export function TableOfContents() {
const { headings, activeId } = useHeadingsObserver();
const autoScroll = useAutoScrollTo(activeId ? `[data-toc-id="${activeId}"]` : '');
return (
);
}
function TableOfContentsLink({ id, element, isActive }: TableOfContentsLinkProps) {
const info = useMemo(() => getHeadingInfo(element), [element]);
return (
{info.text}
);
}
const containerStyle = css({
display: 'block',
width: '100%',
padding: spacing[8],
});
const titleStyle = css({
marginTop: spacing[4],
marginBottom: spacing[1.5],
});
const listStyle = css({
listStyle: 'none',
});
const linkStyle = css({
display: 'block',
padding: `${spacing[1.5]}px 0`,
});
export function getHeadingIndent(heading: HTMLHeadingElement) {
const level = Math.max(Number(heading.tagName.slice(1)) - 2, 0);
return { paddingLeft: spacing[2] * level };
}
/**
* Parse the heading information from an HTML heading element.
* If it contains parenthesis, we try to extract the function name only.
*/
export function getHeadingInfo(heading: HTMLHeadingElement) {
const text = heading.textContent || '';
const functionOpenChar = text.indexOf('(');
return functionOpenChar >= 0 && text[functionOpenChar - 1].trim()
? { type: 'code', text: text.slice(0, functionOpenChar) }
: { type: 'text', text };
}