Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 33 additions & 22 deletions packages/react-components/react-tree/etc/react-tree.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,62 +4,73 @@

```ts

import type { ARIAButtonElement } from '@fluentui/react-aria';
import type { ARIAButtonSlotProps } from '@fluentui/react-aria';
import type { ComponentProps } from '@fluentui/react-utilities';
import type { ComponentState } from '@fluentui/react-utilities';
import { ContextSelector } from '@fluentui/react-context-selector';
import { FC } from 'react';
import type { ForwardRefComponent } from '@fluentui/react-utilities';
import { Provider } from 'react';
import { ProviderProps } from 'react';
import * as React_2 from 'react';
import type { Slot } from '@fluentui/react-utilities';
import type { SlotClassNames } from '@fluentui/react-utilities';

// @public
export const Tree: ForwardRefComponent<TreeProps>;

// @public
export const TreeBranch: ForwardRefComponent<TreeBranchProps>;

// @public (undocumented)
export const treeBranchClassNames: SlotClassNames<TreeBranchSlots>;

// @public (undocumented)
export type TreeBranchProps = ComponentProps<TreeBranchSlots> & {};
export const treeClassNames: SlotClassNames<TreeSlots>;

// @public (undocumented)
export type TreeBranchSlots = {
root: Slot<'div'>;
export type TreeContextValue = {
level: number;
openSubtrees: string[];
focusFirstSubtreeItem(target: TreeItemElement): void;
focusSubtreeOwnerItem(target: TreeItemElement): void;
requestOpenChange(data: TreeOpenChangeData): void;
};

// @public
export type TreeBranchState = ComponentState<TreeBranchSlots>;
export const TreeItem: ForwardRefComponent<TreeItemProps>;

// @public (undocumented)
export const treeClassNames: SlotClassNames<TreeSlots>;
export const treeItemClassNames: SlotClassNames<TreeItemSlots>;

// @public
export const TreeLeaf: ForwardRefComponent<TreeLeafProps>;
export type TreeItemProps = ComponentProps<TreeItemSlots>;

// @public (undocumented)
export const treeLeafClassNames: SlotClassNames<TreeLeafSlots>;
export type TreeItemSlots = {
root: NonNullable<Slot<ARIAButtonSlotProps<'div' | 'a'>>>;
};

// @public (undocumented)
export type TreeLeafProps = ComponentProps<TreeLeafSlots> & {};
// @public
export type TreeItemState = ComponentState<TreeItemSlots>;

// @public (undocumented)
export type TreeLeafSlots = {
root: Slot<'div'>;
export type TreeProps = ComponentProps<TreeSlots> & {
openSubtrees?: string | string[];
defaultOpenSubtrees?: string | string[];
onOpenChange?(event: TreeOpenChangeEvent, data: TreeOpenChangeData): void;
};

// @public (undocumented)
export type TreeLeafState = ComponentState<TreeLeafSlots>;

// @public (undocumented)
export type TreeProps = ComponentProps<TreeSlots> & {};
export const TreeProvider: Provider<TreeContextValue | undefined> & FC<ProviderProps<TreeContextValue | undefined>>;

// @public (undocumented)
export type TreeSlots = {
root: Slot<'div'>;
};

// @public
export type TreeState = ComponentState<TreeSlots>;
export type TreeState = ComponentState<TreeSlots> & TreeContextValue & {
open: boolean;
};

// @public (undocumented)
export const useTreeContext_unstable: <T>(selector: ContextSelector<TreeContextValue, T>) => T;

// (No @packageDocumentation comment for this package)

Expand Down
5 changes: 5 additions & 0 deletions packages/react-components/react-tree/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@
"@fluentui/scripts": "^1.0.0"
},
"dependencies": {
"@fluentui/react-context-selector": "^9.1.2",
"@fluentui/react-shared-contexts": "^9.1.1",
"@fluentui/react-aria": "^9.3.2",
"@fluentui/react-tabster": "^9.3.1",
"@fluentui/keyboard-keys": "^9.0.1",
"@fluentui/react-theme": "^9.1.2",
"@fluentui/react-utilities": "^9.2.2",
"@griffel/react": "^1.4.2",
Expand Down
1 change: 0 additions & 1 deletion packages/react-components/react-tree/src/TreeBranch.ts

This file was deleted.

1 change: 1 addition & 0 deletions packages/react-components/react-tree/src/TreeItem.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './components/TreeItem/index';
1 change: 0 additions & 1 deletion packages/react-components/react-tree/src/TreeLeaf.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ describe('Tree', () => {
isConformant({
Component: Tree,
displayName: 'Tree',
disabledTests: ['consistent-callback-args'],
});

it('renders a default state', () => {
const result = render(<Tree>Default Tree</Tree>);
const result = render(<Tree />);
expect(result.container).toMatchSnapshot();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,21 @@ import { renderTree_unstable } from './renderTree';
import { useTreeStyles_unstable } from './useTreeStyles';
import type { TreeProps } from './Tree.types';
import type { ForwardRefComponent } from '@fluentui/react-utilities';
import { useTreeContextValues_unstable } from './useTreeContextValues';

/**
* A tree component provides a hierarchical list
* A tree view widget presents a hierarchical list.
* Any item in the hierarchy may have child items,
* and items that have children may be expanded or collapsed to show or hide the children.
* For example, in a file system navigator that uses a tree view to display folders and files,
* an item representing a folder can be expanded to reveal the contents of the folder,
* which may be files, folders, or both.
*/
export const Tree: ForwardRefComponent<TreeProps> = React.forwardRef((props, ref) => {
const state = useTree_unstable(props, ref);

useTreeStyles_unstable(state);
return renderTree_unstable(state);
const contextValues = useTreeContextValues_unstable(state);
return renderTree_unstable(state, contextValues);
});

Tree.displayName = 'Tree';
Original file line number Diff line number Diff line change
@@ -1,12 +1,56 @@
import * as React from 'react';
import type { ComponentProps, ComponentState, Slot } from '@fluentui/react-utilities';
import type { TreeItemElement } from '../TreeItem/TreeItem.types';
import { TreeContextValue } from '../../contexts/treeContext';

export type TreeSlots = {
root: Slot<'div'>;
};

export type TreeProps = ComponentProps<TreeSlots> & {};
export type TreeOpenChangeData = { open: boolean; id: string } & (
| {
event: React.MouseEvent<TreeItemElement>;
type: 'click';
}
| {
event: React.KeyboardEvent<TreeItemElement>;
type: 'arrowRight' | 'arrowLeft';
}
);

export type TreeOpenChangeEvent = TreeOpenChangeData['event'];

export type TreeContextValues = {
tree: TreeContextValue;
};

export type TreeProps = ComponentProps<TreeSlots> & {
/**
* Controls the state of the open subtrees.
* These property is ignored for subtrees.
*/
openSubtrees?: string | string[];
/**
* Default value for the uncontrolled state of open subtrees.
* These property is ignored for subtrees.
*/
defaultOpenSubtrees?: string | string[];
/**
* Callback fired when the component changes value from open state.
* These property is ignored for subtrees.
*
* @param event - a React's Synthetic event
* @param data - A data object with relevant information,
* such as open value and type of interaction that created the event
* and the id of the subtree that is being opened/closed
*/
onOpenChange?(event: TreeOpenChangeEvent, data: TreeOpenChangeData): void;
};

/**
* State used in rendering Tree
*/
export type TreeState = ComponentState<TreeSlots>;
export type TreeState = ComponentState<TreeSlots> &
TreeContextValue & {
open: boolean;
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ exports[`Tree renders a default state 1`] = `
<div>
<div
class="fui-Tree"
>
Default Tree
</div>
data-tabster="{\\"mover\\":{\\"cyclic\\":false,\\"direction\\":1,\\"tabbable\\":true}}"
role="tree"
/>
</div>
`;
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import * as React from 'react';
import { getSlots } from '@fluentui/react-utilities';
import type { TreeState, TreeSlots } from './Tree.types';
import type { TreeState, TreeSlots, TreeContextValues } from './Tree.types';
import { TreeProvider } from '../../contexts';

export const renderTree_unstable = (state: TreeState) => {
export const renderTree_unstable = (state: TreeState, contextValues: TreeContextValues) => {
const { open } = state;
const { slots, slotProps } = getSlots<TreeSlots>(state);

return <slots.root {...slotProps.root} />;
return (
<TreeProvider value={contextValues.tree}>
{open && <slots.root {...slotProps.root}>{slotProps.root.children}</slots.root>}
</TreeProvider>
);
};
Loading