Skip to content

Commit

Permalink
feat: add select option to toc component (#177)
Browse files Browse the repository at this point in the history
* feat(toc): adds select to toc

* chore: add 72 space increment

* chore: removes redundant flex

Co-authored-by: Nauman Ali <[email protected]>
Co-authored-by: Marc MacLeod <[email protected]>
  • Loading branch information
3 people authored Jul 28, 2020
1 parent 3a44d5a commit 72e1558
Show file tree
Hide file tree
Showing 3 changed files with 821 additions and 12 deletions.
72 changes: 60 additions & 12 deletions src/TableOfContents/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { Button, Drawer, InputGroup } from '@blueprintjs/core';
import { Button, Drawer, InputGroup, MenuItem } from '@blueprintjs/core';
import cn from 'classnames';
import { flatMap, range } from 'lodash';
import * as React from 'react';

import { FAIcon, FAIconProp } from '../FAIcon';
import { ScrollContainer } from '../ScrollContainer';
import { ItemRenderer, Select } from '../Select';

export type TableOfContentsItem = {
name: React.ReactNode;
Expand All @@ -30,6 +31,12 @@ export type TableOfContentsItem = {
};
};

export type SelectItem = {
name: React.ReactNode;
value: string;
label?: string;
};

export type ITableOfContentsLink = TableOfContentsItem & {
to?: string;
exact?: boolean;
Expand Down Expand Up @@ -77,6 +84,14 @@ export interface ITableOfContents<T extends TableOfContentsItem = TableOfContent
// provide filter and onChangeFilter to enable filtering. this will render a filter input at the top of the TOC.
filter?: string;
onChangeFilter?: (filter: string) => void;

// provide filter and onChangeFilter to enable filtering.
selectFilter?: {
items: SelectItem[];
onSelect: (value: SelectItem) => void;
activeItem?: SelectItem;
initialContent?: string;
};
}

// This is to avoid "mismatch" when rendering during SSR, since we render without scroll container in SSR
Expand Down Expand Up @@ -159,6 +174,7 @@ export function TableOfContents<T extends TableOfContentsItem = TableOfContentsI
withScroller,
filter,
onChangeFilter,
selectFilter,
...innerProps
}: ITableOfContents<T>) {
useRenderWithScroll();
Expand All @@ -167,22 +183,54 @@ export function TableOfContents<T extends TableOfContentsItem = TableOfContentsI

const hasFilter = filter !== undefined && onChangeFilter;

const SelectGroup = Select.ofType<SelectItem>();

const toc = <TableOfContentsInner className={cn(hasFilter ? `pb-${padding}` : `py-${padding}`)} {...innerProps} />;

const renderSelect: ItemRenderer<SelectItem> = (item, { handleClick, modifiers }) => {
if (!modifiers.matchesPredicate) {
return null;
}
return (
<MenuItem key={item.value} text={item.name} label={item.label} active={modifiers.active} onClick={handleClick} />
);
};

function getActiveItem() {
return selectFilter?.activeItem;
}

const containerClassName = cn('TableOfContents', className);
const comp = (
<>
{hasFilter && (
<InputGroup
leftIcon="filter"
placeholder="Filter..."
className={`m-${padding}`}
value={filter}
autoFocus
onChange={(event: React.ChangeEvent<HTMLInputElement>) => onChangeFilter?.(event.currentTarget.value)}
/>
)}

<div className="flex">
{selectFilter != undefined && (
<SelectGroup
items={selectFilter.items}
onItemSelect={selectFilter.onSelect}
itemRenderer={renderSelect}
filterable={false}
activeItem={getActiveItem()}
className={cn(`m-${padding}`, { 'mr-0': hasFilter })}
>
<Button
text={getActiveItem()?.name ?? selectFilter.initialContent ?? 'Fetching...'}
alignText="left"
rightIcon="caret-down"
/>
</SelectGroup>
)}
{hasFilter && (
<InputGroup
leftIcon="search"
placeholder="Search..."
className={`m-${padding} w-full`}
value={filter}
autoFocus
onChange={(event: React.ChangeEvent<HTMLInputElement>) => onChangeFilter?.(event.currentTarget.value)}
/>
)}
</div>
<div className={containerClassName} data-test={dataTest}>
{renderWithScroll && withScroller ? <ScrollContainer>{toc}</ScrollContainer> : toc}
</div>
Expand Down
Loading

0 comments on commit 72e1558

Please sign in to comment.