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,72 @@
import { _ as _define_property } from "@swc/helpers/_/_define_property";
const internalMapSymbol = Symbol('#internalMap');
let _internalMapSymbol = internalMapSymbol;
export class ImmutableMap {
static dangerouslyGetInternalMap(immutableMap) {
return immutableMap[internalMapSymbol];
}
static copy(immutableMap) {
return this.from(immutableMap[internalMapSymbol]);
}
static from(iterable, mapFn) {
if (iterable === undefined) {
return this.empty;
}
if (!mapFn) {
if (iterable instanceof this) {
return iterable;
}
// casting here is ok, as the function overload ensures that the iterable is
// Iterable<[unknown, unknown]>
// if mapFn is not provided
const iterableAsTuple = iterable;
return new this(new Map(iterableAsTuple));
}
const map = new Map();
for (const value of iterable){
map.set(...mapFn(value));
}
return new this(map);
}
static [Symbol.hasInstance](instance) {
return Boolean(typeof instance === 'object' && instance && internalMapSymbol in instance);
}
delete(key) {
if (!this.has(key)) {
return this;
}
const copy = ImmutableMap.copy(this);
copy[internalMapSymbol].delete(key);
return copy;
}
get(key) {
return this[internalMapSymbol].get(key);
}
has(key) {
return this[internalMapSymbol].has(key);
}
set(key, value) {
if (this.get(key) === value) {
return this;
}
const copy = ImmutableMap.copy(this);
copy[internalMapSymbol].set(key, value);
return copy;
}
[Symbol.iterator]() {
return this[internalMapSymbol].entries();
}
/**
* Do not use this constructor directly, use {@link ImmutableMap.from} instead.
* {@link ImmutableMap.from} handles instance verification (which might be problematic on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof#instanceof_and_multiple_realms | multiple realms}),
* avoid unnecessary copies, supports iterables and ensures that the internal map is never exposed.
*
*⚠️⚠️ _By using this constructor directly, you might end up with a mutable map, as it is not guaranteed that the internal map is not exposed._ ⚠️⚠️
*/ constructor(internalMap){
_define_property(this, "size", void 0);
_define_property(this, _internalMapSymbol, void 0);
this[internalMapSymbol] = internalMap;
this.size = this[internalMapSymbol].size;
}
}
_define_property(ImmutableMap, "empty", new ImmutableMap(new Map()));

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,67 @@
import { _ as _define_property } from "@swc/helpers/_/_define_property";
const internalSetSymbol = Symbol('#internalSet');
let _internalSetSymbol = internalSetSymbol;
/**
* Small immutable wrapper around the native Set implementation.
* Every operation that would modify the set returns a new copy instance.
*
* @public
*/ export class ImmutableSet {
static dangerouslyGetInternalSet(set) {
return set[internalSetSymbol];
}
static copy(immutableSet) {
return new ImmutableSet(new Set(immutableSet[internalSetSymbol]));
}
/**
* Creates a new {@link ImmutableSet} from an iterable.
* If the iterable is undefined, {@link ImmutableSet.empty} will be returned.
* If the iterable is already an {@link ImmutableSet}, it will be returned as is no copy will be made.
*/ static from(iterable) {
if (iterable === undefined) {
return this.empty;
}
if (iterable instanceof this) {
return iterable;
}
return new this(new Set(iterable));
}
static [Symbol.hasInstance](instance) {
return Boolean(typeof instance === 'object' && instance && internalSetSymbol in instance);
}
add(value) {
if (this.has(value)) {
return this;
}
const copy = ImmutableSet.copy(this);
copy[internalSetSymbol].add(value);
return copy;
}
delete(value) {
if (!this.has(value)) {
return this;
}
const copy = ImmutableSet.copy(this);
copy[internalSetSymbol].delete(value);
return copy;
}
has(value) {
return this[internalSetSymbol].has(value);
}
[Symbol.iterator]() {
return this[internalSetSymbol].values();
}
/**
* Do not use this constructor directly, use {@link ImmutableSet.from} instead.
* {@link ImmutableSet.from} handles instance verification (which might be problematic on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof#instanceof_and_multiple_realms | multiple realms}),
* avoid unnecessary copies, supports iterables and ensures that the internal set is never exposed.
*
*⚠️⚠️ _By using this constructor directly, you might end up with a mutable set, as it is not guaranteed that the internal set is not exposed._ ⚠️⚠️
*/ constructor(internalSet){
_define_property(this, "size", void 0);
_define_property(this, _internalSetSymbol, void 0);
this[internalSetSymbol] = internalSet;
this.size = this[internalSetSymbol].size;
}
}
_define_property(ImmutableSet, "empty", new ImmutableSet(new Set()));

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/utils/ImmutableSet.ts"],"sourcesContent":["const internalSetSymbol = Symbol('#internalSet');\n\n/**\n * Small immutable wrapper around the native Set implementation.\n * Every operation that would modify the set returns a new copy instance.\n *\n * @public\n */\nexport class ImmutableSet<T> implements Iterable<T> {\n public static empty: ImmutableSet<never> = new ImmutableSet(new Set());\n public readonly size: number;\n\n private [internalSetSymbol]: Set<T>;\n\n public static dangerouslyGetInternalSet<Value>(set: ImmutableSet<Value>): Set<Value> {\n return set[internalSetSymbol];\n }\n\n public static copy<T>(immutableSet: ImmutableSet<T>): ImmutableSet<T> {\n return new ImmutableSet(new Set(immutableSet[internalSetSymbol]));\n }\n\n /**\n * Creates a new {@link ImmutableSet} from an iterable.\n * If the iterable is undefined, {@link ImmutableSet.empty} will be returned.\n * If the iterable is already an {@link ImmutableSet}, it will be returned as is no copy will be made.\n */\n public static from<Value>(iterable?: Iterable<Value>): ImmutableSet<Value> {\n if (iterable === undefined) {\n return this.empty;\n }\n if (iterable instanceof this) {\n return iterable;\n }\n return new this(new Set(iterable));\n }\n\n public static [Symbol.hasInstance](instance: unknown): boolean {\n return Boolean(typeof instance === 'object' && instance && internalSetSymbol in instance);\n }\n\n /**\n * Do not use this constructor directly, use {@link ImmutableSet.from} instead.\n * {@link ImmutableSet.from} handles instance verification (which might be problematic on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof#instanceof_and_multiple_realms | multiple realms}),\n * avoid unnecessary copies, supports iterables and ensures that the internal set is never exposed.\n *\n *⚠️⚠️ _By using this constructor directly, you might end up with a mutable set, as it is not guaranteed that the internal set is not exposed._ ⚠️⚠️\n */\n constructor(internalSet: Set<T>) {\n this[internalSetSymbol] = internalSet;\n this.size = this[internalSetSymbol].size;\n }\n\n public add(value: T): ImmutableSet<T> {\n if (this.has(value)) {\n return this;\n }\n const copy = ImmutableSet.copy(this);\n copy[internalSetSymbol].add(value);\n return copy;\n }\n\n public delete(value: T): ImmutableSet<T> {\n if (!this.has(value)) {\n return this;\n }\n const copy = ImmutableSet.copy(this);\n copy[internalSetSymbol].delete(value);\n return copy;\n }\n\n public has(value: T): boolean {\n return this[internalSetSymbol].has(value);\n }\n\n public [Symbol.iterator](): Iterator<T> {\n return this[internalSetSymbol].values();\n }\n}\n"],"names":["internalSetSymbol","Symbol","ImmutableSet","dangerouslyGetInternalSet","set","copy","immutableSet","Set","from","iterable","undefined","empty","hasInstance","instance","Boolean","add","value","has","delete","iterator","values","constructor","internalSet","size"],"mappings":";AAAA,MAAMA,oBAAoBC,OAAO;IAYtBD,qBAAAA;AAVX;;;;;CAKC,GACD,OAAO,MAAME;IAMX,OAAcC,0BAAiCC,GAAwB,EAAc;QACnF,OAAOA,GAAG,CAACJ,kBAAkB;IAC/B;IAEA,OAAcK,KAAQC,YAA6B,EAAmB;QACpE,OAAO,IAAIJ,aAAa,IAAIK,IAAID,YAAY,CAACN,kBAAkB;IACjE;IAEA;;;;GAIC,GACD,OAAcQ,KAAYC,QAA0B,EAAuB;QACzE,IAAIA,aAAaC,WAAW;YAC1B,OAAO,IAAI,CAACC,KAAK;QACnB;QACA,IAAIF,oBAAoB,IAAI,EAAE;YAC5B,OAAOA;QACT;QACA,OAAO,IAAI,IAAI,CAAC,IAAIF,IAAIE;IAC1B;IAEA,OAAc,CAACR,OAAOW,WAAW,CAAC,CAACC,QAAiB,EAAW;QAC7D,OAAOC,QAAQ,OAAOD,aAAa,YAAYA,YAAYb,qBAAqBa;IAClF;IAcOE,IAAIC,KAAQ,EAAmB;QACpC,IAAI,IAAI,CAACC,GAAG,CAACD,QAAQ;YACnB,OAAO,IAAI;QACb;QACA,MAAMX,OAAOH,aAAaG,IAAI,CAAC,IAAI;QACnCA,IAAI,CAACL,kBAAkB,CAACe,GAAG,CAACC;QAC5B,OAAOX;IACT;IAEOa,OAAOF,KAAQ,EAAmB;QACvC,IAAI,CAAC,IAAI,CAACC,GAAG,CAACD,QAAQ;YACpB,OAAO,IAAI;QACb;QACA,MAAMX,OAAOH,aAAaG,IAAI,CAAC,IAAI;QACnCA,IAAI,CAACL,kBAAkB,CAACkB,MAAM,CAACF;QAC/B,OAAOX;IACT;IAEOY,IAAID,KAAQ,EAAW;QAC5B,OAAO,IAAI,CAAChB,kBAAkB,CAACiB,GAAG,CAACD;IACrC;IAEO,CAACf,OAAOkB,QAAQ,CAAC,GAAgB;QACtC,OAAO,IAAI,CAACnB,kBAAkB,CAACoB,MAAM;IACvC;IApCA;;;;;;GAMC,GACDC,YAAYC,WAAmB,CAAE;QAtCjC,uBAAgBC,QAAhB,KAAA;QAEA,uBAASvB,oBAAT,KAAA;QAqCE,IAAI,CAACA,kBAAkB,GAAGsB;QAC1B,IAAI,CAACC,IAAI,GAAG,IAAI,CAACvB,kBAAkB,CAACuB,IAAI;IAC1C;AA2BF;AArEE,iBADWrB,cACGS,SAA6B,IAAIT,aAAa,IAAIK"}

