@sinups/fmap
fmap is a lightweight tool that visualizes your file and folder structure in a clean, readable tree view — perfect for documentation
Source
View source code
Package
@sinups/fmap
Docs
Edit this page
Built by
Andrei Cojocari (@sinups)
License
MIT
Installation
yarn add @sinups/fmapnpm install @sinups/fmapUsage
- src
- node_modules
- package.json
- tsconfig.json
import { Tree } from '@mantine/core';
import { data } from './data';
function Demo() {
return <Tree data={data} />;
}Files Example
- src
- node_modules
- package.json
- tsconfig.json
import { IconFolder, IconFolderOpen } from '@tabler/icons-react';
import { Group } from '@mantine/core';
import { RenderTreeNodePayload, Tree } from '@sinups/fmap';
import { CssIcon, NpmIcon, TypeScriptCircleIcon } from '@mantinex/dev-icons';
import { data, dataCode } from './data';
import classes from './Demo.module.css';
interface FileIconProps {
name: string;
isFolder: boolean;
expanded: boolean;
}
function FileIcon({ name, isFolder, expanded }: FileIconProps) {
if (name.endsWith('package.json')) {
return <NpmIcon size={14} />;
}
if (name.endsWith('.ts') || name.endsWith('.tsx') || name.endsWith('tsconfig.json')) {
return <TypeScriptCircleIcon size={14} />;
}
if (name.endsWith('.css')) {
return <CssIcon size={14} />;
}
if (isFolder) {
return expanded ? (
<IconFolderOpen color="var(--mantine-color-yellow-9)" size={14} stroke={2.5} />
) : (
<IconFolder color="var(--mantine-color-yellow-9)" size={14} stroke={2.5} />
);
}
return null;
}
function Leaf({ node, expanded, hasChildren, elementProps }: RenderTreeNodePayload) {
return (
<Group gap={5} {...elementProps}>
<FileIcon name={node.value} isFolder={hasChildren} expanded={expanded} />
<span>{node.label}</span>
</Group>
);
}
function Demo() {
return (
<Tree
classNames={classes}
selectOnClick
clearSelectionOnOutsideClick
data={data}
renderNode={(payload) => <Leaf {...payload} />}
/>
);
}Render Node
- src
- node_modules
- package.json
- tsconfig.json
import { IconChevronDown } from '@tabler/icons-react';
import { Group } from '@mantine/core';
import { Tree } from '@sinups/fmap';
import { data } from './data';
function Demo() {
return (
<Tree
data={data}
levelOffset={23}
renderNode={({ node, expanded, hasChildren, elementProps }) => (
<Group gap={5} {...elementProps}>
{hasChildren && (
<IconChevronDown
size={18}
style={{ transform: expanded ? 'rotate(180deg)' : 'rotate(0deg)' }}
/>
)}
<span>{node.label}</span>
</Group>
)}
/>
);
}Controller
- src
- node_modules
- package.json
- tsconfig.json
import { Button, Group, Tree, useTree } from '@mantine/core';
import { data } from './data';
function Demo() {
const tree = useTree();
return (
<>
<Tree data={data} tree={tree} />
<Group mt="md">
<Button onClick={() => tree.expandAllNodes()}>Expand all</Button>
<Button onClick={() => tree.collapseAllNodes()}>Collapse all</Button>
</Group>
</>
);
}Checked State
- src
- node_modules
- package.json
- tsconfig.json
import { IconChevronDown } from '@tabler/icons-react';
import { Checkbox, Group, RenderTreeNodePayload, Tree } from '@mantine/core';
import { data } from './data';
const renderTreeNode = ({
node,
expanded,
hasChildren,
elementProps,
tree,
}: RenderTreeNodePayload) => {
const checked = tree.isNodeChecked(node.value);
const indeterminate = tree.isNodeIndeterminate(node.value);
return (
<Group gap="xs" {...elementProps}>
<Checkbox.Indicator
checked={checked}
indeterminate={indeterminate}
onClick={() => (!checked ? tree.checkNode(node.value) : tree.uncheckNode(node.value))}
/>
<Group gap={5} onClick={() => tree.toggleExpanded(node.value)}>
<span>{node.label}</span>
{hasChildren && (
<IconChevronDown
size={14}
style={{ transform: expanded ? 'rotate(180deg)' : 'rotate(0deg)' }}
/>
)}
</Group>
</Group>
);
};
function Demo() {
return <Tree data={data} levelOffset={23} expandOnClick={false} renderNode={renderTreeNode} />;
}Expanded State
- src
- components
- Accordion.tsx
- Tree.tsx
- Button.tsx
- node_modules
- package.json
- tsconfig.json
import { getTreeExpandedState, Tree, useTree } from '@mantine/core';
import { data } from './data';
function Demo() {
const tree = useTree({
initialExpandedState: getTreeExpandedState(data, ['src', 'src/components']),
});
return <Tree data={data} tree={tree} />;
}Check All Nodes
- src
- components
- Accordion.tsx
- Tree.tsx
- Button.tsx
- node_modules
- react
- index.d.ts
- package.json
- @mantine
- core
- index.d.ts
- package.json
- hooks
- index.d.ts
- package.json
- form
- index.d.ts
- package.json
- package.json
- tsconfig.json
import { IconChevronDown } from '@tabler/icons-react';
import {
Button,
Checkbox,
getTreeExpandedState,
Group,
RenderTreeNodePayload,
Tree,
useTree,
} from '@mantine/core';
import { data } from './data';
const renderTreeNode = ({
node,
expanded,
hasChildren,
elementProps,
tree,
}: RenderTreeNodePayload) => {
const checked = tree.isNodeChecked(node.value);
const indeterminate = tree.isNodeIndeterminate(node.value);
return (
<Group gap="xs" {...elementProps}>
<Checkbox.Indicator
checked={checked}
indeterminate={indeterminate}
onClick={() => (!checked ? tree.checkNode(node.value) : tree.uncheckNode(node.value))}
/>
<Group gap={5} onClick={() => tree.toggleExpanded(node.value)}>
<span>{node.label}</span>
{hasChildren && (
<IconChevronDown
size={14}
style={{ transform: expanded ? 'rotate(180deg)' : 'rotate(0deg)' }}
/>
)}
</Group>
</Group>
);
};
function Demo() {
const tree = useTree({
initialExpandedState: getTreeExpandedState(data, '*'),
initialCheckedState: [
'node_modules',
'node_modules/@mantine/core/index.d.ts',
'node_modules/@mantine/form/package.json',
],
});
return (
<>
<Group mb="md">
<Button onClick={() => tree.checkAllNodes()}>Check all</Button>
<Button onClick={() => tree.uncheckAllNodes()}>Uncheck all</Button>
</Group>
<Tree
tree={tree}
data={data}
levelOffset={23}
expandOnClick={false}
renderNode={renderTreeNode}
/>
</>
);
}