aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/organisms/widgets/toc-widget/toc-widget.tsx
blob: c2d015a6cb53af234c38f7f1e017b18d71934ad2 (plain)
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
import { type ForwardRefRenderFunction, forwardRef } from 'react';
import type { HeadingsTreeNode } from '../../../../utils/hooks';
import {
  LinksWidget,
  type LinksWidgetItemData,
  type LinksWidgetProps,
} from '../links-widget';
import styles from './toc-widget.module.scss';

const getLinksItemFrom = (tree: HeadingsTreeNode[]): LinksWidgetItemData[] =>
  tree.map((node) => {
    return {
      child: node.children.length ? getLinksItemFrom(node.children) : undefined,
      id: node.id,
      label: node.label,
      url: `#${node.id}`,
    };
  });

export type TocWidgetProps = Omit<LinksWidgetProps, 'isOrdered' | 'items'> & {
  /**
   * The headings tree.
   */
  tree: HeadingsTreeNode[];
};

const TocWidgetWithRef: ForwardRefRenderFunction<
  HTMLDivElement,
  TocWidgetProps
> = ({ className = '', tree, ...props }, ref) => {
  const wrapperClass = `${styles.toc} ${className}`;

  return (
    <LinksWidget
      {...props}
      className={wrapperClass}
      isOrdered
      items={getLinksItemFrom(tree)}
      ref={ref}
    />
  );
};

export const TocWidget = forwardRef(TocWidgetWithRef);