View File

@@ -0,0 +1,7 @@
import * as React from 'react';
export function assertIsDefinedRef(refObject, msg = `assertIsDefinedRef: reference not properly defined ${refObject}`) {
// eslint-disable-next-line eqeqeq
if (refObject.current == undefined && process.env.NODE_ENV === 'development') {
throw new TypeError(msg);
}
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/utils/assert.ts"],"sourcesContent":["import * as React from 'react';\n\nexport function assertIsDefinedRef<V>(\n refObject: React.RefObject<V | null | undefined>,\n msg = `assertIsDefinedRef: reference not properly defined ${refObject}`,\n // eslint-disable-next-line @typescript-eslint/no-deprecated\n): asserts refObject is React.MutableRefObject<V> {\n // eslint-disable-next-line eqeqeq\n if (refObject.current == undefined && process.env.NODE_ENV === 'development') {\n throw new TypeError(msg);\n }\n}\n"],"names":["React","assertIsDefinedRef","refObject","msg","current","undefined","process","env","NODE_ENV","TypeError"],"mappings":"AAAA,YAAYA,WAAW,QAAQ;AAE/B,OAAO,SAASC,mBACdC,SAAgD,EAChDC,MAAM,CAAC,mDAAmD,EAAED,WAAW;IAGvE,kCAAkC;IAClC,IAAIA,UAAUE,OAAO,IAAIC,aAAaC,QAAQC,GAAG,CAACC,QAAQ,KAAK,eAAe;QAC5E,MAAM,IAAIC,UAAUN;IACtB;AACF"}

View File

@@ -0,0 +1,6 @@
import { ImmutableMap } from './ImmutableMap';
const tuplifyCheckedItem = (value)=>Array.isArray(value) ? value : [
value,
true
];
export const createCheckedItems = (iterable)=>ImmutableMap.from(iterable, tuplifyCheckedItem);

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/utils/createCheckedItems.ts"],"sourcesContent":["import type { TreeSelectionValue } from '../Tree';\nimport type { TreeItemValue } from '../TreeItem';\nimport { ImmutableMap } from './ImmutableMap';\n\nconst tuplifyCheckedItem = (\n value: TreeItemValue | [TreeItemValue, TreeSelectionValue],\n): [TreeItemValue, TreeSelectionValue] => (Array.isArray(value) ? value : [value, true]);\n\nexport const createCheckedItems = (\n iterable?: Iterable<TreeItemValue | [TreeItemValue, TreeSelectionValue]>,\n): ImmutableMap<TreeItemValue, TreeSelectionValue> => ImmutableMap.from(iterable, tuplifyCheckedItem);\n"],"names":["ImmutableMap","tuplifyCheckedItem","value","Array","isArray","createCheckedItems","iterable","from"],"mappings":"AAEA,SAASA,YAAY,QAAQ,iBAAiB;AAE9C,MAAMC,qBAAqB,CACzBC,QACyCC,MAAMC,OAAO,CAACF,SAASA,QAAQ;QAACA;QAAO;KAAK;AAEvF,OAAO,MAAMG,qBAAqB,CAChCC,WACoDN,aAAaO,IAAI,CAACD,UAAUL,oBAAoB"}

View File

@@ -0,0 +1,67 @@
import { isHTMLElement } from '@fluentui/react-utilities';
export function createHTMLElementWalker(root, targetDocument, filter = ()=>NodeFilter.FILTER_ACCEPT) {
let temporaryFilter;
const treeWalker = targetDocument.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, {
acceptNode (node) {
if (!isHTMLElement(node)) {
return NodeFilter.FILTER_REJECT;
}
const filterResult = filter(node);
var _temporaryFilter;
return filterResult === NodeFilter.FILTER_ACCEPT ? (_temporaryFilter = temporaryFilter === null || temporaryFilter === void 0 ? void 0 : temporaryFilter(node)) !== null && _temporaryFilter !== void 0 ? _temporaryFilter : filterResult : filterResult;
}
});
return {
get root () {
return treeWalker.root;
},
get currentElement () {
return treeWalker.currentNode;
},
set currentElement (element){
treeWalker.currentNode = element;
},
firstChild: (localFilter)=>{
temporaryFilter = localFilter;
const result = treeWalker.firstChild();
temporaryFilter = undefined;
return result;
},
lastChild: (localFilter)=>{
temporaryFilter = localFilter;
const result = treeWalker.lastChild();
temporaryFilter = undefined;
return result;
},
nextElement: (localFilter)=>{
temporaryFilter = localFilter;
const result = treeWalker.nextNode();
temporaryFilter = undefined;
return result;
},
nextSibling: (localFilter)=>{
temporaryFilter = localFilter;
const result = treeWalker.nextSibling();
temporaryFilter = undefined;
return result;
},
parentElement: (localFilter)=>{
temporaryFilter = localFilter;
const result = treeWalker.parentNode();
temporaryFilter = undefined;
return result;
},
previousElement: (localFilter)=>{
temporaryFilter = localFilter;
const result = treeWalker.previousNode();
temporaryFilter = undefined;
return result;
},
previousSibling: (localFilter)=>{
temporaryFilter = localFilter;
const result = treeWalker.previousSibling();
temporaryFilter = undefined;
return result;
}
};
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/utils/createHTMLElementWalker.ts"],"sourcesContent":["import { isHTMLElement } from '@fluentui/react-utilities';\n\nexport interface HTMLElementWalker {\n readonly root: HTMLElement;\n currentElement: HTMLElement;\n firstChild(filter?: HTMLElementFilter): HTMLElement | null;\n lastChild(filter?: HTMLElementFilter): HTMLElement | null;\n nextElement(filter?: HTMLElementFilter): HTMLElement | null;\n nextSibling(filter?: HTMLElementFilter): HTMLElement | null;\n parentElement(filter?: HTMLElementFilter): HTMLElement | null;\n previousElement(filter?: HTMLElementFilter): HTMLElement | null;\n previousSibling(filter?: HTMLElementFilter): HTMLElement | null;\n}\n\nexport type HTMLElementFilter = (element: HTMLElement) => number;\n\nexport function createHTMLElementWalker(\n root: HTMLElement,\n targetDocument: Document,\n filter: HTMLElementFilter = () => NodeFilter.FILTER_ACCEPT,\n): HTMLElementWalker {\n let temporaryFilter: HTMLElementFilter | undefined;\n const treeWalker = targetDocument.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, {\n acceptNode(node: Node) {\n if (!isHTMLElement(node)) {\n return NodeFilter.FILTER_REJECT;\n }\n const filterResult = filter(node);\n return filterResult === NodeFilter.FILTER_ACCEPT ? temporaryFilter?.(node) ?? filterResult : filterResult;\n },\n });\n return {\n get root() {\n return treeWalker.root as HTMLElement;\n },\n get currentElement() {\n return treeWalker.currentNode as HTMLElement;\n },\n set currentElement(element) {\n treeWalker.currentNode = element;\n },\n firstChild: localFilter => {\n temporaryFilter = localFilter;\n const result = treeWalker.firstChild() as HTMLElement | null;\n temporaryFilter = undefined;\n return result;\n },\n lastChild: localFilter => {\n temporaryFilter = localFilter;\n const result = treeWalker.lastChild() as HTMLElement | null;\n temporaryFilter = undefined;\n return result;\n },\n nextElement: localFilter => {\n temporaryFilter = localFilter;\n const result = treeWalker.nextNode() as HTMLElement | null;\n temporaryFilter = undefined;\n return result;\n },\n nextSibling: localFilter => {\n temporaryFilter = localFilter;\n const result = treeWalker.nextSibling() as HTMLElement | null;\n temporaryFilter = undefined;\n return result;\n },\n parentElement: localFilter => {\n temporaryFilter = localFilter;\n const result = treeWalker.parentNode() as HTMLElement | null;\n temporaryFilter = undefined;\n return result;\n },\n previousElement: localFilter => {\n temporaryFilter = localFilter;\n const result = treeWalker.previousNode() as HTMLElement | null;\n temporaryFilter = undefined;\n return result;\n },\n previousSibling: localFilter => {\n temporaryFilter = localFilter;\n const result = treeWalker.previousSibling() as HTMLElement | null;\n temporaryFilter = undefined;\n return result;\n },\n };\n}\n"],"names":["isHTMLElement","createHTMLElementWalker","root","targetDocument","filter","NodeFilter","FILTER_ACCEPT","temporaryFilter","treeWalker","createTreeWalker","SHOW_ELEMENT","acceptNode","node","FILTER_REJECT","filterResult","currentElement","currentNode","element","firstChild","localFilter","result","undefined","lastChild","nextElement","nextNode","nextSibling","parentElement","parentNode","previousElement","previousNode","previousSibling"],"mappings":"AAAA,SAASA,aAAa,QAAQ,4BAA4B;AAgB1D,OAAO,SAASC,wBACdC,IAAiB,EACjBC,cAAwB,EACxBC,SAA4B,IAAMC,WAAWC,aAAa;IAE1D,IAAIC;IACJ,MAAMC,aAAaL,eAAeM,gBAAgB,CAACP,MAAMG,WAAWK,YAAY,EAAE;QAChFC,YAAWC,IAAU;YACnB,IAAI,CAACZ,cAAcY,OAAO;gBACxB,OAAOP,WAAWQ,aAAa;YACjC;YACA,MAAMC,eAAeV,OAAOQ;gBACuBL;YAAnD,OAAOO,iBAAiBT,WAAWC,aAAa,GAAGC,CAAAA,mBAAAA,4BAAAA,sCAAAA,gBAAkBK,mBAAlBL,8BAAAA,mBAA2BO,eAAeA;QAC/F;IACF;IACA,OAAO;QACL,IAAIZ,QAAO;YACT,OAAOM,WAAWN,IAAI;QACxB;QACA,IAAIa,kBAAiB;YACnB,OAAOP,WAAWQ,WAAW;QAC/B;QACA,IAAID,gBAAeE,QAAS;YAC1BT,WAAWQ,WAAW,GAAGC;QAC3B;QACAC,YAAYC,CAAAA;YACVZ,kBAAkBY;YAClB,MAAMC,SAASZ,WAAWU,UAAU;YACpCX,kBAAkBc;YAClB,OAAOD;QACT;QACAE,WAAWH,CAAAA;YACTZ,kBAAkBY;YAClB,MAAMC,SAASZ,WAAWc,SAAS;YACnCf,kBAAkBc;YAClB,OAAOD;QACT;QACAG,aAAaJ,CAAAA;YACXZ,kBAAkBY;YAClB,MAAMC,SAASZ,WAAWgB,QAAQ;YAClCjB,kBAAkBc;YAClB,OAAOD;QACT;QACAK,aAAaN,CAAAA;YACXZ,kBAAkBY;YAClB,MAAMC,SAASZ,WAAWiB,WAAW;YACrClB,kBAAkBc;YAClB,OAAOD;QACT;QACAM,eAAeP,CAAAA;YACbZ,kBAAkBY;YAClB,MAAMC,SAASZ,WAAWmB,UAAU;YACpCpB,kBAAkBc;YAClB,OAAOD;QACT;QACAQ,iBAAiBT,CAAAA;YACfZ,kBAAkBY;YAClB,MAAMC,SAASZ,WAAWqB,YAAY;YACtCtB,kBAAkBc;YAClB,OAAOD;QACT;QACAU,iBAAiBX,CAAAA;YACfZ,kBAAkBY;YAClB,MAAMC,SAASZ,WAAWsB,eAAe;YACzCvB,kBAAkBc;YAClB,OAAOD;QACT;IACF;AACF"}

View File

@@ -0,0 +1,191 @@
/**
* creates a list of virtual tree items
* and provides a map to access each item by id
*/ export function createHeadlessTree(initialProps = []) {
const root = createHeadlessTreeRootItem();
const itemsPerValue = new Map([
[
root.value,
root
]
]);
const headlessTree = {
root,
get size () {
return itemsPerValue.size;
},
getParent: (key)=>{
var _itemsPerValue_get;
var _itemsPerValue_get_parentValue, _itemsPerValue_get1;
return (_itemsPerValue_get1 = itemsPerValue.get((_itemsPerValue_get_parentValue = (_itemsPerValue_get = itemsPerValue.get(key)) === null || _itemsPerValue_get === void 0 ? void 0 : _itemsPerValue_get.parentValue) !== null && _itemsPerValue_get_parentValue !== void 0 ? _itemsPerValue_get_parentValue : root.value)) !== null && _itemsPerValue_get1 !== void 0 ? _itemsPerValue_get1 : root;
},
get: (key)=>itemsPerValue.get(key),
has: (key)=>itemsPerValue.has(key),
add (props) {
const { parentValue = headlessTreeRootId, ...propsWithoutParentValue } = props;
const parentItem = itemsPerValue.get(parentValue);
if (!parentItem) {
if (process.env.NODE_ENV === 'development') {
// eslint-disable-next-line no-console
console.error(`@fluentui/react-tree [createHeadlessTree]:
TreeItem "${props.value}" is wrongly positioned, did you properly ordered provided item props? make sure provided items are organized, parents should come before children`);
}
return;
}
parentItem.itemType = 'branch';
var _propsWithoutParentValue_itemType;
const item = {
value: props.value,
getTreeItemProps: ()=>({
...propsWithoutParentValue,
parentValue,
'aria-level': item.level,
'aria-posinset': item.position,
'aria-setsize': parentItem.childrenValues.length,
itemType: item.itemType
}),
itemType: (_propsWithoutParentValue_itemType = propsWithoutParentValue.itemType) !== null && _propsWithoutParentValue_itemType !== void 0 ? _propsWithoutParentValue_itemType : 'leaf',
level: parentItem.level + 1,
parentValue,
childrenValues: [],
index: -1,
position: parentItem.childrenValues.push(props.value)
};
itemsPerValue.set(item.value, item);
},
subtree: (key)=>HeadlessTreeSubtreeGenerator(key, headlessTree),
children: (key)=>HeadlessTreeChildrenGenerator(key, headlessTree),
ancestors: (key)=>HeadlessTreeAncestorsGenerator(key, headlessTree),
visibleItems: (openItems)=>HeadlessTreeVisibleItemsGenerator(openItems, headlessTree)
};
initialProps.forEach(headlessTree.add);
return headlessTree;
}
export const headlessTreeRootId = '__fuiHeadlessTreeRoot';
function createHeadlessTreeRootItem() {
return {
parentValue: undefined,
value: headlessTreeRootId,
itemType: 'branch',
getTreeItemProps: ()=>{
if (process.env.NODE_ENV !== 'production') {
// eslint-disable-next-line no-console
console.error(`@fluentui/react-tree [createHeadlessTree]:
Internal error, trying to access treeitem props from invalid root element`);
}
return {
id: headlessTreeRootId,
parentValue: undefined,
value: headlessTreeRootId,
'aria-setsize': -1,
'aria-level': -1,
'aria-posinset': -1,
itemType: 'branch'
};
},
childrenValues: [],
get index () {
if (process.env.NODE_ENV !== 'production') {
// eslint-disable-next-line no-console
console.error(`@fluentui/react-tree [createHeadlessTree]:
Internal error, trying to access treeitem props from invalid root element`);
}
return -1;
},
get position () {
if (process.env.NODE_ENV !== 'production') {
// eslint-disable-next-line no-console
console.error(`@fluentui/react-tree [createHeadlessTree]:
Internal error, trying to access treeitem props from invalid root element`);
}
return -1;
},
level: 0
};
}
/**
* Generator that returns all subtree of a given virtual tree item
* @param key - the key of the item to get the subtree from
*/ // eslint-disable-next-line @typescript-eslint/naming-convention
function* HeadlessTreeSubtreeGenerator(key, virtualTreeItems) {
const item = virtualTreeItems.get(key);
if (!item || item.childrenValues.length === 0) {
return;
}
for (const childValue of item.childrenValues){
yield virtualTreeItems.get(childValue);
yield* HeadlessTreeSubtreeGenerator(childValue, virtualTreeItems);
}
}
/**
* Generator that returns all children of a given virtual tree item
* @param key - the key of the item to get the children from
*/ // eslint-disable-next-line @typescript-eslint/naming-convention
function* HeadlessTreeChildrenGenerator(key, virtualTreeItems) {
const item = virtualTreeItems.get(key);
if (!item || item.childrenValues.length === 0) {
return;
}
for (const childValue of item.childrenValues){
yield virtualTreeItems.get(childValue);
}
}
/**
* Generator that returns all ancestors of a given virtual tree item
* @param key - the key of the item to get the children from
*/ // eslint-disable-next-line @typescript-eslint/naming-convention
function* HeadlessTreeAncestorsGenerator(key, virtualTreeItems) {
let parent = virtualTreeItems.getParent(key);
while(parent !== virtualTreeItems.root){
yield parent;
parent = virtualTreeItems.getParent(parent.value);
}
}
/**
* Generator that returns all visible items of a given virtual tree
* @param openItems - the open items of the tree
*/ // eslint-disable-next-line @typescript-eslint/naming-convention
function* HeadlessTreeVisibleItemsGenerator(openItems, virtualTreeItems) {
let index = 0;
for (const item of recursiveVisibleItems(virtualTreeItems.root.value, openItems, virtualTreeItems)){
item.index = index++;
yield item;
}
}
function* recursiveVisibleItems(parentValue, openItems, virtualTreeItems) {
const parent = virtualTreeItems.get(parentValue);
if (!parent || parent.childrenValues.length === 0) {
return;
}
for (const childValue of parent.childrenValues){
const child = virtualTreeItems.get(childValue);
if (!child) {
continue;
}
if (isItemVisible(child, openItems, virtualTreeItems)) {
yield child;
// Process children only as long as their parents are open.
// This makes it possible to have large trees with good performance as
// long as most branches are not expanded.
if (openItems.has(childValue)) {
yield* recursiveVisibleItems(childValue, openItems, virtualTreeItems);
}
}
}
}
function isItemVisible(item, openItems, virtualTreeItems) {
if (item.level === 1) {
return true;
}
while(item.parentValue && item.parentValue !== virtualTreeItems.root.value){
if (!openItems.has(item.parentValue)) {
return false;
}
const parent = virtualTreeItems.get(item.parentValue);
if (!parent) {
return false;
}
item = parent;
}
return true;
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,57 @@
function flattenTreeRecursive(items, parent, level = 1) {
return items.reduce((acc, { subtree, ...item }, index)=>{
const flatTreeItem = {
'aria-level': level,
'aria-posinset': index + 1,
'aria-setsize': items.length,
parentValue: parent === null || parent === void 0 ? void 0 : parent.value,
...item
};
acc.push(flatTreeItem);
if (subtree !== undefined) {
acc.push(...flattenTreeRecursive(subtree, flatTreeItem, level + 1));
}
return acc;
}, []);
}
/**
* Converts a nested structure to a flat one which can be consumed by `useFlatTreeItems`
* @example
* ```tsx
* const defaultItems = flattenTree_unstable([
* {
* children: <TreeItemLayout>level 1, item 1</TreeItemLayout>,
* subtree: [
* {
* children: <TreeItemLayout>level 2, item 1</TreeItemLayout>,
* },
* {
* children: <TreeItemLayout>level 2, item 2</TreeItemLayout>,
* },
* {
* children: <TreeItemLayout>level 2, item 3</TreeItemLayout>,
* },
* ],
* },
* {
* children: <TreeItemLayout>level 1, item 2</TreeItemLayout>,
* subtree: [
* {
* children: <TreeItemLayout>level 2, item 1</TreeItemLayout>,
* subtree: [
* {
* children: <TreeItemLayout>level 3, item 1</TreeItemLayout>,
* subtree: [
* {
* children: <TreeItemLayout>level 4, item 1</TreeItemLayout>,
* },
* ],
* },
* ],
* },
* ],
* },
* ]);
* ```
*/ // eslint-disable-next-line @typescript-eslint/naming-convention
export const flattenTree_unstable = (items)=>flattenTreeRecursive(items);

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/utils/flattenTree.ts"],"sourcesContent":["import { HeadlessFlatTreeItemProps } from '../FlatTree';\nimport { TreeItemProps, TreeItemValue } from '../TreeItem';\n\nexport type FlattenTreeItem<Props extends TreeItemProps> = Omit<Props, 'subtree' | 'itemType'> & {\n value: TreeItemValue;\n subtree?: FlattenTreeItem<Props>[];\n};\n\nexport type FlattenedTreeItem<Props extends TreeItemProps> = HeadlessFlatTreeItemProps & Props;\n\nfunction flattenTreeRecursive<Props extends TreeItemProps>(\n items: FlattenTreeItem<Props>[],\n parent?: HeadlessFlatTreeItemProps & Props,\n level = 1,\n): FlattenedTreeItem<Props>[] {\n return items.reduce<FlattenedTreeItem<Props>[]>((acc, { subtree, ...item }, index) => {\n const flatTreeItem = {\n 'aria-level': level,\n 'aria-posinset': index + 1,\n 'aria-setsize': items.length,\n parentValue: parent?.value,\n ...item,\n } as FlattenedTreeItem<Props>;\n acc.push(flatTreeItem);\n if (subtree !== undefined) {\n acc.push(...flattenTreeRecursive<Props>(subtree, flatTreeItem, level + 1));\n }\n return acc;\n }, []);\n}\n\n/**\n * Converts a nested structure to a flat one which can be consumed by `useFlatTreeItems`\n * @example\n * ```tsx\n * const defaultItems = flattenTree_unstable([\n * {\n * children: <TreeItemLayout>level 1, item 1</TreeItemLayout>,\n * subtree: [\n * {\n * children: <TreeItemLayout>level 2, item 1</TreeItemLayout>,\n * },\n * {\n * children: <TreeItemLayout>level 2, item 2</TreeItemLayout>,\n * },\n * {\n * children: <TreeItemLayout>level 2, item 3</TreeItemLayout>,\n * },\n * ],\n * },\n * {\n * children: <TreeItemLayout>level 1, item 2</TreeItemLayout>,\n * subtree: [\n * {\n * children: <TreeItemLayout>level 2, item 1</TreeItemLayout>,\n * subtree: [\n * {\n * children: <TreeItemLayout>level 3, item 1</TreeItemLayout>,\n * subtree: [\n * {\n * children: <TreeItemLayout>level 4, item 1</TreeItemLayout>,\n * },\n * ],\n * },\n * ],\n * },\n * ],\n * },\n * ]);\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport const flattenTree_unstable = <Props extends TreeItemProps>(\n items: FlattenTreeItem<Props>[],\n): FlattenedTreeItem<Props>[] => flattenTreeRecursive(items);\n"],"names":["flattenTreeRecursive","items","parent","level","reduce","acc","subtree","item","index","flatTreeItem","length","parentValue","value","push","undefined","flattenTree_unstable"],"mappings":"AAUA,SAASA,qBACPC,KAA+B,EAC/BC,MAA0C,EAC1CC,QAAQ,CAAC;IAET,OAAOF,MAAMG,MAAM,CAA6B,CAACC,KAAK,EAAEC,OAAO,EAAE,GAAGC,MAAM,EAAEC;QAC1E,MAAMC,eAAe;YACnB,cAAcN;YACd,iBAAiBK,QAAQ;YACzB,gBAAgBP,MAAMS,MAAM;YAC5BC,WAAW,EAAET,mBAAAA,6BAAAA,OAAQU,KAAK;YAC1B,GAAGL,IAAI;QACT;QACAF,IAAIQ,IAAI,CAACJ;QACT,IAAIH,YAAYQ,WAAW;YACzBT,IAAIQ,IAAI,IAAIb,qBAA4BM,SAASG,cAAcN,QAAQ;QACzE;QACA,OAAOE;IACT,GAAG,EAAE;AACP;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuCC,GACD,gEAAgE;AAChE,OAAO,MAAMU,uBAAuB,CAClCd,QAC+BD,qBAAqBC,OAAO"}

View File

@@ -0,0 +1,4 @@
export const dataTreeItemValueAttrName = 'data-fui-tree-item-value';
export const getTreeItemValueFromElement = (element)=>{
return element.getAttribute(dataTreeItemValueAttrName);
};

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/utils/getTreeItemValueFromElement.ts"],"sourcesContent":["import type { TreeItemValue } from '../TreeItem';\n\nexport const dataTreeItemValueAttrName = 'data-fui-tree-item-value';\n\nexport const getTreeItemValueFromElement = (element: HTMLElement): TreeItemValue | null => {\n return element.getAttribute(dataTreeItemValueAttrName) as TreeItemValue | null;\n};\n"],"names":["dataTreeItemValueAttrName","getTreeItemValueFromElement","element","getAttribute"],"mappings":"AAEA,OAAO,MAAMA,4BAA4B,2BAA2B;AAEpE,OAAO,MAAMC,8BAA8B,CAACC;IAC1C,OAAOA,QAAQC,YAAY,CAACH;AAC9B,EAAE"}

View File

@@ -0,0 +1,13 @@
export function nextTypeAheadElement(treeWalker, key) {
const keyToLowerCase = key.toLowerCase();
const typeAheadFilter = (element)=>{
var _element_textContent;
return ((_element_textContent = element.textContent) === null || _element_textContent === void 0 ? void 0 : _element_textContent.trim().charAt(0).toLowerCase()) === keyToLowerCase ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
};
let nextElement = treeWalker.nextElement(typeAheadFilter);
if (!nextElement) {
treeWalker.currentElement = treeWalker.root;
nextElement = treeWalker.nextElement(typeAheadFilter);
}
return nextElement;
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/utils/nextTypeAheadElement.ts"],"sourcesContent":["import { HTMLElementWalker } from './createHTMLElementWalker';\n\nexport function nextTypeAheadElement(treeWalker: HTMLElementWalker, key: string): HTMLElement | null {\n const keyToLowerCase = key.toLowerCase();\n const typeAheadFilter = (element: HTMLElement) => {\n return element.textContent?.trim().charAt(0).toLowerCase() === keyToLowerCase\n ? NodeFilter.FILTER_ACCEPT\n : NodeFilter.FILTER_SKIP;\n };\n let nextElement = treeWalker.nextElement(typeAheadFilter);\n if (!nextElement) {\n treeWalker.currentElement = treeWalker.root;\n nextElement = treeWalker.nextElement(typeAheadFilter);\n }\n return nextElement;\n}\n"],"names":["nextTypeAheadElement","treeWalker","key","keyToLowerCase","toLowerCase","typeAheadFilter","element","textContent","trim","charAt","NodeFilter","FILTER_ACCEPT","FILTER_SKIP","nextElement","currentElement","root"],"mappings":"AAEA,OAAO,SAASA,qBAAqBC,UAA6B,EAAEC,GAAW;IAC7E,MAAMC,iBAAiBD,IAAIE,WAAW;IACtC,MAAMC,kBAAkB,CAACC;YAChBA;QAAP,OAAOA,EAAAA,uBAAAA,QAAQC,WAAW,cAAnBD,2CAAAA,qBAAqBE,IAAI,GAAGC,MAAM,CAAC,GAAGL,WAAW,QAAOD,iBAC3DO,WAAWC,aAAa,GACxBD,WAAWE,WAAW;IAC5B;IACA,IAAIC,cAAcZ,WAAWY,WAAW,CAACR;IACzC,IAAI,CAACQ,aAAa;QAChBZ,WAAWa,cAAc,GAAGb,WAAWc,IAAI;QAC3CF,cAAcZ,WAAWY,WAAW,CAACR;IACvC;IACA,OAAOQ;AACT"}

View File

@@ -0,0 +1,8 @@
export function normalizeOpenItems(openSubtrees, options) {
if (!openSubtrees) {
return (options === null || options === void 0 ? void 0 : options.keepUndefined) ? undefined : [];
}
return Array.isArray(openSubtrees) ? openSubtrees : [
openSubtrees
];
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/utils/normalizeOpenItems.ts"],"sourcesContent":["export function normalizeOpenItems(\n openSubtrees?: string | string[],\n options?: {\n keepUndefined?: false;\n },\n): string[];\n\nexport function normalizeOpenItems(\n openSubtrees?: string | string[],\n options?: {\n keepUndefined: true;\n },\n): string[] | undefined;\n\nexport function normalizeOpenItems(\n openSubtrees?: string | string[],\n options?: {\n keepUndefined?: boolean;\n },\n): string[] | undefined {\n if (!openSubtrees) {\n return options?.keepUndefined ? undefined : [];\n }\n return Array.isArray(openSubtrees) ? openSubtrees : [openSubtrees];\n}\n"],"names":["normalizeOpenItems","openSubtrees","options","keepUndefined","undefined","Array","isArray"],"mappings":"AAcA,OAAO,SAASA,mBACdC,YAAgC,EAChCC,OAEC;IAED,IAAI,CAACD,cAAc;QACjB,OAAOC,CAAAA,oBAAAA,8BAAAA,QAASC,aAAa,IAAGC,YAAY,EAAE;IAChD;IACA,OAAOC,MAAMC,OAAO,CAACL,gBAAgBA,eAAe;QAACA;KAAa;AACpE"}

19
node_modules/@fluentui/react-tree/lib/utils/tokens.js generated vendored Normal file
View File

@@ -0,0 +1,19 @@
import { ArrowDown, ArrowLeft, ArrowRight, ArrowUp, End, Home, Enter } from '@fluentui/keyboard-keys';
export const treeItemLevelToken = '--fluent-TreeItem--level';
export const treeAvatarSize = {
medium: 32,
small: 24
};
export const treeDataTypes = {
ArrowLeft,
ArrowRight,
Enter,
Click: 'Click',
ExpandIconClick: 'ExpandIconClick',
End,
Home,
ArrowUp,
ArrowDown,
TypeAhead: 'TypeAhead',
Change: 'Change'
};

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/utils/tokens.ts"],"sourcesContent":["import { ArrowDown, ArrowLeft, ArrowRight, ArrowUp, End, Home, Enter } from '@fluentui/keyboard-keys';\nimport { TreeCheckedChangeData, TreeNavigationData_unstable, TreeOpenChangeData } from '../Tree';\n\nexport const treeItemLevelToken = '--fluent-TreeItem--level' as const;\n\nexport const treeAvatarSize = {\n medium: 32,\n small: 24,\n} as const;\n\nexport const treeDataTypes: {\n readonly [K in TreeOpenChangeData['type'] | TreeNavigationData_unstable['type'] | TreeCheckedChangeData['type']]: K;\n} = {\n ArrowLeft,\n ArrowRight,\n Enter,\n Click: 'Click',\n ExpandIconClick: 'ExpandIconClick',\n End,\n Home,\n ArrowUp,\n ArrowDown,\n TypeAhead: 'TypeAhead',\n Change: 'Change',\n};\n"],"names":["ArrowDown","ArrowLeft","ArrowRight","ArrowUp","End","Home","Enter","treeItemLevelToken","treeAvatarSize","medium","small","treeDataTypes","Click","ExpandIconClick","TypeAhead","Change"],"mappings":"AAAA,SAASA,SAAS,EAAEC,SAAS,EAAEC,UAAU,EAAEC,OAAO,EAAEC,GAAG,EAAEC,IAAI,EAAEC,KAAK,QAAQ,0BAA0B;AAGtG,OAAO,MAAMC,qBAAqB,2BAAoC;AAEtE,OAAO,MAAMC,iBAAiB;IAC5BC,QAAQ;IACRC,OAAO;AACT,EAAW;AAEX,OAAO,MAAMC,gBAET;IACFV;IACAC;IACAI;IACAM,OAAO;IACPC,iBAAiB;IACjBT;IACAC;IACAF;IACAH;IACAc,WAAW;IACXC,QAAQ;AACV,EAAE"}

View File

@@ -0,0 +1,3 @@
export const treeItemFilter = (element)=>{
return element.getAttribute('role') === 'treeitem' ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
};

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/utils/treeItemFilter.ts"],"sourcesContent":["export const treeItemFilter = (element: HTMLElement): number => {\n return element.getAttribute('role') === 'treeitem' ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;\n};\n"],"names":["treeItemFilter","element","getAttribute","NodeFilter","FILTER_ACCEPT","FILTER_SKIP"],"mappings":"AAAA,OAAO,MAAMA,iBAAiB,CAACC;IAC7B,OAAOA,QAAQC,YAAY,CAAC,YAAY,aAAaC,WAAWC,aAAa,GAAGD,WAAWE,WAAW;AACxG,EAAE"}