Private
Public Access
1
0

feat: Fluent UI Outlook Lite + connections mockup

This commit is contained in:
2026-04-14 18:52:25 +00:00
parent 1199eff6c3
commit dfa4010406
34820 changed files with 1003813 additions and 205 deletions

View File

@@ -0,0 +1,119 @@
'use client';
import { useEventCallback, useMergedRefs } from '@fluentui/react-utilities';
import * as React from 'react';
import { createHeadlessTree } from '../../utils/createHeadlessTree';
import { treeDataTypes } from '../../utils/tokens';
import { useFlatTreeNavigation } from '../../hooks/useFlatTreeNavigation';
import { createNextOpenItems, useControllableOpenItems } from '../../hooks/useControllableOpenItems';
import { dataTreeItemValueAttrName } from '../../utils/getTreeItemValueFromElement';
import { ImmutableSet } from '../../utils/ImmutableSet';
import { createNextFlatCheckedItems, useFlatControllableCheckedItems } from './useFlatControllableCheckedItems';
import { ImmutableMap } from '../../utils/ImmutableMap';
/**
* this hook provides FlatTree API to manage all required mechanisms to convert a list of items into renderable TreeItems
* in multiple scenarios including virtualization.
*
* !!A flat tree is an unofficial spec for tree!!
*
* It should be used on cases where more complex interactions with a Tree is required.
* On simple scenarios it is advised to simply use a nested structure instead.
*
* @param props - a list of tree items
* @param options - in case control over the internal openItems is required
*/ export function useHeadlessFlatTree_unstable(props, options = {}) {
'use no memo';
const headlessTree = React.useMemo(()=>createHeadlessTree(props), [
props
]);
const [openItems, setOpenItems] = useControllableOpenItems(options);
const [checkedItems, setCheckedItems] = useFlatControllableCheckedItems(options, headlessTree);
const navigation = useFlatTreeNavigation();
const treeRef = React.useRef(null);
const handleOpenChange = useEventCallback((event, data)=>{
var _options_onOpenChange;
const nextOpenItems = createNextOpenItems(data, openItems);
(_options_onOpenChange = options.onOpenChange) === null || _options_onOpenChange === void 0 ? void 0 : _options_onOpenChange.call(options, event, {
...data,
openItems: ImmutableSet.dangerouslyGetInternalSet(nextOpenItems)
});
setOpenItems(nextOpenItems);
});
const handleCheckedChange = useEventCallback((event, data)=>{
var _options_onCheckedChange;
const nextCheckedItems = createNextFlatCheckedItems(data, checkedItems, headlessTree);
(_options_onCheckedChange = options.onCheckedChange) === null || _options_onCheckedChange === void 0 ? void 0 : _options_onCheckedChange.call(options, event, {
...data,
checkedItems: ImmutableMap.dangerouslyGetInternalMap(nextCheckedItems)
});
setCheckedItems(nextCheckedItems);
});
const getNextNavigableItem = useEventCallback((visibleItems, data)=>{
const item = headlessTree.get(data.value);
if (item) {
switch(data.type){
case treeDataTypes.TypeAhead:
return item;
case treeDataTypes.ArrowLeft:
return headlessTree.get(item.parentValue);
case treeDataTypes.ArrowRight:
return visibleItems[item.index + 1];
case treeDataTypes.End:
return visibleItems[visibleItems.length - 1];
case treeDataTypes.Home:
return visibleItems[0];
case treeDataTypes.ArrowDown:
return visibleItems[item.index + 1];
case treeDataTypes.ArrowUp:
return visibleItems[item.index - 1];
}
}
});
const getElementFromItem = React.useCallback((item)=>{
var _treeRef_current;
return (_treeRef_current = treeRef.current) === null || _treeRef_current === void 0 ? void 0 : _treeRef_current.querySelector(`[${dataTreeItemValueAttrName}="${item.value}"]`);
}, []);
const ref = useMergedRefs(treeRef, navigation.rootRef);
const getTreeProps = React.useCallback(()=>{
var _options_onNavigation;
return {
ref,
openItems,
selectionMode: options.selectionMode,
checkedItems,
onOpenChange: handleOpenChange,
onCheckedChange: handleCheckedChange,
onNavigation: (_options_onNavigation = options.onNavigation) !== null && _options_onNavigation !== void 0 ? _options_onNavigation : noop
};
}, // ref, handleOpenChange - useEventCallback, handleCheckedChange - useEventCallback
// eslint-disable-next-line react-hooks/exhaustive-deps
[
openItems,
checkedItems,
options.selectionMode,
options.onNavigation
]);
const items = React.useCallback(()=>headlessTree.visibleItems(openItems), [
openItems,
headlessTree
]);
const getItem = React.useCallback((value)=>headlessTree.get(value), [
headlessTree
]);
return React.useMemo(()=>({
navigate: navigation.navigate,
getTreeProps,
getNextNavigableItem,
getElementFromItem,
items,
getItem
}), [
navigation.navigate,
getTreeProps,
getNextNavigableItem,
getElementFromItem,
items,
getItem
]);
}
/** @internal */ function noop() {
/* noop */ }