Skip to content

Commit

Permalink
Format union types
Browse files Browse the repository at this point in the history
  • Loading branch information
vladmoroz committed Nov 14, 2024
1 parent 3fa72d3 commit da20f92
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 1 deletion.
87 changes: 87 additions & 0 deletions docs/src/components/TableCode.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import * as React from 'react';

interface TableCodeProps extends React.ComponentProps<'code'> {
printWidth?: number;
}

/** An inline code component that breaks long union types into multiple lines */
export function TableCode({ children, printWidth = 40, ...props }: TableCodeProps) {
const text = getTextContents(children);

if (text.includes('|') && text.length > printWidth) {
const unionGroups: React.ReactNode[][] = [];
const parts = React.Children.toArray(children);

let depth = 0;
let groupIndex = 0;
parts.forEach((child, index) => {
if (index === 0) {
unionGroups.push([child]);
return;
}

if (getTextContents(child).trim() === '|' && depth < 1) {
groupIndex += 1;
unionGroups.push([]);
return;
}

if (getTextContents(child).trim() === '(') {
depth += 1;
}

if (getTextContents(child).trim() === ')') {
depth -= 1;
}

unionGroups[groupIndex].push(child);
});

if (unionGroups.length > 1) {
unionGroups.forEach((_, index) => {
const pipe = <span style={{ color: 'var(--syntax-keyword)' }}>| </span>;
const pipeWithNewline = (
<React.Fragment>
<br />
{pipe}
</React.Fragment>
);

const element = index === 0 ? pipe : pipeWithNewline;
unionGroups.splice(index * 2, 0, [element]);
});
}

children = unionGroups.flat();
}

return <code {...props}>{children}</code>;
}

function getTextContents(node?: React.ReactNode): string {
if (hasChildren(node)) {
return getTextContents(node.props?.children);
}

if (Array.isArray(node)) {
return node.map(getTextContents).flat().filter(Boolean).join('');
}

if (typeof node === 'string') {
return node;
}

return '';
}

function hasChildren(
element?: React.ReactNode,
): element is React.ReactElement<React.PropsWithChildren> {
return (
React.isValidElement(element) &&
typeof element.props === 'object' &&
!!element.props &&
'children' in element.props &&
Boolean(element.props.children)
);
}
3 changes: 2 additions & 1 deletion docs/src/mdx-components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Code } from './components/Code';
import { PropsTable } from './components/reference/PropsTable';
import { AttributesTable } from './components/reference/AttributesTable';
import { CssVariablesTable } from './components/reference/CssVariablesTable';
import { TableCode } from './components/TableCode';

interface MDXComponents {
[key: string]: React.FC<any> | MDXComponents;
Expand Down Expand Up @@ -69,7 +70,7 @@ export const tableMdxComponents: MDXComponents = {
...mdxComponents,
// eslint-disable-next-line react/jsx-no-useless-fragment
p: (props) => <React.Fragment {...props} />,
code: (props) => <code {...props} />,
code: TableCode,
};

export function useMDXComponents(): MDXComponents {
Expand Down

0 comments on commit da20f92

Please sign in to comment.