Skip to content

Commit

Permalink
feat(react-tree): value property over id (#27532)
Browse files Browse the repository at this point in the history
  • Loading branch information
bsunderhus authored Apr 19, 2023
1 parent 92f70e6 commit 4dde672
Show file tree
Hide file tree
Showing 27 changed files with 366 additions and 294 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "removes TreeItemId type from react-tree",
"packageName": "@fluentui/react-components",
"email": "[email protected]",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "feat: value property over id",
"packageName": "@fluentui/react-tree",
"email": "[email protected]",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ import { treeClassNames } from '@fluentui/react-tree';
import { TreeContextValue } from '@fluentui/react-tree';
import { TreeItem } from '@fluentui/react-tree';
import { treeItemClassNames } from '@fluentui/react-tree';
import { TreeItemId } from '@fluentui/react-tree';
import { TreeItemLayout } from '@fluentui/react-tree';
import { treeItemLayoutClassNames } from '@fluentui/react-tree';
import { TreeItemLayoutProps } from '@fluentui/react-tree';
Expand Down Expand Up @@ -215,8 +214,6 @@ export { TreeItem }

export { treeItemClassNames }

export { TreeItemId }

export { TreeItemLayout }

export { treeItemLayoutClassNames }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@ export type {
TreeItemLayoutState,
TreeItemLayoutSlots,
TreeItemLayoutProps,
TreeItemId,
TreeContextValue,
NestedTreeItem,
FlatTree,
Expand Down
103 changes: 63 additions & 40 deletions packages/react-components/react-tree/etc/react-tree.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,35 +27,36 @@ import { ProviderProps } from 'react';
import * as React_2 from 'react';
import type { Slot } from '@fluentui/react-utilities';
import type { SlotClassNames } from '@fluentui/react-utilities';
import { SlotRenderFunction } from '@fluentui/react-utilities';

// @public
export const flattenTree_unstable: (items: NestedTreeItem[]) => FlatTreeItemProps[];
export const flattenTree_unstable: <Value = string>(items: NestedTreeItem<Value>[]) => FlatTreeItemProps<Value>[];

// @public
export type FlatTree = {
getTreeProps(): FlatTreeProps;
navigate(data: TreeNavigationData_unstable): void;
getNextNavigableItem(visibleItems: FlatTreeItem[], data: TreeNavigationData_unstable): FlatTreeItem | undefined;
items(): IterableIterator<FlatTreeItem>;
export type FlatTree<Value = string> = {
getTreeProps(): FlatTreeProps<Value>;
navigate(data: TreeNavigationData_unstable<Value>): void;
getNextNavigableItem(visibleItems: FlatTreeItem<Value>[], data: TreeNavigationData_unstable<Value>): FlatTreeItem<Value> | undefined;
items(): IterableIterator<FlatTreeItem<Value>>;
};

// @public (undocumented)
export type FlatTreeItem = Readonly<MutableFlatTreeItem>;
export type FlatTreeItem<Value = string> = Readonly<MutableFlatTreeItem<Value>>;

// @public (undocumented)
export type FlatTreeItemProps = TreeItemProps & {
id: TreeItemId;
parentId?: string;
export type FlatTreeItemProps<Value = string> = Omit<TreeItemProps, 'value'> & {
value: Value;
parentValue?: Value;
};

// @public (undocumented)
export type FlatTreeProps = Required<Pick<TreeProps, 'openItems' | 'onOpenChange' | 'onNavigation_unstable'> & {
export type FlatTreeProps<Value = string> = Required<Pick<TreeProps<Value>, 'openItems' | 'onOpenChange' | 'onNavigation_unstable'> & {
ref: React_2.Ref<HTMLDivElement>;
}>;

// @public (undocumented)
export type NestedTreeItem = Omit<TreeItemProps, 'subtree'> & {
subtree?: NestedTreeItem[];
export type NestedTreeItem<Value = string> = Omit<TreeItemProps<Value>, 'subtree'> & {
subtree?: NestedTreeItem<Value>[];
};

// @public (undocumented)
Expand All @@ -71,7 +72,22 @@ export const renderTreeItemLayout_unstable: (state: TreeItemLayoutState) => JSX.
export const renderTreeItemPersonaLayout_unstable: (state: TreeItemPersonaLayoutState, contextValues: TreeItemPersonaLayoutContextValues) => JSX.Element;

// @public
export const Tree: ForwardRefComponent<TreeProps>;
export const Tree: React_2.ForwardRefExoticComponent<Omit<TreeSlots, "root"> & Omit<{
as?: "div" | undefined;
} & Pick<React_2.DetailedHTMLProps<React_2.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React_2.HTMLAttributes<HTMLDivElement>> & {
ref?: ((instance: HTMLDivElement | null) => void) | React_2.RefObject<HTMLDivElement> | null | undefined;
} & {
children?: React_2.ReactNode | SlotRenderFunction<Pick<React_2.DetailedHTMLProps<React_2.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React_2.HTMLAttributes<HTMLDivElement>> & {
ref?: ((instance: HTMLDivElement | null) => void) | React_2.RefObject<HTMLDivElement> | null | undefined;
}>;
}, "ref"> & {
appearance?: "subtle" | "subtle-alpha" | "transparent" | undefined;
size?: "small" | "medium" | undefined;
openItems?: Iterable<string> | undefined;
defaultOpenItems?: Iterable<string> | undefined;
onOpenChange?(event: React_2.KeyboardEvent<HTMLElement> | React_2.MouseEvent<HTMLElement, MouseEvent>, data: TreeOpenChangeData<string>): void;
onNavigation_unstable?(event: React_2.KeyboardEvent<HTMLElement> | React_2.MouseEvent<HTMLElement, MouseEvent>, data: TreeNavigationData_unstable<string>): void;
} & React_2.RefAttributes<HTMLDivElement>> & (<Value = string>(props: TreeProps<Value>) => JSX.Element);

// @public (undocumented)
export const treeClassNames: SlotClassNames<TreeSlots>;
Expand All @@ -81,20 +97,30 @@ export type TreeContextValue = {
level: number;
appearance: 'subtle' | 'subtle-alpha' | 'transparent';
size: 'small' | 'medium';
openItems: ImmutableSet<TreeItemId>;
requestOpenChange(data: TreeOpenChangeData): void;
requestNavigation(data: TreeNavigationData_unstable): void;
openItems: ImmutableSet<unknown>;
requestOpenChange(data: TreeOpenChangeData<unknown>): void;
requestNavigation(data: TreeNavigationData_unstable<unknown>): void;
};

// @public
export const TreeItem: ForwardRefComponent<TreeItemProps>;
export const TreeItem: React_2.ForwardRefExoticComponent<Omit<Partial<TreeItemSlots>, "root"> & Omit<{
as?: "div" | undefined;
} & Pick<React_2.DetailedHTMLProps<React_2.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React_2.HTMLAttributes<HTMLDivElement>> & {
ref?: ((instance: HTMLDivElement | null) => void) | React_2.RefObject<HTMLDivElement> | null | undefined;
} & {
children?: React_2.ReactNode | SlotRenderFunction<Pick<React_2.DetailedHTMLProps<React_2.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React_2.HTMLAttributes<HTMLDivElement>> & {
ref?: ((instance: HTMLDivElement | null) => void) | React_2.RefObject<HTMLDivElement> | null | undefined;
}>;
} & {
style?: TreeItemCSSProperties | undefined;
}, "ref"> & {
value?: string | undefined;
leaf?: boolean | undefined;
} & React_2.RefAttributes<HTMLDivElement>> & (<Value = string>(props: TreeItemProps<Value>) => JSX.Element);

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

// @public (undocumented)
export type TreeItemId = string;

// @public
export const TreeItemLayout: ForwardRefComponent<TreeItemLayoutProps>;

Expand Down Expand Up @@ -143,7 +169,8 @@ export type TreeItemPersonaLayoutState = ComponentState<TreeItemPersonaLayoutSlo
};

// @public
export type TreeItemProps = ComponentProps<Partial<TreeItemSlots>> & {
export type TreeItemProps<Value = string> = ComponentProps<Partial<TreeItemSlots>> & {
value?: Value;
leaf?: boolean;
};

Expand Down Expand Up @@ -171,46 +198,42 @@ export type TreeItemState = ComponentState<TreeItemSlots> & {
};

// @public (undocumented)
export type TreeNavigationData_unstable = {
event: React_2.MouseEvent<HTMLElement>;
export type TreeNavigationData_unstable<Value = string> = {
value: Value;
target: HTMLElement;
} & ({
event: React_2.MouseEvent<HTMLElement>;
type: 'Click';
} | {
event: React_2.KeyboardEvent<HTMLElement>;
target: HTMLElement;
type: 'TypeAhead';
} | {
event: React_2.KeyboardEvent<HTMLElement>;
target: HTMLElement;
type: typeof ArrowRight;
} | {
event: React_2.KeyboardEvent<HTMLElement>;
target: HTMLElement;
type: typeof ArrowLeft;
} | {
event: React_2.KeyboardEvent<HTMLElement>;
target: HTMLElement;
type: typeof ArrowUp;
} | {
event: React_2.KeyboardEvent<HTMLElement>;
target: HTMLElement;
type: typeof ArrowDown;
} | {
event: React_2.KeyboardEvent<HTMLElement>;
target: HTMLElement;
type: typeof Home;
} | {
event: React_2.KeyboardEvent<HTMLElement>;
target: HTMLElement;
type: typeof End;
};
});

// @public (undocumented)
export type TreeNavigationEvent_unstable = TreeNavigationData_unstable['event'];

// @public (undocumented)
export type TreeOpenChangeData = {
export type TreeOpenChangeData<Value = string> = {
open: boolean;
value: Value;
} & ({
event: React_2.MouseEvent<HTMLElement>;
target: HTMLElement;
Expand All @@ -237,13 +260,13 @@ export type TreeOpenChangeData = {
export type TreeOpenChangeEvent = TreeOpenChangeData['event'];

// @public (undocumented)
export type TreeProps = ComponentProps<TreeSlots> & {
export type TreeProps<Value = string> = ComponentProps<TreeSlots> & {
appearance?: 'subtle' | 'subtle-alpha' | 'transparent';
size?: 'small' | 'medium';
openItems?: Iterable<TreeItemId>;
defaultOpenItems?: Iterable<TreeItemId>;
onOpenChange?(event: TreeOpenChangeEvent, data: TreeOpenChangeData): void;
onNavigation_unstable?(event: TreeNavigationEvent_unstable, data: TreeNavigationData_unstable): void;
openItems?: Iterable<Value>;
defaultOpenItems?: Iterable<Value>;
onOpenChange?(event: TreeOpenChangeEvent, data: TreeOpenChangeData<Value>): void;
onNavigation_unstable?(event: TreeNavigationEvent_unstable, data: TreeNavigationData_unstable<Value>): void;
};

// @public (undocumented)
Expand All @@ -258,7 +281,7 @@ export type TreeSlots = {
export type TreeState = ComponentState<TreeSlots> & TreeContextValue;

// @public
export function useFlatTree_unstable(flatTreeItemProps: FlatTreeItemProps[], options?: Pick<TreeProps, 'openItems' | 'defaultOpenItems' | 'onOpenChange' | 'onNavigation_unstable'>): FlatTree;
export function useFlatTree_unstable<Value = string>(flatTreeItemProps: FlatTreeItemProps<Value>[], options?: Pick<TreeProps<Value>, 'openItems' | 'defaultOpenItems' | 'onOpenChange' | 'onNavigation_unstable'>): FlatTree<Value>;

// @public
export const useTree_unstable: (props: TreeProps, ref: React_2.Ref<HTMLElement>) => TreeState;
Expand All @@ -270,7 +293,7 @@ export const useTreeContext_unstable: <T>(selector: ContextSelector<TreeContextV
export function useTreeContextValues_unstable(state: TreeState): TreeContextValues;

// @public
export const useTreeItem_unstable: (props: TreeItemProps, ref: React_2.Ref<HTMLDivElement>) => TreeItemState;
export function useTreeItem_unstable<Value = string>(props: TreeItemProps<Value>, ref: React_2.Ref<HTMLDivElement>): TreeItemState;

// @public (undocumented)
export const useTreeItemContext_unstable: () => TreeItemContextValue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ const FlatTree: React.FC<TreeProps> = (props: TreeProps) => {
return (
<Tree {...props} {...flatTree.getTreeProps()} id="tree" aria-label="Tree">
{Array.from(flatTree.items(), item => (
<TreeItem key={item.id} {...item.getTreeItemProps()} />
<TreeItem key={item.value} {...item.getTreeItemProps()} />
))}
</Tree>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ import { useTreeContextValues_unstable } from './useTreeContextValues';
* 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) => {
export const Tree = React.forwardRef((props, ref) => {
const state = useTree_unstable(props, ref);
useTreeStyles_unstable(state);
const contextValues = useTreeContextValues_unstable(state);
return renderTree_unstable(state, contextValues);
});
}) as ForwardRefComponent<TreeProps> & (<Value = string>(props: TreeProps<Value>) => JSX.Element);

Tree.displayName = 'Tree';
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,27 @@ import * as React from 'react';
import type { ComponentProps, ComponentState, Slot } from '@fluentui/react-utilities';
import { TreeContextValue } from '../../contexts/treeContext';
import { ArrowDown, ArrowLeft, ArrowRight, ArrowUp, End, Enter, Home } from '@fluentui/keyboard-keys';
import { TreeItemId } from '../TreeItem/TreeItem.types';

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

// eslint-disable-next-line @typescript-eslint/naming-convention
export type TreeNavigationData_unstable =
| { event: React.MouseEvent<HTMLElement>; target: HTMLElement; type: 'Click' }
| { event: React.KeyboardEvent<HTMLElement>; target: HTMLElement; type: 'TypeAhead' }
| { event: React.KeyboardEvent<HTMLElement>; target: HTMLElement; type: typeof ArrowRight }
| { event: React.KeyboardEvent<HTMLElement>; target: HTMLElement; type: typeof ArrowLeft }
| { event: React.KeyboardEvent<HTMLElement>; target: HTMLElement; type: typeof ArrowUp }
| { event: React.KeyboardEvent<HTMLElement>; target: HTMLElement; type: typeof ArrowDown }
| { event: React.KeyboardEvent<HTMLElement>; target: HTMLElement; type: typeof Home }
| { event: React.KeyboardEvent<HTMLElement>; target: HTMLElement; type: typeof End };
export type TreeNavigationData_unstable<Value = string> = { value: Value; target: HTMLElement } & (
| { event: React.MouseEvent<HTMLElement>; type: 'Click' }
| { event: React.KeyboardEvent<HTMLElement>; type: 'TypeAhead' }
| { event: React.KeyboardEvent<HTMLElement>; type: typeof ArrowRight }
| { event: React.KeyboardEvent<HTMLElement>; type: typeof ArrowLeft }
| { event: React.KeyboardEvent<HTMLElement>; type: typeof ArrowUp }
| { event: React.KeyboardEvent<HTMLElement>; type: typeof ArrowDown }
| { event: React.KeyboardEvent<HTMLElement>; type: typeof Home }
| { event: React.KeyboardEvent<HTMLElement>; type: typeof End }
);

// eslint-disable-next-line @typescript-eslint/naming-convention
export type TreeNavigationEvent_unstable = TreeNavigationData_unstable['event'];

export type TreeOpenChangeData = { open: boolean } & (
export type TreeOpenChangeData<Value = string> = { open: boolean; value: Value } & (
| {
event: React.MouseEvent<HTMLElement>;
target: HTMLElement;
Expand Down Expand Up @@ -56,7 +56,7 @@ export type TreeContextValues = {
tree: TreeContextValue;
};

export type TreeProps = ComponentProps<TreeSlots> & {
export type TreeProps<Value = string> = ComponentProps<TreeSlots> & {
/**
* A tree item can have various appearances:
* - 'subtle' (default): The default tree item styles.
Expand All @@ -75,13 +75,13 @@ export type TreeProps = ComponentProps<TreeSlots> & {
* Controls the state of the open tree items.
* These property is ignored for subtrees.
*/
openItems?: Iterable<TreeItemId>;
openItems?: Iterable<Value>;
/**
* This refers to a list of ids of opened tree items.
* Default value for the uncontrolled state of open tree items.
* These property is ignored for subtrees.
*/
defaultOpenItems?: Iterable<TreeItemId>;
defaultOpenItems?: Iterable<Value>;
/**
* Callback fired when the component changes value from open state.
* These property is ignored for subtrees.
Expand All @@ -90,7 +90,7 @@ export type TreeProps = ComponentProps<TreeSlots> & {
* @param data - A data object with relevant information,
* such as open value and type of interaction that created the event.
*/
onOpenChange?(event: TreeOpenChangeEvent, data: TreeOpenChangeData): void;
onOpenChange?(event: TreeOpenChangeEvent, data: TreeOpenChangeData<Value>): void;

/**
* Callback fired when navigation happens inside the component.
Expand All @@ -102,7 +102,7 @@ export type TreeProps = ComponentProps<TreeSlots> & {
* @param data - A data object with relevant information,
*/
// eslint-disable-next-line @typescript-eslint/naming-convention
onNavigation_unstable?(event: TreeNavigationEvent_unstable, data: TreeNavigationData_unstable): void;
onNavigation_unstable?(event: TreeNavigationEvent_unstable, data: TreeNavigationData_unstable<Value>): void;
};

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ import { useTreeItemContextValues_unstable } from './useTreeItemContextValues';
* The content and layout of a TreeItem can be defined using the TreeItemLayout or TreeItemPersonaLayout component,
* which should be used as a direct child of TreeItem.
*
* When a TreeItem has nsted child subtree, an expand/collapse control is displayed,
* When a TreeItem has nested child subtree, an expand/collapse control is displayed,
* allowing the user to show or hide the children.
*/
export const TreeItem: ForwardRefComponent<TreeItemProps> = React.forwardRef((props, ref) => {
export const TreeItem = React.forwardRef((props, ref) => {
const state = useTreeItem_unstable(props, ref);

useTreeItemStyles_unstable(state);
const contextValues = useTreeItemContextValues_unstable(state);
return renderTreeItem_unstable(state, contextValues);
});
}) as ForwardRefComponent<TreeItemProps> & (<Value = string>(props: TreeItemProps<Value>) => JSX.Element);

TreeItem.displayName = 'TreeItem';
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { treeItemLevelToken } from '../../utils/tokens';
import * as React from 'react';

export type TreeItemCSSProperties = React.CSSProperties & { [treeItemLevelToken]?: string | number };
export type TreeItemId = string;

export type TreeItemSlots = {
root: Slot<ExtractSlotProps<Slot<'div'> & { style?: TreeItemCSSProperties }>>;
Expand All @@ -31,7 +30,8 @@ export type TreeItemContextValues = {
/**
* TreeItem Props
*/
export type TreeItemProps = ComponentProps<Partial<TreeItemSlots>> & {
export type TreeItemProps<Value = string> = ComponentProps<Partial<TreeItemSlots>> & {
value?: Value;
/**
* If a TreeItem is a leaf, it'll not present the `expandIcon` slot by default.
* This attribute is used to force the decision if a TreeItem is a leaf or not. By not providing this property
Expand Down
Loading

0 comments on commit 4dde672

Please sign in to comment.