Skip to content

Commit

Permalink
chore(react-tree): deprecate flattenTree
Browse files Browse the repository at this point in the history
  • Loading branch information
bsunderhus committed Jan 29, 2025
1 parent 82cc27f commit 26be764
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 50 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "chore: deprecate flattenTree",
"packageName": "@fluentui/react-tree",
"email": "[email protected]",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ import type { SelectionMode as SelectionMode_2 } from '@fluentui/react-utilities
import type { Slot } from '@fluentui/react-utilities';
import type { SlotClassNames } from '@fluentui/react-utilities';

// @public
// @public @deprecated (undocumented)
export const flattenTree_unstable: <Props extends TreeItemProps>(items: FlattenTreeItem<Props>[]) => FlattenedTreeItem<Props>[];

// @public (undocumented)
// @public @deprecated (undocumented)
export type FlattenTreeItem<Props extends TreeItemProps> = Omit<Props, 'subtree' | 'itemType'> & {
value: TreeItemValue;
subtree?: FlattenTreeItem<Props>[];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,35 @@
import { HeadlessFlatTreeItemProps } from '../FlatTree';
import { TreeItemProps, TreeItemValue } from '../TreeItem';

/**
* @deprecated - deprecating in favor of user flattening its custom data structure on its own
*/
export type FlattenTreeItem<Props extends TreeItemProps> = Omit<Props, 'subtree' | 'itemType'> & {
value: TreeItemValue;
subtree?: FlattenTreeItem<Props>[];
};

/**
* @deprecated - deprecating in favor of user flattening its custom data structure on its own
*/
export type FlattenedTreeItem<Props extends TreeItemProps> = HeadlessFlatTreeItemProps & Props;

function flattenTreeRecursive<Props extends TreeItemProps>(
// eslint-disable-next-line @typescript-eslint/no-deprecated
items: FlattenTreeItem<Props>[],
parent?: HeadlessFlatTreeItemProps & Props,
level = 1,
// eslint-disable-next-line @typescript-eslint/no-deprecated
): FlattenedTreeItem<Props>[] {
// eslint-disable-next-line @typescript-eslint/no-deprecated
return items.reduce<FlattenedTreeItem<Props>[]>((acc, { subtree, ...item }, index) => {
const flatTreeItem = {
'aria-level': level,
'aria-posinset': index + 1,
'aria-setsize': items.length,
parentValue: parent?.value,
...item,
// eslint-disable-next-line @typescript-eslint/no-deprecated
} as FlattenedTreeItem<Props>;
acc.push(flatTreeItem);
if (subtree !== undefined) {
Expand All @@ -30,6 +40,9 @@ function flattenTreeRecursive<Props extends TreeItemProps>(
}

/**
*
* @deprecated - deprecating in favor of user flattening its custom data structure on its own
*
* Converts a nested structure to a flat one which can be consumed by `useFlatTreeItems`
* @example
* ```tsx
Expand Down Expand Up @@ -71,5 +84,7 @@ function flattenTreeRecursive<Props extends TreeItemProps>(
*/
// eslint-disable-next-line @typescript-eslint/naming-convention
export const flattenTree_unstable = <Props extends TreeItemProps>(
// eslint-disable-next-line @typescript-eslint/no-deprecated
items: FlattenTreeItem<Props>[],
// eslint-disable-next-line @typescript-eslint/no-deprecated
): FlattenedTreeItem<Props>[] => flattenTreeRecursive(items);
Original file line number Diff line number Diff line change
Expand Up @@ -32,54 +32,6 @@ const flatTreeItems: FlatItem[] = [
{ value: '2-1-1-1', parentValue: '2-1-1', content: 'Level 4, item 1' },
];

// // EXAMPLE OF NESTED TREE ITEMS BEING FLATTEN BY `flattenTree`:
// type Item = TreeItemProps & { content: React.ReactNode };

// const nestedTreeItems = [
// {
// value: '1',
// content: <>level 1, item 1</>,
// subtree: [
// {
// value: '1-1',
// content: <>level 2, item 1</>,
// },
// {
// value: '1-2',
// content: <>level 2, item 2</>,
// },
// {
// value: '1-3',
// content: <>level 2, item 3</>,
// },
// ],
// },
// {
// value: '2',
// content: <>level 1, item 2</>,
// subtree: [
// {
// value: '2-1',
// content: <>level 2, item 1</>,
// subtree: [
// {
// value: '2-1-1',
// content: <>level 3, item 1</>,
// subtree: [
// {
// value: '2-1-1-1',
// content: <>level 4, item 1</>,
// },
// ],
// },
// ],
// },
// ],
// },
// ];

// const flatTreeItems = flattenTree_unstable<Item>(nestedTreeItems);

const ActionsExample = () => (
<>
<Button aria-label="Edit" appearance="subtle" icon={<Edit20Regular />} />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import * as React from 'react';
import {
FlatTree,
TreeItem,
TreeItemLayout,
useHeadlessFlatTree_unstable,
HeadlessFlatTreeItemProps,
TreeItemValue,
} from '@fluentui/react-components';

type FlatTreeItem = HeadlessFlatTreeItemProps & { content: React.ReactNode };
type NestedTreeItem = FlatTreeItem & { subtree?: NestedTreeItem[] };

const flattenTree = (items: NestedTreeItem[], parentValue?: TreeItemValue | undefined): FlatTreeItem[] =>
items.flatMap<FlatTreeItem>(({ subtree, ...item }) =>
subtree ? [{ ...item, parentValue }, ...flattenTree(subtree, item.value)] : { parentValue, ...item },
);

const flatTreeItems = flattenTree([
{
value: '1',
content: <>level 1, item 1</>,
subtree: [
{
value: '1-1',
content: <>level 2, item 1</>,
},
{
value: '1-2',
content: <>level 2, item 2</>,
},
{
value: '1-3',
content: <>level 2, item 3</>,
},
],
},
{
value: '2',
content: <>level 1, item 2</>,
subtree: [
{
value: '2-1',
content: <>level 2, item 1</>,
subtree: [
{
value: '2-1-1',
content: <>level 3, item 1</>,
subtree: [
{
value: '2-1-1-1',
content: <>level 4, item 1</>,
},
],
},
],
},
],
},
]);

export const UseHeadlessFlatTreeWithNestedStructure = () => {
const flatTree = useHeadlessFlatTree_unstable(flatTreeItems);
return (
<FlatTree {...flatTree.getTreeProps()} aria-label="Flat Tree">
{Array.from(flatTree.items(), flatTreeItem => {
const { content, ...treeItemProps } = flatTreeItem.getTreeItemProps();
return (
<TreeItem key={treeItemProps.value} {...treeItemProps}>
<TreeItemLayout>{content}</TreeItemLayout>
</TreeItem>
);
})}
</FlatTree>
);
};

UseHeadlessFlatTreeWithNestedStructure.parameters = {
docs: {
description: {
story: `If your data structure is nested, it can be converted to a flat structure before providing it to \`useHeadlessFlatTree\`. Here's an example using recursion and [\`Array.flatMap\`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap) to convert a nested array of items (nested by the property \`subtree\`) into a flat array of items:`,
},
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export { FlatTreeStory as FlatTree } from './FlatTree.stories';

// SCENARIOS & FEATURES
export { UseHeadlessFlatTree } from './UseHeadlessFlatTree.stories';
export { UseHeadlessFlatTreeWithNestedStructure } from './UseHeadlessFlatTreeWithNestedStructure.stories';
export { Selection } from './TreeSelection.stories';
export { Manipulation } from './TreeManipulation.stories';
export { LazyLoading } from './TreeLazyLoading.stories';
Expand Down

0 comments on commit 26be764

Please sign in to comment.