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,35 @@
'use client';
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
createNextOpenItems: function() {
return createNextOpenItems;
},
useControllableOpenItems: function() {
return useControllableOpenItems;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _reactutilities = require("@fluentui/react-utilities");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
const _ImmutableSet = require("../utils/ImmutableSet");
function useControllableOpenItems(props) {
return (0, _reactutilities.useControllableState)({
state: _react.useMemo(()=>props.openItems && _ImmutableSet.ImmutableSet.from(props.openItems), [
props.openItems
]),
defaultState: props.defaultOpenItems && (()=>_ImmutableSet.ImmutableSet.from(props.defaultOpenItems)),
initialState: _ImmutableSet.ImmutableSet.empty
});
}
function createNextOpenItems(data, previousOpenItems) {
return data.open ? previousOpenItems.add(data.value) : previousOpenItems.delete(data.value);
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useControllableOpenItems.ts"],"sourcesContent":["'use client';\n\nimport { useControllableState } from '@fluentui/react-utilities';\nimport * as React from 'react';\nimport { ImmutableSet } from '../utils/ImmutableSet';\nimport type { TreeItemValue } from '../components/TreeItem/TreeItem.types';\nimport { TreeOpenChangeData, TreeProps } from '../Tree';\n\n/**\n * @internal\n */\nexport function useControllableOpenItems(\n props: Pick<TreeProps, 'openItems' | 'defaultOpenItems'>,\n): [ImmutableSet<TreeItemValue>, React.Dispatch<React.SetStateAction<ImmutableSet<TreeItemValue>>>] {\n return useControllableState({\n state: React.useMemo(() => props.openItems && ImmutableSet.from(props.openItems), [props.openItems]),\n defaultState: props.defaultOpenItems && (() => ImmutableSet.from(props.defaultOpenItems)),\n initialState: ImmutableSet.empty,\n });\n}\n\n/**\n * @internal\n */\nexport function createNextOpenItems(\n data: Pick<TreeOpenChangeData, 'value' | 'open'>,\n previousOpenItems: ImmutableSet<TreeItemValue>,\n): ImmutableSet<TreeItemValue> {\n return data.open ? previousOpenItems.add(data.value) : previousOpenItems.delete(data.value);\n}\n"],"names":["useControllableState","React","ImmutableSet","useControllableOpenItems","props","state","useMemo","openItems","from","defaultState","defaultOpenItems","initialState","empty","createNextOpenItems","data","previousOpenItems","open","add","value","delete"],"mappings":"AAAA;;;;;;;;;;;;uBAwBgBa;;;4BAbAV;;;;;gCATqB,4BAA4B;iEAC1C,QAAQ;8BACF,wBAAwB;AAO9C,SAASA,yBACdC,KAAwD;IAExD,WAAOJ,oCAAAA,EAAqB;QAC1BK,OAAOJ,OAAMK,OAAO,CAAC,IAAMF,MAAMG,SAAS,IAAIL,0BAAAA,CAAaM,IAAI,CAACJ,MAAMG,SAAS,GAAG;YAACH,MAAMG,SAAS;SAAC;QACnGE,cAAcL,MAAMM,gBAAgB,IAAK,KAAMR,0BAAAA,CAAaM,IAAI,CAACJ,MAAMM,iBAAgB,CAAA;QACvFC,cAAcT,0BAAAA,CAAaU,KAAK;IAClC;AACF;AAKO,SAASC,oBACdC,IAAgD,EAChDC,iBAA8C;IAE9C,OAAOD,KAAKE,IAAI,GAAGD,kBAAkBE,GAAG,CAACH,KAAKI,KAAK,IAAIH,kBAAkBI,MAAM,CAACL,KAAKI,KAAK;AAC5F"}

View File

@@ -0,0 +1,127 @@
'use client';
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "useFlatTreeNavigation", {
enumerable: true,
get: function() {
return useFlatTreeNavigation;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _reactutilities = require("@fluentui/react-utilities");
const _nextTypeAheadElement = require("../utils/nextTypeAheadElement");
const _tokens = require("../utils/tokens");
const _useRovingTabIndexes = require("./useRovingTabIndexes");
const _getTreeItemValueFromElement = require("../utils/getTreeItemValueFromElement");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
const _useHTMLElementWalkerRef = require("./useHTMLElementWalkerRef");
const _reacttabster = require("@fluentui/react-tabster");
const _TreeItemLayout = require("../TreeItemLayout");
function useFlatTreeNavigation(navigationMode = 'tree') {
'use no memo';
const { walkerRef, rootRef: walkerRootRef } = (0, _useHTMLElementWalkerRef.useHTMLElementWalkerRef)();
const { rove, forceUpdate: forceUpdateRovingTabIndex, initialize: initializeRovingTabIndex } = (0, _useRovingTabIndexes.useRovingTabIndex)();
const { findFirstFocusable } = (0, _reacttabster.useFocusFinders)();
const rootRefCallback = _react.useCallback((root)=>{
if (walkerRef.current && root) {
initializeRovingTabIndex(walkerRef.current);
}
}, [
initializeRovingTabIndex,
walkerRef
]);
function getNextElement(data) {
if (!walkerRef.current) {
return null;
}
switch(data.type){
case _tokens.treeDataTypes.Click:
return data.target;
case _tokens.treeDataTypes.TypeAhead:
walkerRef.current.currentElement = data.target;
return (0, _nextTypeAheadElement.nextTypeAheadElement)(walkerRef.current, data.event.key);
case _tokens.treeDataTypes.ArrowLeft:
{
const actions = queryActions(data.target);
if (navigationMode === 'treegrid' && (actions === null || actions === void 0 ? void 0 : actions.contains(data.target.ownerDocument.activeElement))) {
return data.target;
}
const nextElement = parentElement(data.parentValue, walkerRef.current);
if (!nextElement && process.env.NODE_ENV !== 'production') {
// eslint-disable-next-line no-console
console.warn(`@fluentui/react-tree [useFlatTreeNavigation]:
\'ArrowLeft\' navigation was not possible.
No parent element found for the current element:`, data.target);
}
return nextElement;
}
case _tokens.treeDataTypes.ArrowRight:
{
if (navigationMode === 'treegrid') {
const actions = queryActions(data.target);
if (actions) {
var _findFirstFocusable;
(_findFirstFocusable = findFirstFocusable(actions)) === null || _findFirstFocusable === void 0 ? void 0 : _findFirstFocusable.focus();
}
return null;
}
walkerRef.current.currentElement = data.target;
const nextElement = firstChild(data.target, walkerRef.current);
if (!nextElement && process.env.NODE_ENV !== 'production') {
const ariaLevel = Number(data.target.getAttribute('aria-level'));
// eslint-disable-next-line no-console
console.warn(`@fluentui/react-tree [useFlatTreeNavigation]:
\'ArrowRight\' navigation was not possible.
No element with "aria-posinset=1" and "aria-level=${ariaLevel + 1}"
was found after the current element!`, data.target);
}
return nextElement;
}
case _tokens.treeDataTypes.End:
walkerRef.current.currentElement = walkerRef.current.root;
return walkerRef.current.lastChild();
case _tokens.treeDataTypes.Home:
walkerRef.current.currentElement = walkerRef.current.root;
return walkerRef.current.firstChild();
case _tokens.treeDataTypes.ArrowDown:
walkerRef.current.currentElement = data.target;
return walkerRef.current.nextElement();
case _tokens.treeDataTypes.ArrowUp:
walkerRef.current.currentElement = data.target;
return walkerRef.current.previousElement();
}
}
const navigate = (0, _reactutilities.useEventCallback)((data)=>{
const nextElement = getNextElement(data);
if (nextElement) {
rove(nextElement);
}
});
return {
navigate,
rootRef: (0, _reactutilities.useMergedRefs)(walkerRootRef, rootRefCallback),
forceUpdateRovingTabIndex
};
}
function firstChild(target, treeWalker) {
const nextElement = treeWalker.nextElement();
if (!nextElement) {
return null;
}
const nextElementAriaPosInSet = nextElement.getAttribute('aria-posinset');
const nextElementAriaLevel = nextElement.getAttribute('aria-level');
const targetAriaLevel = target.getAttribute('aria-level');
if (nextElementAriaPosInSet === '1' && Number(nextElementAriaLevel) === Number(targetAriaLevel) + 1) {
return nextElement;
}
return null;
}
function parentElement(parentValue, treeWalker) {
if (parentValue === undefined) {
return null;
}
return treeWalker.root.querySelector(`[${_getTreeItemValueFromElement.dataTreeItemValueAttrName}="${parentValue}"]`);
}
const queryActions = (target)=>target.querySelector(`:scope > .${_TreeItemLayout.treeItemLayoutClassNames.root} > .${_TreeItemLayout.treeItemLayoutClassNames.actions}`);

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,29 @@
'use client';
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "useHTMLElementWalkerRef", {
enumerable: true,
get: function() {
return useHTMLElementWalkerRef;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
const _reactsharedcontexts = require("@fluentui/react-shared-contexts");
const _createHTMLElementWalker = require("../utils/createHTMLElementWalker");
const _treeItemFilter = require("../utils/treeItemFilter");
function useHTMLElementWalkerRef() {
const { targetDocument } = (0, _reactsharedcontexts.useFluent_unstable)();
const walkerRef = _react.useRef(undefined);
const rootRef = _react.useCallback((root)=>{
walkerRef.current = targetDocument && root ? (0, _createHTMLElementWalker.createHTMLElementWalker)(root, targetDocument, _treeItemFilter.treeItemFilter) : undefined;
}, [
targetDocument
]);
return {
walkerRef,
rootRef
};
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useHTMLElementWalkerRef.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { useFluent_unstable } from '@fluentui/react-shared-contexts';\nimport { HTMLElementWalker, createHTMLElementWalker } from '../utils/createHTMLElementWalker';\nimport { treeItemFilter } from '../utils/treeItemFilter';\n\nexport function useHTMLElementWalkerRef(): {\n // eslint-disable-next-line @typescript-eslint/no-deprecated\n walkerRef: React.MutableRefObject<HTMLElementWalker | undefined>;\n rootRef: React.Ref<HTMLElement>;\n} {\n const { targetDocument } = useFluent_unstable();\n\n const walkerRef = React.useRef<HTMLElementWalker>(undefined);\n\n const rootRef: React.Ref<HTMLElement> = React.useCallback(\n (root: HTMLElement) => {\n walkerRef.current =\n targetDocument && root ? createHTMLElementWalker(root, targetDocument, treeItemFilter) : undefined;\n },\n [targetDocument],\n );\n return { walkerRef, rootRef } as const;\n}\n"],"names":["React","useFluent_unstable","createHTMLElementWalker","treeItemFilter","useHTMLElementWalkerRef","targetDocument","walkerRef","useRef","undefined","rootRef","useCallback","root","current"],"mappings":"AAAA;;;;;;;;;;;;iEAEuB,QAAQ;qCACI,kCAAkC;yCACV,mCAAmC;gCAC/D,0BAA0B;AAElD,SAASI;IAKd,MAAM,EAAEC,cAAc,EAAE,OAAGJ,uCAAAA;IAE3B,MAAMK,YAAYN,OAAMO,MAAM,CAAoBC;IAElD,MAAMC,UAAkCT,OAAMU,WAAW,CACvD,CAACC;QACCL,UAAUM,OAAO,GACfP,kBAAkBM,WAAOT,gDAAAA,EAAwBS,MAAMN,gBAAgBF,8BAAAA,IAAkBK;IAC7F,GACA;QAACH;KAAe;IAElB,OAAO;QAAEC;QAAWG;IAAQ;AAC9B"}

View File

@@ -0,0 +1,119 @@
'use client';
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "useRootTree", {
enumerable: true,
get: function() {
return useRootTree;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _reactutilities = require("@fluentui/react-utilities");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
const _reactmotioncomponentspreview = require("@fluentui/react-motion-components-preview");
const _createCheckedItems = require("../utils/createCheckedItems");
const _tokens = require("../utils/tokens");
const _useControllableOpenItems = require("./useControllableOpenItems");
const _ImmutableSet = require("../utils/ImmutableSet");
const _ImmutableMap = require("../utils/ImmutableMap");
function useRootTree(props, ref) {
warnIfNoProperPropsRootTree(props);
const { appearance = 'subtle', size = 'medium', selectionMode = 'none' } = props;
const openItems = _react.useMemo(()=>_ImmutableSet.ImmutableSet.from(props.openItems), [
props.openItems
]);
const checkedItems = _react.useMemo(()=>(0, _createCheckedItems.createCheckedItems)(props.checkedItems), [
props.checkedItems
]);
const requestOpenChange = (request)=>{
var _props_onOpenChange;
(_props_onOpenChange = props.onOpenChange) === null || _props_onOpenChange === void 0 ? void 0 : _props_onOpenChange.call(props, request.event, {
...request,
openItems: _ImmutableSet.ImmutableSet.dangerouslyGetInternalSet((0, _useControllableOpenItems.createNextOpenItems)(request, openItems))
});
};
const requestCheckedChange = (request)=>{
var _props_onCheckedChange;
if (selectionMode === 'none') {
return;
}
(_props_onCheckedChange = props.onCheckedChange) === null || _props_onCheckedChange === void 0 ? void 0 : _props_onCheckedChange.call(props, request.event, {
...request,
selectionMode,
checkedItems: _ImmutableMap.ImmutableMap.dangerouslyGetInternalMap(checkedItems)
});
};
const requestNavigation = (request)=>{
var _props_onNavigation;
let isScrollPrevented = false;
(_props_onNavigation = props.onNavigation) === null || _props_onNavigation === void 0 ? void 0 : _props_onNavigation.call(props, request.event, {
...request,
preventScroll: ()=>{
isScrollPrevented = true;
},
isScrollPrevented: ()=>isScrollPrevented
});
switch(request.type){
case _tokens.treeDataTypes.ArrowDown:
case _tokens.treeDataTypes.ArrowUp:
case _tokens.treeDataTypes.Home:
case _tokens.treeDataTypes.End:
// stop the default behavior of the event
// which is to scroll the page
request.event.preventDefault();
}
};
const requestTreeResponse = (0, _reactutilities.useEventCallback)((request)=>{
switch(request.requestType){
case 'navigate':
return requestNavigation(request);
case 'open':
return requestOpenChange(request);
case 'selection':
return requestCheckedChange(request);
}
});
var _props_navigationMode;
return {
components: {
root: 'div',
collapseMotion: _reactmotioncomponentspreview.Collapse
},
contextType: 'root',
selectionMode,
navigationMode: (_props_navigationMode = props.navigationMode) !== null && _props_navigationMode !== void 0 ? _props_navigationMode : 'tree',
open: true,
appearance,
size,
level: 1,
openItems,
checkedItems,
requestTreeResponse,
forceUpdateRovingTabIndex: ()=>{
// noop
},
root: _reactutilities.slot.always((0, _reactutilities.getIntrinsicElementProps)('div', {
// FIXME:
// `ref` is wrongly assigned to be `HTMLElement` instead of `HTMLDivElement`
// but since it would be a breaking change to fix it, we are casting ref to it's proper type
ref: ref,
role: 'tree',
'aria-multiselectable': selectionMode === 'multiselect' ? true : undefined,
...props
}), {
elementType: 'div'
}),
collapseMotion: undefined
};
}
function warnIfNoProperPropsRootTree(props) {
if (process.env.NODE_ENV === 'development') {
if (!props['aria-label'] && !props['aria-labelledby']) {
// eslint-disable-next-line no-console
console.warn(`@fluentui/react-tree [useRootTree]:
Tree must have either a \`aria-label\` or \`aria-labelledby\` property defined`);
}
}
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,74 @@
'use client';
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "useRovingTabIndex", {
enumerable: true,
get: function() {
return useRovingTabIndex;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
const _reactsharedcontexts = require("@fluentui/react-shared-contexts");
const _reacttabster = require("@fluentui/react-tabster");
const findTreeItemRoot = (element)=>{
let parent = element.parentElement;
while(parent && parent.getAttribute('role') !== 'tree'){
parent = parent.parentElement;
}
return parent;
};
function useRovingTabIndex() {
const currentElementRef = _react.useRef(null);
const walkerRef = _react.useRef(null);
const { targetDocument } = (0, _reactsharedcontexts.useFluent_unstable)();
(0, _reacttabster.useFocusedElementChange)((element)=>{
if ((element === null || element === void 0 ? void 0 : element.getAttribute('role')) === 'treeitem' && walkerRef.current && walkerRef.current.root.contains(element)) {
const treeitemRoot = findTreeItemRoot(element);
if (walkerRef.current.root !== treeitemRoot) {
return;
}
rove(element);
}
});
const initialize = _react.useCallback((walker)=>{
walkerRef.current = walker;
walker.currentElement = walker.root;
let tabbableChild = walker.firstChild((element)=>element.tabIndex === 0 ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP);
walker.currentElement = walker.root;
tabbableChild !== null && tabbableChild !== void 0 ? tabbableChild : tabbableChild = walker.firstChild();
if (!tabbableChild) {
return;
}
tabbableChild.tabIndex = 0;
currentElementRef.current = tabbableChild;
let nextElement = null;
while((nextElement = walker.nextElement()) && nextElement !== tabbableChild){
nextElement.tabIndex = -1;
}
}, []);
const rove = _react.useCallback((nextElement, focusOptions)=>{
if (!currentElementRef.current) {
return;
}
currentElementRef.current.tabIndex = -1;
nextElement.tabIndex = 0;
nextElement.focus(focusOptions);
currentElementRef.current = nextElement;
}, []);
const forceUpdate = _react.useCallback(()=>{
if ((currentElementRef.current === null || !(targetDocument === null || targetDocument === void 0 ? void 0 : targetDocument.body.contains(currentElementRef.current))) && walkerRef.current) {
initialize(walkerRef.current);
}
}, [
targetDocument,
initialize
]);
return {
rove,
initialize,
forceUpdate
};
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useRovingTabIndexes.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';\nimport { HTMLElementWalker } from '../utils/createHTMLElementWalker';\nimport { useFocusedElementChange } from '@fluentui/react-tabster';\n\nconst findTreeItemRoot = (element: HTMLElement) => {\n let parent = element.parentElement;\n while (parent && parent.getAttribute('role') !== 'tree') {\n parent = parent.parentElement;\n }\n return parent;\n};\n\n/**\n * https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_roving_tabindex\n *\n * @internal\n */\nexport function useRovingTabIndex(): {\n rove: (nextElement: HTMLElement, focusOptions?: FocusOptions) => void;\n initialize: (walker: HTMLElementWalker) => void;\n forceUpdate: () => void;\n} {\n const currentElementRef = React.useRef<HTMLElement | null>(null);\n const walkerRef = React.useRef<HTMLElementWalker | null>(null);\n const { targetDocument } = useFluent();\n\n useFocusedElementChange(element => {\n if (element?.getAttribute('role') === 'treeitem' && walkerRef.current && walkerRef.current.root.contains(element)) {\n const treeitemRoot = findTreeItemRoot(element);\n if (walkerRef.current.root !== treeitemRoot) {\n return;\n }\n rove(element);\n }\n });\n\n const initialize = React.useCallback((walker: HTMLElementWalker) => {\n walkerRef.current = walker;\n walker.currentElement = walker.root;\n let tabbableChild = walker.firstChild(element =>\n element.tabIndex === 0 ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP,\n );\n walker.currentElement = walker.root;\n tabbableChild ??= walker.firstChild();\n if (!tabbableChild) {\n return;\n }\n tabbableChild.tabIndex = 0;\n currentElementRef.current = tabbableChild;\n let nextElement: HTMLElement | null = null;\n while ((nextElement = walker.nextElement()) && nextElement !== tabbableChild) {\n nextElement.tabIndex = -1;\n }\n }, []);\n const rove = React.useCallback((nextElement: HTMLElement, focusOptions?: FocusOptions) => {\n if (!currentElementRef.current) {\n return;\n }\n currentElementRef.current.tabIndex = -1;\n nextElement.tabIndex = 0;\n nextElement.focus(focusOptions);\n currentElementRef.current = nextElement;\n }, []);\n\n const forceUpdate = React.useCallback(() => {\n if (\n (currentElementRef.current === null || !targetDocument?.body.contains(currentElementRef.current)) &&\n walkerRef.current\n ) {\n initialize(walkerRef.current);\n }\n }, [targetDocument, initialize]);\n\n return {\n rove,\n initialize,\n forceUpdate,\n };\n}\n"],"names":["React","useFluent_unstable","useFluent","useFocusedElementChange","findTreeItemRoot","element","parent","parentElement","getAttribute","useRovingTabIndex","currentElementRef","useRef","walkerRef","targetDocument","current","root","contains","treeitemRoot","rove","initialize","useCallback","walker","currentElement","tabbableChild","firstChild","tabIndex","NodeFilter","FILTER_ACCEPT","FILTER_SKIP","nextElement","focusOptions","focus","forceUpdate","body"],"mappings":"AAAA;;;;;+BAoBgBS;;;;;;;iEAlBO,QAAQ;qCACiB,kCAAkC;8BAE1C,0BAA0B;AAElE,MAAML,mBAAmB,CAACC;IACxB,IAAIC,SAASD,QAAQE,aAAa;IAClC,MAAOD,UAAUA,OAAOE,YAAY,CAAC,YAAY,OAAQ;QACvDF,SAASA,OAAOC,aAAa;IAC/B;IACA,OAAOD;AACT;AAOO;IAKL,MAAMI,oBAAoBV,OAAMW,MAAM,CAAqB;IAC3D,MAAMC,YAAYZ,OAAMW,MAAM,CAA2B;IACzD,MAAM,EAAEE,cAAc,EAAE,OAAGX,uCAAAA;QAE3BC,qCAAAA,EAAwBE,CAAAA;QACtB,IAAIA,CAAAA,YAAAA,QAAAA,YAAAA,KAAAA,IAAAA,KAAAA,IAAAA,QAASG,YAAY,CAAC,OAAA,MAAY,cAAcI,UAAUE,OAAO,IAAIF,UAAUE,OAAO,CAACC,IAAI,CAACC,QAAQ,CAACX,UAAU;YACjH,MAAMY,eAAeb,iBAAiBC;YACtC,IAAIO,UAAUE,OAAO,CAACC,IAAI,KAAKE,cAAc;gBAC3C;YACF;YACAC,KAAKb;QACP;IACF;IAEA,MAAMc,aAAanB,OAAMoB,WAAW,CAAC,CAACC;QACpCT,UAAUE,OAAO,GAAGO;QACpBA,OAAOC,cAAc,GAAGD,OAAON,IAAI;QACnC,IAAIQ,gBAAgBF,OAAOG,UAAU,CAACnB,CAAAA,UACpCA,QAAQoB,QAAQ,KAAK,IAAIC,WAAWC,aAAa,GAAGD,WAAWE,WAAW;QAE5EP,OAAOC,cAAc,GAAGD,OAAON,IAAI;QACnCQ,kBAAAA,QAAAA,kBAAAA,KAAAA,IAAAA,gBAAAA,gBAAkBF,OAAOG,UAAU;QACnC,IAAI,CAACD,eAAe;YAClB;QACF;QACAA,cAAcE,QAAQ,GAAG;QACzBf,kBAAkBI,OAAO,GAAGS;QAC5B,IAAIM,cAAkC;QACtC,MAAQA,CAAAA,cAAcR,OAAOQ,WAAW,EAAA,CAAC,IAAMA,gBAAgBN,cAAe;YAC5EM,YAAYJ,QAAQ,GAAG,CAAC;QAC1B;IACF,GAAG,EAAE;IACL,MAAMP,OAAOlB,OAAMoB,WAAW,CAAC,CAACS,aAA0BC;QACxD,IAAI,CAACpB,kBAAkBI,OAAO,EAAE;YAC9B;QACF;QACAJ,kBAAkBI,OAAO,CAACW,QAAQ,GAAG,CAAC;QACtCI,YAAYJ,QAAQ,GAAG;QACvBI,YAAYE,KAAK,CAACD;QAClBpB,kBAAkBI,OAAO,GAAGe;IAC9B,GAAG,EAAE;IAEL,MAAMG,cAAchC,OAAMoB,WAAW,CAAC;QACpC,IACGV,CAAAA,kBAAkBI,OAAO,KAAK,QAAQ,EAACD,mBAAAA,QAAAA,mBAAAA,KAAAA,IAAAA,KAAAA,IAAAA,eAAgBoB,IAAI,CAACjB,QAAQ,CAACN,kBAAkBI,QAAO,CAAA,CAAA,IAC/FF,UAAUE,OAAO,EACjB;YACAK,WAAWP,UAAUE,OAAO;QAC9B;IACF,GAAG;QAACD;QAAgBM;KAAW;IAE/B,OAAO;QACLD;QACAC;QACAa;IACF;AACF"}

View File

@@ -0,0 +1,48 @@
'use client';
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "useSubtree", {
enumerable: true,
get: function() {
return useSubtree;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
const _index = require("../contexts/index");
const _reactutilities = require("@fluentui/react-utilities");
const _reactmotioncomponentspreview = require("@fluentui/react-motion-components-preview");
const _reactmotion = require("@fluentui/react-motion");
function useSubtree(props, ref) {
const subtreeRef = (0, _index.useTreeItemContext_unstable)((ctx)=>ctx.subtreeRef);
const { level: parentLevel } = (0, _index.useSubtreeContext_unstable)();
const open = (0, _index.useTreeItemContext_unstable)((ctx)=>ctx.open);
return {
contextType: 'subtree',
open,
components: {
root: 'div',
collapseMotion: _reactmotioncomponentspreview.Collapse
},
level: parentLevel + 1,
root: _reactutilities.slot.always((0, _reactutilities.getIntrinsicElementProps)('div', {
// FIXME:
// `ref` is wrongly assigned to be `HTMLElement` instead of `HTMLDivElement`
// but since it would be a breaking change to fix it, we are casting ref to it's proper type
ref: (0, _reactutilities.useMergedRefs)(ref, subtreeRef),
role: 'group',
...props
}), {
elementType: 'div'
}),
collapseMotion: (0, _reactmotion.presenceMotionSlot)(props.collapseMotion, {
elementType: _reactmotioncomponentspreview.Collapse,
defaultProps: {
visible: open,
unmountOnExit: true
}
})
};
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useSubtree.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { TreeProps, TreeState } from '../Tree';\nimport { SubtreeContextValue, useSubtreeContext_unstable, useTreeItemContext_unstable } from '../contexts/index';\nimport { getIntrinsicElementProps, useMergedRefs, slot } from '@fluentui/react-utilities';\nimport { Collapse } from '@fluentui/react-motion-components-preview';\nimport { presenceMotionSlot } from '@fluentui/react-motion';\n\n/**\n * Create the state required to render a sub-level tree.\n *\n * @param props - props from this instance of tree\n * @param ref - reference to root HTMLElement of tree\n */\nexport function useSubtree(\n props: TreeProps,\n ref: React.Ref<HTMLElement>,\n): Omit<TreeState & SubtreeContextValue, 'treeType'> {\n const subtreeRef = useTreeItemContext_unstable(ctx => ctx.subtreeRef);\n\n const { level: parentLevel } = useSubtreeContext_unstable();\n\n const open = useTreeItemContext_unstable(ctx => ctx.open);\n\n return {\n contextType: 'subtree',\n open,\n components: {\n root: 'div',\n collapseMotion: Collapse,\n },\n level: parentLevel + 1,\n root: slot.always(\n getIntrinsicElementProps('div', {\n // FIXME:\n // `ref` is wrongly assigned to be `HTMLElement` instead of `HTMLDivElement`\n // but since it would be a breaking change to fix it, we are casting ref to it's proper type\n ref: useMergedRefs(ref, subtreeRef) as React.Ref<HTMLDivElement>,\n role: 'group',\n ...props,\n }),\n { elementType: 'div' },\n ),\n collapseMotion: presenceMotionSlot(props.collapseMotion, {\n elementType: Collapse,\n defaultProps: {\n visible: open,\n unmountOnExit: true,\n },\n }),\n };\n}\n"],"names":["React","useSubtreeContext_unstable","useTreeItemContext_unstable","getIntrinsicElementProps","useMergedRefs","slot","Collapse","presenceMotionSlot","useSubtree","props","ref","subtreeRef","ctx","level","parentLevel","open","contextType","components","root","collapseMotion","always","role","elementType","defaultProps","visible","unmountOnExit"],"mappings":"AAAA;;;;;+BAegBQ;;;;;;;iEAbO,QAAQ;uBAE8D,oBAAoB;gCACnD,4BAA4B;8CACjE,4CAA4C;6BAClC,yBAAyB;AAQrD,oBACLC,KAAgB,EAChBC,GAA2B;IAE3B,MAAMC,iBAAaT,kCAAAA,EAA4BU,CAAAA,MAAOA,IAAID,UAAU;IAEpE,MAAM,EAAEE,OAAOC,WAAW,EAAE,GAAGb,qCAAAA;IAE/B,MAAMc,WAAOb,kCAAAA,EAA4BU,CAAAA,MAAOA,IAAIG,IAAI;IAExD,OAAO;QACLC,aAAa;QACbD;QACAE,YAAY;YACVC,MAAM;YACNC,gBAAgBb,sCAAAA;QAClB;QACAO,OAAOC,cAAc;QACrBI,MAAMb,oBAAAA,CAAKe,MAAM,KACfjB,wCAAAA,EAAyB,OAAO;YAC9B,SAAS;YACT,4EAA4E;YAC5E,4FAA4F;YAC5FO,SAAKN,6BAAAA,EAAcM,KAAKC;YACxBU,MAAM;YACN,GAAGZ,KAAK;QACV,IACA;YAAEa,aAAa;QAAM;QAEvBH,oBAAgBZ,+BAAAA,EAAmBE,MAAMU,cAAc,EAAE;YACvDG,aAAahB,sCAAAA;YACbiB,cAAc;gBACZC,SAAST;gBACTU,eAAe;YACjB;QACF;IACF;AACF"}

View File

@@ -0,0 +1,99 @@
'use client';
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "useTreeNavigation", {
enumerable: true,
get: function() {
return useTreeNavigation;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _nextTypeAheadElement = require("../utils/nextTypeAheadElement");
const _tokens = require("../utils/tokens");
const _useRovingTabIndexes = require("./useRovingTabIndexes");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
const _useHTMLElementWalkerRef = require("./useHTMLElementWalkerRef");
const _reactutilities = require("@fluentui/react-utilities");
const _TreeItemLayout = require("../TreeItemLayout");
const _reacttabster = require("@fluentui/react-tabster");
function useTreeNavigation(navigationMode = 'tree') {
'use no memo';
const { rove, initialize: initializeRovingTabIndex, forceUpdate: forceUpdateRovingTabIndex } = (0, _useRovingTabIndexes.useRovingTabIndex)();
const { findFirstFocusable } = (0, _reacttabster.useFocusFinders)();
const { walkerRef, rootRef: walkerRootRef } = (0, _useHTMLElementWalkerRef.useHTMLElementWalkerRef)();
const rootRefCallback = _react.useCallback((root)=>{
if (root && walkerRef.current) {
initializeRovingTabIndex(walkerRef.current);
}
}, [
walkerRef,
initializeRovingTabIndex
]);
const getNextElement = (data)=>{
if (!walkerRef.current) {
return null;
}
switch(data.type){
case _tokens.treeDataTypes.Click:
return data.target;
case _tokens.treeDataTypes.TypeAhead:
walkerRef.current.currentElement = data.target;
return (0, _nextTypeAheadElement.nextTypeAheadElement)(walkerRef.current, data.event.key);
case _tokens.treeDataTypes.ArrowLeft:
{
const actions = queryActions(data.target);
if (navigationMode === 'treegrid' && (actions === null || actions === void 0 ? void 0 : actions.contains(data.target.ownerDocument.activeElement))) {
return data.target;
}
walkerRef.current.currentElement = data.target;
return walkerRef.current.parentElement();
}
case _tokens.treeDataTypes.ArrowRight:
if (navigationMode === 'treegrid') {
const actions = queryActions(data.target);
if (actions) {
var _findFirstFocusable;
(_findFirstFocusable = findFirstFocusable(actions)) === null || _findFirstFocusable === void 0 ? void 0 : _findFirstFocusable.focus();
}
return null;
}
walkerRef.current.currentElement = data.target;
return walkerRef.current.firstChild();
case _tokens.treeDataTypes.End:
walkerRef.current.currentElement = walkerRef.current.root;
return lastChildRecursive(walkerRef.current);
case _tokens.treeDataTypes.Home:
walkerRef.current.currentElement = walkerRef.current.root;
return walkerRef.current.firstChild();
case _tokens.treeDataTypes.ArrowDown:
walkerRef.current.currentElement = data.target;
return walkerRef.current.nextElement();
case _tokens.treeDataTypes.ArrowUp:
walkerRef.current.currentElement = data.target;
return walkerRef.current.previousElement();
}
};
function navigate(data, focusOptions) {
const nextElement = getNextElement(data);
if (nextElement) {
rove(nextElement, focusOptions);
}
return nextElement;
}
return {
navigate,
treeRef: (0, _reactutilities.useMergedRefs)(walkerRootRef, rootRefCallback),
forceUpdateRovingTabIndex
};
}
function lastChildRecursive(walker) {
let lastElement = null;
let nextElement = null;
while(nextElement = walker.lastChild()){
lastElement = nextElement;
}
return lastElement;
}
const queryActions = (target)=>target.querySelector(`:scope > .${_TreeItemLayout.treeItemLayoutClassNames.root} > .${_TreeItemLayout.treeItemLayoutClassNames.actions}`);

File diff suppressed because one or more lines are too long