@fluentui/react-tree 9.4.9 → 9.4.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.json +31 -1
- package/CHANGELOG.md +20 -2
- package/dist/index.d.ts +7 -0
- package/lib/components/FlatTree/useFlatTree.js +4 -17
- package/lib/components/FlatTree/useFlatTree.js.map +1 -1
- package/lib/components/Tree/useTree.js +9 -4
- package/lib/components/Tree/useTree.js.map +1 -1
- package/lib/components/TreeItem/useTreeItem.js +9 -46
- package/lib/components/TreeItem/useTreeItem.js.map +1 -1
- package/lib/components/TreeItem/useTreeItemContextValues.js +4 -1
- package/lib/components/TreeItem/useTreeItemContextValues.js.map +1 -1
- package/lib/components/TreeItemLayout/useTreeItemLayout.js +84 -6
- package/lib/components/TreeItemLayout/useTreeItemLayout.js.map +1 -1
- package/lib/contexts/treeItemContext.js +1 -0
- package/lib/contexts/treeItemContext.js.map +1 -1
- package/lib-commonjs/components/FlatTree/useFlatTree.js +3 -16
- package/lib-commonjs/components/FlatTree/useFlatTree.js.map +1 -1
- package/lib-commonjs/components/Tree/useTree.js +9 -4
- package/lib-commonjs/components/Tree/useTree.js.map +1 -1
- package/lib-commonjs/components/TreeItem/useTreeItem.js +8 -45
- package/lib-commonjs/components/TreeItem/useTreeItem.js.map +1 -1
- package/lib-commonjs/components/TreeItem/useTreeItemContextValues.js +2 -1
- package/lib-commonjs/components/TreeItem/useTreeItemContextValues.js.map +1 -1
- package/lib-commonjs/components/TreeItemLayout/useTreeItemLayout.js +83 -5
- package/lib-commonjs/components/TreeItemLayout/useTreeItemLayout.js.map +1 -1
- package/lib-commonjs/contexts/treeItemContext.js +1 -0
- package/lib-commonjs/contexts/treeItemContext.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.json
CHANGED
|
@@ -2,7 +2,37 @@
|
|
|
2
2
|
"name": "@fluentui/react-tree",
|
|
3
3
|
"entries": [
|
|
4
4
|
{
|
|
5
|
-
"date": "
|
|
5
|
+
"date": "Thu, 02 Nov 2023 17:38:20 GMT",
|
|
6
|
+
"tag": "@fluentui/react-tree_v9.4.11",
|
|
7
|
+
"version": "9.4.11",
|
|
8
|
+
"comments": {
|
|
9
|
+
"patch": [
|
|
10
|
+
{
|
|
11
|
+
"author": "bernardo.sunderhus@gmail.com",
|
|
12
|
+
"package": "@fluentui/react-tree",
|
|
13
|
+
"commit": "9b59f49f035e556aab24cfd8ad8da429815db061",
|
|
14
|
+
"comment": "chore: throws if FlatTree is used as a subtree"
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"date": "Wed, 01 Nov 2023 19:15:55 GMT",
|
|
21
|
+
"tag": "@fluentui/react-tree_v9.4.10",
|
|
22
|
+
"version": "9.4.10",
|
|
23
|
+
"comments": {
|
|
24
|
+
"patch": [
|
|
25
|
+
{
|
|
26
|
+
"author": "bernardo.sunderhus@gmail.com",
|
|
27
|
+
"package": "@fluentui/react-tree",
|
|
28
|
+
"commit": "88574cc717e7bffe6f8f0f5fce191350066e7a62",
|
|
29
|
+
"comment": "chore: stop unnecessary re-rendering when no actions are available"
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"date": "Wed, 01 Nov 2023 12:55:59 GMT",
|
|
6
36
|
"tag": "@fluentui/react-tree_v9.4.9",
|
|
7
37
|
"version": "9.4.9",
|
|
8
38
|
"comments": {
|
package/CHANGELOG.md
CHANGED
|
@@ -1,12 +1,30 @@
|
|
|
1
1
|
# Change Log - @fluentui/react-tree
|
|
2
2
|
|
|
3
|
-
This log was last generated on
|
|
3
|
+
This log was last generated on Thu, 02 Nov 2023 17:38:20 GMT and should not be manually modified.
|
|
4
4
|
|
|
5
5
|
<!-- Start content -->
|
|
6
6
|
|
|
7
|
+
## [9.4.11](https://github.com/microsoft/fluentui/tree/@fluentui/react-tree_v9.4.11)
|
|
8
|
+
|
|
9
|
+
Thu, 02 Nov 2023 17:38:20 GMT
|
|
10
|
+
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-tree_v9.4.10..@fluentui/react-tree_v9.4.11)
|
|
11
|
+
|
|
12
|
+
### Patches
|
|
13
|
+
|
|
14
|
+
- chore: throws if FlatTree is used as a subtree ([PR #29729](https://github.com/microsoft/fluentui/pull/29729) by bernardo.sunderhus@gmail.com)
|
|
15
|
+
|
|
16
|
+
## [9.4.10](https://github.com/microsoft/fluentui/tree/@fluentui/react-tree_v9.4.10)
|
|
17
|
+
|
|
18
|
+
Wed, 01 Nov 2023 19:15:55 GMT
|
|
19
|
+
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-tree_v9.4.9..@fluentui/react-tree_v9.4.10)
|
|
20
|
+
|
|
21
|
+
### Patches
|
|
22
|
+
|
|
23
|
+
- chore: stop unnecessary re-rendering when no actions are available ([PR #29694](https://github.com/microsoft/fluentui/pull/29694) by bernardo.sunderhus@gmail.com)
|
|
24
|
+
|
|
7
25
|
## [9.4.9](https://github.com/microsoft/fluentui/tree/@fluentui/react-tree_v9.4.9)
|
|
8
26
|
|
|
9
|
-
Wed, 01 Nov 2023 12:
|
|
27
|
+
Wed, 01 Nov 2023 12:55:59 GMT
|
|
10
28
|
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-tree_v9.4.8..@fluentui/react-tree_v9.4.9)
|
|
11
29
|
|
|
12
30
|
### Patches
|
package/dist/index.d.ts
CHANGED
|
@@ -460,13 +460,20 @@ export declare const TreeItem: ForwardRefComponent<TreeItemProps>;
|
|
|
460
460
|
export declare const treeItemClassNames: SlotClassNames<TreeItemSlots>;
|
|
461
461
|
|
|
462
462
|
export declare type TreeItemContextValue = {
|
|
463
|
+
/**
|
|
464
|
+
* @deprecated - this value is irrelevant for the tree item
|
|
465
|
+
*/
|
|
463
466
|
isActionsVisible: boolean;
|
|
467
|
+
/**
|
|
468
|
+
* @deprecated - this value is irrelevant for the tree item
|
|
469
|
+
*/
|
|
464
470
|
isAsideVisible: boolean;
|
|
465
471
|
selectionRef: React_2.Ref<HTMLInputElement>;
|
|
466
472
|
actionsRef: React_2.Ref<HTMLDivElement>;
|
|
467
473
|
expandIconRef: React_2.Ref<HTMLDivElement>;
|
|
468
474
|
layoutRef: React_2.Ref<HTMLDivElement>;
|
|
469
475
|
subtreeRef: React_2.Ref<HTMLDivElement>;
|
|
476
|
+
treeItemRef?: React_2.RefObject<HTMLDivElement>;
|
|
470
477
|
itemType: TreeItemType;
|
|
471
478
|
value: TreeItemValue;
|
|
472
479
|
open: boolean;
|
|
@@ -4,8 +4,7 @@ import { useFlatTreeNavigation } from './useFlatTreeNavigation';
|
|
|
4
4
|
import { createHTMLElementWalker } from '../../utils/createHTMLElementWalker';
|
|
5
5
|
import { useFluent_unstable } from '@fluentui/react-shared-contexts';
|
|
6
6
|
import { treeItemFilter } from '../../utils/treeItemFilter';
|
|
7
|
-
import {
|
|
8
|
-
import { useTreeContext_unstable } from '../../contexts/treeContext';
|
|
7
|
+
import { useEventCallback, useMergedRefs } from '@fluentui/react-utilities';
|
|
9
8
|
import { useSubtree } from '../../hooks/useSubtree';
|
|
10
9
|
import { ImmutableSet } from '../../utils/ImmutableSet';
|
|
11
10
|
import { ImmutableMap } from '../../utils/ImmutableMap';
|
|
@@ -47,15 +46,9 @@ function useRootFlatTree(props, ref) {
|
|
|
47
46
|
}
|
|
48
47
|
function useSubFlatTree(props, ref) {
|
|
49
48
|
if (process.env.NODE_ENV === 'development') {
|
|
50
|
-
|
|
51
|
-
console.error(`@fluentui/react-tree [useFlatTree]:
|
|
49
|
+
throw new Error(`@fluentui/react-tree [useFlatTree]:
|
|
52
50
|
Subtrees are not allowed in a FlatTree!
|
|
53
|
-
You cannot use a <FlatTree> component inside of another <FlatTree> component
|
|
54
|
-
}
|
|
55
|
-
if (useTreeContext_unstable((ctx)=>ctx.treeType) === 'nested' && process.env.NODE_ENV === 'development') {
|
|
56
|
-
// eslint-disable-next-line no-console
|
|
57
|
-
console.error(`@fluentui/react-tree [useFlatTree]:
|
|
58
|
-
Error: <FlatTree> component cannot be used inside of a nested <Tree> component and vice versa.`);
|
|
51
|
+
You cannot use a <FlatTree> component inside of another <FlatTree> nor a <Tree> component!`);
|
|
59
52
|
}
|
|
60
53
|
return {
|
|
61
54
|
...useSubtree(props, ref),
|
|
@@ -70,13 +63,7 @@ Error: <FlatTree> component cannot be used inside of a nested <Tree> component a
|
|
|
70
63
|
appearance: 'subtle',
|
|
71
64
|
size: 'medium',
|
|
72
65
|
// ------ defaultTreeContextValue
|
|
73
|
-
open: false
|
|
74
|
-
components: {
|
|
75
|
-
root: React.Fragment
|
|
76
|
-
},
|
|
77
|
-
root: slot.always(props, {
|
|
78
|
-
elementType: React.Fragment
|
|
79
|
-
})
|
|
66
|
+
open: false
|
|
80
67
|
};
|
|
81
68
|
}
|
|
82
69
|
function noop() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["useFlatTree.ts"],"sourcesContent":["import * as React from 'react';\nimport { useRootTree } from '../../hooks/useRootTree';\nimport { FlatTreeProps, FlatTreeState } from './FlatTree.types';\nimport { useFlatTreeNavigation } from './useFlatTreeNavigation';\nimport { HTMLElementWalker, createHTMLElementWalker } from '../../utils/createHTMLElementWalker';\nimport { useFluent_unstable } from '@fluentui/react-shared-contexts';\nimport { treeItemFilter } from '../../utils/treeItemFilter';\nimport {
|
|
1
|
+
{"version":3,"sources":["useFlatTree.ts"],"sourcesContent":["import * as React from 'react';\nimport { useRootTree } from '../../hooks/useRootTree';\nimport { FlatTreeProps, FlatTreeState } from './FlatTree.types';\nimport { useFlatTreeNavigation } from './useFlatTreeNavigation';\nimport { HTMLElementWalker, createHTMLElementWalker } from '../../utils/createHTMLElementWalker';\nimport { useFluent_unstable } from '@fluentui/react-shared-contexts';\nimport { treeItemFilter } from '../../utils/treeItemFilter';\nimport { useEventCallback, useMergedRefs } from '@fluentui/react-utilities';\nimport type { TreeNavigationData_unstable, TreeNavigationEvent_unstable } from '../Tree/Tree.types';\nimport { useSubtree } from '../../hooks/useSubtree';\nimport { ImmutableSet } from '../../utils/ImmutableSet';\nimport { ImmutableMap } from '../../utils/ImmutableMap';\nimport { SubtreeContext } from '../../contexts/subtreeContext';\n\nexport const useFlatTree_unstable: (props: FlatTreeProps, ref: React.Ref<HTMLElement>) => FlatTreeState = (\n props,\n ref,\n) => {\n const isRoot = React.useContext(SubtreeContext) === undefined;\n // as level is static, this doesn't break rule of hooks\n // and if this becomes an issue later on, this can be easily converted\n // eslint-disable-next-line react-hooks/rules-of-hooks\n return isRoot ? useRootFlatTree(props, ref) : useSubFlatTree(props, ref);\n};\n\nfunction useRootFlatTree(props: FlatTreeProps, ref: React.Ref<HTMLElement>): FlatTreeState {\n const { navigate, initialize } = useFlatTreeNavigation();\n const walkerRef = React.useRef<HTMLElementWalker>();\n const { targetDocument } = useFluent_unstable();\n\n const initializeWalker = React.useCallback(\n (root: HTMLElement | null) => {\n if (root && targetDocument) {\n walkerRef.current = createHTMLElementWalker(root, targetDocument, treeItemFilter);\n initialize(walkerRef.current);\n }\n },\n [initialize, targetDocument],\n );\n\n const handleNavigation = useEventCallback(\n (event: TreeNavigationEvent_unstable, data: TreeNavigationData_unstable) => {\n props.onNavigation?.(event, data);\n if (walkerRef.current && !event.isDefaultPrevented()) {\n navigate(data, walkerRef.current);\n }\n },\n );\n\n return {\n treeType: 'flat',\n ...useRootTree({ ...props, onNavigation: handleNavigation }, useMergedRefs(ref, initializeWalker)),\n };\n}\n\nfunction useSubFlatTree(props: FlatTreeProps, ref: React.Ref<HTMLElement>): FlatTreeState {\n if (process.env.NODE_ENV === 'development') {\n throw new Error(/* #__DE-INDENT__ */ `\n @fluentui/react-tree [useFlatTree]:\n Subtrees are not allowed in a FlatTree!\n You cannot use a <FlatTree> component inside of another <FlatTree> nor a <Tree> component!\n `);\n }\n return {\n ...useSubtree(props, ref),\n // ------ defaultTreeContextValue\n level: 0,\n contextType: 'root',\n treeType: 'nested',\n selectionMode: 'none',\n openItems: ImmutableSet.empty,\n checkedItems: ImmutableMap.empty,\n requestTreeResponse: noop,\n appearance: 'subtle',\n size: 'medium',\n // ------ defaultTreeContextValue\n open: false,\n };\n}\n\nfunction noop() {\n /* do nothing */\n}\n"],"names":["React","useRootTree","useFlatTreeNavigation","createHTMLElementWalker","useFluent_unstable","treeItemFilter","useEventCallback","useMergedRefs","useSubtree","ImmutableSet","ImmutableMap","SubtreeContext","useFlatTree_unstable","props","ref","isRoot","useContext","undefined","useRootFlatTree","useSubFlatTree","navigate","initialize","walkerRef","useRef","targetDocument","initializeWalker","useCallback","root","current","handleNavigation","event","data","onNavigation","isDefaultPrevented","treeType","process","env","NODE_ENV","Error","level","contextType","selectionMode","openItems","empty","checkedItems","requestTreeResponse","noop","appearance","size","open"],"mappings":"AAAA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,WAAW,QAAQ,0BAA0B;AAEtD,SAASC,qBAAqB,QAAQ,0BAA0B;AAChE,SAA4BC,uBAAuB,QAAQ,sCAAsC;AACjG,SAASC,kBAAkB,QAAQ,kCAAkC;AACrE,SAASC,cAAc,QAAQ,6BAA6B;AAC5D,SAASC,gBAAgB,EAAEC,aAAa,QAAQ,4BAA4B;AAE5E,SAASC,UAAU,QAAQ,yBAAyB;AACpD,SAASC,YAAY,QAAQ,2BAA2B;AACxD,SAASC,YAAY,QAAQ,2BAA2B;AACxD,SAASC,cAAc,QAAQ,gCAAgC;AAE/D,OAAO,MAAMC,uBAA6F,CACxGC,OACAC;IAEA,MAAMC,SAASf,MAAMgB,UAAU,CAACL,oBAAoBM;IACpD,uDAAuD;IACvD,sEAAsE;IACtE,sDAAsD;IACtD,OAAOF,SAASG,gBAAgBL,OAAOC,OAAOK,eAAeN,OAAOC;AACtE,EAAE;AAEF,SAASI,gBAAgBL,KAAoB,EAAEC,GAA2B;IACxE,MAAM,EAAEM,QAAQ,EAAEC,UAAU,EAAE,GAAGnB;IACjC,MAAMoB,YAAYtB,MAAMuB,MAAM;IAC9B,MAAM,EAAEC,cAAc,EAAE,GAAGpB;IAE3B,MAAMqB,mBAAmBzB,MAAM0B,WAAW,CACxC,CAACC;QACC,IAAIA,QAAQH,gBAAgB;YAC1BF,UAAUM,OAAO,GAAGzB,wBAAwBwB,MAAMH,gBAAgBnB;YAClEgB,WAAWC,UAAUM,OAAO;QAC9B;IACF,GACA;QAACP;QAAYG;KAAe;IAG9B,MAAMK,mBAAmBvB,iBACvB,CAACwB,OAAqCC;YACpClB;SAAAA,sBAAAA,MAAMmB,YAAY,cAAlBnB,0CAAAA,yBAAAA,OAAqBiB,OAAOC;QAC5B,IAAIT,UAAUM,OAAO,IAAI,CAACE,MAAMG,kBAAkB,IAAI;YACpDb,SAASW,MAAMT,UAAUM,OAAO;QAClC;IACF;IAGF,OAAO;QACLM,UAAU;QACV,GAAGjC,YAAY;YAAE,GAAGY,KAAK;YAAEmB,cAAcH;QAAiB,GAAGtB,cAAcO,KAAKW,kBAAkB;IACpG;AACF;AAEA,SAASN,eAAeN,KAAoB,EAAEC,GAA2B;IACvE,IAAIqB,QAAQC,GAAG,CAACC,QAAQ,KAAK,eAAe;QAC1C,MAAM,IAAIC,MAA2B,CAAC;;0FAItC,CAAC;IACH;IACA,OAAO;QACL,GAAG9B,WAAWK,OAAOC,IAAI;QACzB,iCAAiC;QACjCyB,OAAO;QACPC,aAAa;QACbN,UAAU;QACVO,eAAe;QACfC,WAAWjC,aAAakC,KAAK;QAC7BC,cAAclC,aAAaiC,KAAK;QAChCE,qBAAqBC;QACrBC,YAAY;QACZC,MAAM;QACN,iCAAiC;QACjCC,MAAM;IACR;AACF;AAEA,SAASH;AACP,cAAc,GAChB"}
|
|
@@ -71,10 +71,15 @@ function useNestedRootTree(props, ref) {
|
|
|
71
71
|
};
|
|
72
72
|
}
|
|
73
73
|
function useNestedSubtree(props, ref) {
|
|
74
|
-
if (
|
|
75
|
-
//
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
if (process.env.NODE_ENV === 'development') {
|
|
75
|
+
// this doesn't break rule of hooks, as environment is a static value
|
|
76
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
77
|
+
const treeType = useTreeContext_unstable((ctx)=>ctx.treeType);
|
|
78
|
+
if (treeType === 'flat') {
|
|
79
|
+
throw new Error(`@fluentui/react-tree [useTree]:
|
|
80
|
+
Subtrees are not allowed in a FlatTree!
|
|
81
|
+
You cannot use a <Tree> component inside of a <FlatTree> component!`);
|
|
82
|
+
}
|
|
78
83
|
}
|
|
79
84
|
return useSubtree(props, ref);
|
|
80
85
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["useTree.ts"],"sourcesContent":["import * as React from 'react';\nimport { useEventCallback, useMergedRefs } from '@fluentui/react-utilities';\nimport type {\n TreeCheckedChangeData,\n TreeCheckedChangeEvent,\n TreeNavigationData_unstable,\n TreeNavigationEvent_unstable,\n TreeOpenChangeData,\n TreeOpenChangeEvent,\n TreeProps,\n TreeState,\n} from './Tree.types';\nimport { createNextOpenItems, useControllableOpenItems } from '../../hooks/useControllableOpenItems';\nimport { createNextNestedCheckedItems, useNestedCheckedItems } from './useNestedControllableCheckedItems';\nimport { SubtreeContext } from '../../contexts/subtreeContext';\nimport { useRootTree } from '../../hooks/useRootTree';\nimport { useSubtree } from '../../hooks/useSubtree';\nimport { HTMLElementWalker, createHTMLElementWalker } from '../../utils/createHTMLElementWalker';\nimport { treeItemFilter } from '../../utils/treeItemFilter';\nimport { useTreeNavigation } from './useTreeNavigation';\nimport { useFluent_unstable } from '@fluentui/react-shared-contexts';\nimport { useTreeContext_unstable } from '../../contexts/treeContext';\n\nexport const useTree_unstable = (props: TreeProps, ref: React.Ref<HTMLElement>): TreeState => {\n const isRoot = React.useContext(SubtreeContext) === undefined;\n // as level is static, this doesn't break rule of hooks\n // and if this becomes an issue later on, this can be easily converted\n // eslint-disable-next-line react-hooks/rules-of-hooks\n return isRoot ? useNestedRootTree(props, ref) : useNestedSubtree(props, ref);\n};\n\nfunction useNestedRootTree(props: TreeProps, ref: React.Ref<HTMLElement>): TreeState {\n const [openItems, setOpenItems] = useControllableOpenItems(props);\n const checkedItems = useNestedCheckedItems(props);\n const { navigate, initialize } = useTreeNavigation();\n const walkerRef = React.useRef<HTMLElementWalker>();\n const { targetDocument } = useFluent_unstable();\n\n const initializeWalker = React.useCallback(\n (root: HTMLElement | null) => {\n if (root && targetDocument) {\n walkerRef.current = createHTMLElementWalker(root, targetDocument, treeItemFilter);\n initialize(walkerRef.current);\n }\n },\n [initialize, targetDocument],\n );\n\n const handleOpenChange = useEventCallback((event: TreeOpenChangeEvent, data: TreeOpenChangeData) => {\n const nextOpenItems = createNextOpenItems(data, openItems);\n props.onOpenChange?.(event, {\n ...data,\n openItems: nextOpenItems.dangerouslyGetInternalSet_unstable(),\n });\n setOpenItems(nextOpenItems);\n });\n\n const handleCheckedChange = useEventCallback((event: TreeCheckedChangeEvent, data: TreeCheckedChangeData) => {\n if (walkerRef.current) {\n const nextCheckedItems = createNextNestedCheckedItems(data, checkedItems);\n props.onCheckedChange?.(event, {\n ...data,\n checkedItems: nextCheckedItems.dangerouslyGetInternalMap_unstable(),\n });\n }\n });\n const handleNavigation = useEventCallback(\n (event: TreeNavigationEvent_unstable, data: TreeNavigationData_unstable) => {\n props.onNavigation?.(event, data);\n if (walkerRef.current && !event.isDefaultPrevented()) {\n navigate(data, walkerRef.current);\n }\n },\n );\n\n return {\n treeType: 'nested',\n ...useRootTree(\n {\n ...props,\n openItems,\n checkedItems,\n onOpenChange: handleOpenChange,\n onNavigation: handleNavigation,\n onCheckedChange: handleCheckedChange,\n },\n useMergedRefs(ref, initializeWalker),\n ),\n };\n}\n\nfunction useNestedSubtree(props: TreeProps, ref: React.Ref<HTMLElement>): TreeState {\n if (
|
|
1
|
+
{"version":3,"sources":["useTree.ts"],"sourcesContent":["import * as React from 'react';\nimport { useEventCallback, useMergedRefs } from '@fluentui/react-utilities';\nimport type {\n TreeCheckedChangeData,\n TreeCheckedChangeEvent,\n TreeNavigationData_unstable,\n TreeNavigationEvent_unstable,\n TreeOpenChangeData,\n TreeOpenChangeEvent,\n TreeProps,\n TreeState,\n} from './Tree.types';\nimport { createNextOpenItems, useControllableOpenItems } from '../../hooks/useControllableOpenItems';\nimport { createNextNestedCheckedItems, useNestedCheckedItems } from './useNestedControllableCheckedItems';\nimport { SubtreeContext } from '../../contexts/subtreeContext';\nimport { useRootTree } from '../../hooks/useRootTree';\nimport { useSubtree } from '../../hooks/useSubtree';\nimport { HTMLElementWalker, createHTMLElementWalker } from '../../utils/createHTMLElementWalker';\nimport { treeItemFilter } from '../../utils/treeItemFilter';\nimport { useTreeNavigation } from './useTreeNavigation';\nimport { useFluent_unstable } from '@fluentui/react-shared-contexts';\nimport { useTreeContext_unstable } from '../../contexts/treeContext';\n\nexport const useTree_unstable = (props: TreeProps, ref: React.Ref<HTMLElement>): TreeState => {\n const isRoot = React.useContext(SubtreeContext) === undefined;\n // as level is static, this doesn't break rule of hooks\n // and if this becomes an issue later on, this can be easily converted\n // eslint-disable-next-line react-hooks/rules-of-hooks\n return isRoot ? useNestedRootTree(props, ref) : useNestedSubtree(props, ref);\n};\n\nfunction useNestedRootTree(props: TreeProps, ref: React.Ref<HTMLElement>): TreeState {\n const [openItems, setOpenItems] = useControllableOpenItems(props);\n const checkedItems = useNestedCheckedItems(props);\n const { navigate, initialize } = useTreeNavigation();\n const walkerRef = React.useRef<HTMLElementWalker>();\n const { targetDocument } = useFluent_unstable();\n\n const initializeWalker = React.useCallback(\n (root: HTMLElement | null) => {\n if (root && targetDocument) {\n walkerRef.current = createHTMLElementWalker(root, targetDocument, treeItemFilter);\n initialize(walkerRef.current);\n }\n },\n [initialize, targetDocument],\n );\n\n const handleOpenChange = useEventCallback((event: TreeOpenChangeEvent, data: TreeOpenChangeData) => {\n const nextOpenItems = createNextOpenItems(data, openItems);\n props.onOpenChange?.(event, {\n ...data,\n openItems: nextOpenItems.dangerouslyGetInternalSet_unstable(),\n });\n setOpenItems(nextOpenItems);\n });\n\n const handleCheckedChange = useEventCallback((event: TreeCheckedChangeEvent, data: TreeCheckedChangeData) => {\n if (walkerRef.current) {\n const nextCheckedItems = createNextNestedCheckedItems(data, checkedItems);\n props.onCheckedChange?.(event, {\n ...data,\n checkedItems: nextCheckedItems.dangerouslyGetInternalMap_unstable(),\n });\n }\n });\n const handleNavigation = useEventCallback(\n (event: TreeNavigationEvent_unstable, data: TreeNavigationData_unstable) => {\n props.onNavigation?.(event, data);\n if (walkerRef.current && !event.isDefaultPrevented()) {\n navigate(data, walkerRef.current);\n }\n },\n );\n\n return {\n treeType: 'nested',\n ...useRootTree(\n {\n ...props,\n openItems,\n checkedItems,\n onOpenChange: handleOpenChange,\n onNavigation: handleNavigation,\n onCheckedChange: handleCheckedChange,\n },\n useMergedRefs(ref, initializeWalker),\n ),\n };\n}\n\nfunction useNestedSubtree(props: TreeProps, ref: React.Ref<HTMLElement>): TreeState {\n if (process.env.NODE_ENV === 'development') {\n // this doesn't break rule of hooks, as environment is a static value\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const treeType = useTreeContext_unstable(ctx => ctx.treeType);\n if (treeType === 'flat') {\n throw new Error(/* #__DE-INDENT__ */ `\n @fluentui/react-tree [useTree]:\n Subtrees are not allowed in a FlatTree!\n You cannot use a <Tree> component inside of a <FlatTree> component!\n `);\n }\n }\n return useSubtree(props, ref);\n}\n"],"names":["React","useEventCallback","useMergedRefs","createNextOpenItems","useControllableOpenItems","createNextNestedCheckedItems","useNestedCheckedItems","SubtreeContext","useRootTree","useSubtree","createHTMLElementWalker","treeItemFilter","useTreeNavigation","useFluent_unstable","useTreeContext_unstable","useTree_unstable","props","ref","isRoot","useContext","undefined","useNestedRootTree","useNestedSubtree","openItems","setOpenItems","checkedItems","navigate","initialize","walkerRef","useRef","targetDocument","initializeWalker","useCallback","root","current","handleOpenChange","event","data","nextOpenItems","onOpenChange","dangerouslyGetInternalSet_unstable","handleCheckedChange","nextCheckedItems","onCheckedChange","dangerouslyGetInternalMap_unstable","handleNavigation","onNavigation","isDefaultPrevented","treeType","process","env","NODE_ENV","ctx","Error"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import * as ReactDOM from 'react-dom';
|
|
3
|
-
import { getIntrinsicElementProps, useId,
|
|
3
|
+
import { getIntrinsicElementProps, useId, useEventCallback, slot, elementContains, useMergedRefs } from '@fluentui/react-utilities';
|
|
4
4
|
import { Space } from '@fluentui/keyboard-keys';
|
|
5
5
|
import { treeDataTypes } from '../../utils/tokens';
|
|
6
6
|
import { useTreeContext_unstable, useSubtreeContext_unstable, useTreeItemContext_unstable } from '../../contexts';
|
|
@@ -30,16 +30,12 @@ import { dataTreeItemValueAttrName } from '../../utils/getTreeItemValueFromEleme
|
|
|
30
30
|
var _props_value;
|
|
31
31
|
const value = (_props_value = props.value) !== null && _props_value !== void 0 ? _props_value : internalValue;
|
|
32
32
|
const { onClick, onKeyDown, onMouseOver, onFocus, onMouseOut, onBlur, onChange, as = 'div', itemType = 'leaf', 'aria-level': level = contextLevel, ...rest } = props;
|
|
33
|
-
const [isActionsVisible, setActionsVisible] = React.useState(false);
|
|
34
|
-
const [isAsideVisible, setAsideVisible] = React.useState(true);
|
|
35
|
-
const handleActionsRef = React.useCallback((actionsElement)=>{
|
|
36
|
-
setAsideVisible(actionsElement === null);
|
|
37
|
-
}, []);
|
|
38
33
|
const actionsRef = React.useRef(null);
|
|
39
34
|
const expandIconRef = React.useRef(null);
|
|
40
35
|
const layoutRef = React.useRef(null);
|
|
41
36
|
const subtreeRef = React.useRef(null);
|
|
42
37
|
const selectionRef = React.useRef(null);
|
|
38
|
+
const treeItemRef = React.useRef(null);
|
|
43
39
|
const open = useTreeContext_unstable((ctx)=>{
|
|
44
40
|
var _props_open;
|
|
45
41
|
return (_props_open = props.open) !== null && _props_open !== void 0 ? _props_open : ctx.openItems.has(value);
|
|
@@ -183,38 +179,6 @@ import { dataTreeItemValueAttrName } from '../../utils/getTreeItemValueFromEleme
|
|
|
183
179
|
});
|
|
184
180
|
}
|
|
185
181
|
});
|
|
186
|
-
const setActionsVisibleIfNotFromSubtree = React.useCallback((event)=>{
|
|
187
|
-
const isTargetFromSubtree = Boolean(subtreeRef.current && elementContains(subtreeRef.current, event.target));
|
|
188
|
-
if (!isTargetFromSubtree) {
|
|
189
|
-
setActionsVisible(true);
|
|
190
|
-
}
|
|
191
|
-
}, []);
|
|
192
|
-
const setActionsInvisibleIfNotFromSubtree = React.useCallback((event)=>{
|
|
193
|
-
const isTargetFromSubtree = Boolean(subtreeRef.current && elementContains(subtreeRef.current, event.target));
|
|
194
|
-
const isRelatedTargetFromActions = Boolean(actionsRef.current && elementContains(actionsRef.current, event.relatedTarget));
|
|
195
|
-
if (isRelatedTargetFromActions) {
|
|
196
|
-
return setActionsVisible(true);
|
|
197
|
-
}
|
|
198
|
-
if (!isTargetFromSubtree) {
|
|
199
|
-
return setActionsVisible(false);
|
|
200
|
-
}
|
|
201
|
-
}, []);
|
|
202
|
-
const handleMouseOver = useEventCallback((event)=>{
|
|
203
|
-
onMouseOver === null || onMouseOver === void 0 ? void 0 : onMouseOver(event);
|
|
204
|
-
setActionsVisibleIfNotFromSubtree(event);
|
|
205
|
-
});
|
|
206
|
-
const handleFocus = useEventCallback((event)=>{
|
|
207
|
-
onFocus === null || onFocus === void 0 ? void 0 : onFocus(event);
|
|
208
|
-
setActionsVisibleIfNotFromSubtree(event);
|
|
209
|
-
});
|
|
210
|
-
const handleMouseOut = useEventCallback((event)=>{
|
|
211
|
-
onMouseOut === null || onMouseOut === void 0 ? void 0 : onMouseOut(event);
|
|
212
|
-
setActionsInvisibleIfNotFromSubtree(event);
|
|
213
|
-
});
|
|
214
|
-
const handleBlur = useEventCallback((event)=>{
|
|
215
|
-
onBlur === null || onBlur === void 0 ? void 0 : onBlur(event);
|
|
216
|
-
setActionsInvisibleIfNotFromSubtree(event);
|
|
217
|
-
});
|
|
218
182
|
const handleChange = useEventCallback((event)=>{
|
|
219
183
|
onChange === null || onChange === void 0 ? void 0 : onChange(event);
|
|
220
184
|
if (event.isDefaultPrevented()) {
|
|
@@ -242,19 +206,22 @@ import { dataTreeItemValueAttrName } from '../../utils/getTreeItemValueFromEleme
|
|
|
242
206
|
layoutRef,
|
|
243
207
|
selectionRef,
|
|
244
208
|
expandIconRef,
|
|
245
|
-
|
|
209
|
+
treeItemRef,
|
|
210
|
+
actionsRef,
|
|
246
211
|
itemType,
|
|
247
212
|
level,
|
|
248
213
|
components: {
|
|
249
214
|
root: 'div'
|
|
250
215
|
},
|
|
251
|
-
|
|
252
|
-
|
|
216
|
+
// FIXME: this property is not necessary anymore, but as removing it would be a breaking change, we need to keep it as false
|
|
217
|
+
isAsideVisible: false,
|
|
218
|
+
// FIXME: this property is not necessary anymore, but as removing it would be a breaking change, we need to keep it as false
|
|
219
|
+
isActionsVisible: false,
|
|
253
220
|
root: slot.always(getIntrinsicElementProps(as, {
|
|
254
221
|
tabIndex: -1,
|
|
255
222
|
[dataTreeItemValueAttrName]: value,
|
|
256
223
|
...rest,
|
|
257
|
-
ref,
|
|
224
|
+
ref: useMergedRefs(ref, treeItemRef),
|
|
258
225
|
role: 'treeitem',
|
|
259
226
|
'aria-level': level,
|
|
260
227
|
'aria-checked': selectionMode === 'multiselect' ? checked : undefined,
|
|
@@ -265,10 +232,6 @@ import { dataTreeItemValueAttrName } from '../../utils/getTreeItemValueFromEleme
|
|
|
265
232
|
'aria-expanded': itemType === 'branch' ? open : undefined,
|
|
266
233
|
onClick: handleClick,
|
|
267
234
|
onKeyDown: handleKeyDown,
|
|
268
|
-
onMouseOver: handleMouseOver,
|
|
269
|
-
onFocus: handleFocus,
|
|
270
|
-
onMouseOut: handleMouseOut,
|
|
271
|
-
onBlur: handleBlur,
|
|
272
235
|
onChange: handleChange
|
|
273
236
|
}), {
|
|
274
237
|
elementType: 'div'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["useTreeItem.tsx"],"sourcesContent":["import * as React from 'react';\nimport * as ReactDOM from 'react-dom';\nimport {\n getIntrinsicElementProps,\n useId,\n useMergedRefs,\n useEventCallback,\n slot,\n elementContains,\n} from '@fluentui/react-utilities';\nimport type { TreeItemProps, TreeItemState, TreeItemValue } from './TreeItem.types';\nimport { Space } from '@fluentui/keyboard-keys';\nimport { treeDataTypes } from '../../utils/tokens';\nimport { useTreeContext_unstable, useSubtreeContext_unstable, useTreeItemContext_unstable } from '../../contexts';\nimport { dataTreeItemValueAttrName } from '../../utils/getTreeItemValueFromElement';\n\n/**\n * Create the state required to render TreeItem.\n *\n * The returned state can be modified with hooks such as useTreeItemStyles_unstable,\n * before being passed to renderTreeItem_unstable.\n *\n * @param props - props from this instance of TreeItem\n * @param ref - reference to root HTMLElement of TreeItem\n */\nexport function useTreeItem_unstable(props: TreeItemProps, ref: React.Ref<HTMLDivElement>): TreeItemState {\n const treeType = useTreeContext_unstable(ctx => ctx.treeType);\n if (treeType === 'flat') {\n warnIfNoProperPropsFlatTreeItem(props);\n }\n const requestTreeResponse = useTreeContext_unstable(ctx => ctx.requestTreeResponse);\n const { level: contextLevel } = useSubtreeContext_unstable();\n const parentValue = useTreeItemContext_unstable(ctx => props.parentValue ?? ctx.value);\n\n // note, if the value is not externally provided,\n // then selection and expansion will not work properly\n const internalValue = useId('fuiTreeItemValue-');\n const value: TreeItemValue = props.value ?? internalValue;\n\n const {\n onClick,\n onKeyDown,\n onMouseOver,\n onFocus,\n onMouseOut,\n onBlur,\n onChange,\n as = 'div',\n itemType = 'leaf',\n 'aria-level': level = contextLevel,\n ...rest\n } = props;\n\n const [isActionsVisible, setActionsVisible] = React.useState(false);\n const [isAsideVisible, setAsideVisible] = React.useState(true);\n\n const handleActionsRef = React.useCallback((actionsElement: HTMLDivElement | null) => {\n setAsideVisible(actionsElement === null);\n }, []);\n\n const actionsRef = React.useRef<HTMLDivElement>(null);\n const expandIconRef = React.useRef<HTMLDivElement>(null);\n const layoutRef = React.useRef<HTMLDivElement>(null);\n const subtreeRef = React.useRef<HTMLDivElement>(null);\n const selectionRef = React.useRef<HTMLInputElement>(null);\n\n const open = useTreeContext_unstable(ctx => props.open ?? ctx.openItems.has(value));\n const selectionMode = useTreeContext_unstable(ctx => ctx.selectionMode);\n const checked = useTreeContext_unstable(ctx => ctx.checkedItems.get(value) ?? false);\n\n const handleClick = useEventCallback((event: React.MouseEvent<HTMLDivElement>) => {\n onClick?.(event);\n if (event.isDefaultPrevented()) {\n return;\n }\n const isEventFromActions = actionsRef.current && elementContains(actionsRef.current, event.target as Node);\n if (isEventFromActions) {\n return;\n }\n const isEventFromSubtree = subtreeRef.current && elementContains(subtreeRef.current, event.target as Node);\n if (isEventFromSubtree) {\n return;\n }\n const isEventFromSelection = selectionRef.current && elementContains(selectionRef.current, event.target as Node);\n if (isEventFromSelection) {\n return;\n }\n const isEventFromExpandIcon = expandIconRef.current && elementContains(expandIconRef.current, event.target as Node);\n\n ReactDOM.unstable_batchedUpdates(() => {\n const data = {\n event,\n value,\n open: !open,\n target: event.currentTarget,\n type: isEventFromExpandIcon ? treeDataTypes.ExpandIconClick : treeDataTypes.Click,\n } as const;\n props.onOpenChange?.(event, data);\n requestTreeResponse({\n ...data,\n itemType,\n requestType: 'open',\n });\n requestTreeResponse({\n ...data,\n itemType,\n parentValue,\n requestType: 'navigate',\n type: treeDataTypes.Click,\n });\n });\n });\n\n const handleKeyDown = useEventCallback((event: React.KeyboardEvent<HTMLDivElement>) => {\n onKeyDown?.(event);\n // Ignore keyboard events that do not originate from the current tree item.\n if (event.isDefaultPrevented() || event.currentTarget !== event.target) {\n return;\n }\n switch (event.key) {\n case Space:\n if (selectionMode !== 'none') {\n selectionRef.current?.click();\n // Prevents the page from scrolling down when the spacebar is pressed\n event.preventDefault();\n }\n return;\n case treeDataTypes.Enter: {\n return event.currentTarget.click();\n }\n case treeDataTypes.End:\n case treeDataTypes.Home:\n case treeDataTypes.ArrowUp:\n case treeDataTypes.ArrowDown:\n return requestTreeResponse({\n requestType: 'navigate',\n event,\n value,\n itemType,\n parentValue,\n type: event.key,\n target: event.currentTarget,\n });\n case treeDataTypes.ArrowLeft: {\n // do not navigate to parent if the item is on the top level\n if (level === 1 && !open) {\n return;\n }\n const data = {\n value,\n event,\n open: !open,\n type: event.key,\n target: event.currentTarget,\n } as const;\n if (open) {\n props.onOpenChange?.(event, data);\n }\n return requestTreeResponse({\n ...data,\n itemType,\n parentValue,\n requestType: open ? 'open' : 'navigate',\n });\n }\n case treeDataTypes.ArrowRight:\n // do not navigate or open if the item is a leaf\n if (itemType === 'leaf') {\n return;\n }\n const data = {\n value,\n event,\n open: !open,\n type: event.key,\n target: event.currentTarget,\n } as const;\n if (!open) {\n props.onOpenChange?.(event, data);\n }\n return requestTreeResponse({\n ...data,\n itemType,\n parentValue,\n requestType: open ? 'navigate' : 'open',\n });\n }\n const isTypeAheadCharacter =\n event.key.length === 1 && event.key.match(/\\w/) && !event.altKey && !event.ctrlKey && !event.metaKey;\n if (isTypeAheadCharacter) {\n requestTreeResponse({\n requestType: 'navigate',\n event,\n target: event.currentTarget,\n value,\n itemType,\n type: treeDataTypes.TypeAhead,\n parentValue,\n });\n }\n });\n\n const setActionsVisibleIfNotFromSubtree = React.useCallback((event: React.SyntheticEvent<HTMLDivElement>) => {\n const isTargetFromSubtree = Boolean(\n subtreeRef.current && elementContains(subtreeRef.current, event.target as Node),\n );\n if (!isTargetFromSubtree) {\n setActionsVisible(true);\n }\n }, []);\n const setActionsInvisibleIfNotFromSubtree = React.useCallback(\n (event: React.MouseEvent<HTMLDivElement> | React.FocusEvent<HTMLDivElement>) => {\n const isTargetFromSubtree = Boolean(\n subtreeRef.current && elementContains(subtreeRef.current, event.target as Node),\n );\n const isRelatedTargetFromActions = Boolean(\n actionsRef.current && elementContains(actionsRef.current, event.relatedTarget as Node),\n );\n if (isRelatedTargetFromActions) {\n return setActionsVisible(true);\n }\n if (!isTargetFromSubtree) {\n return setActionsVisible(false);\n }\n },\n [],\n );\n\n const handleMouseOver = useEventCallback((event: React.MouseEvent<HTMLDivElement>) => {\n onMouseOver?.(event);\n setActionsVisibleIfNotFromSubtree(event);\n });\n\n const handleFocus = useEventCallback((event: React.FocusEvent<HTMLDivElement>) => {\n onFocus?.(event);\n setActionsVisibleIfNotFromSubtree(event);\n });\n\n const handleMouseOut = useEventCallback((event: React.MouseEvent<HTMLDivElement>) => {\n onMouseOut?.(event);\n setActionsInvisibleIfNotFromSubtree(event);\n });\n const handleBlur = useEventCallback((event: React.FocusEvent<HTMLDivElement>) => {\n onBlur?.(event);\n setActionsInvisibleIfNotFromSubtree(event);\n });\n\n const handleChange = useEventCallback((event: React.ChangeEvent<HTMLInputElement>) => {\n onChange?.(event);\n if (event.isDefaultPrevented()) {\n return;\n }\n const isEventFromSubtree = subtreeRef.current && elementContains(subtreeRef.current, event.target as Node);\n if (isEventFromSubtree) {\n return;\n }\n requestTreeResponse({\n requestType: 'selection',\n event,\n value,\n itemType,\n type: 'Change',\n target: event.currentTarget,\n checked: checked === 'mixed' ? true : !checked,\n });\n });\n\n return {\n value,\n open,\n checked,\n subtreeRef,\n layoutRef,\n selectionRef,\n expandIconRef,\n actionsRef: useMergedRefs(handleActionsRef, actionsRef),\n itemType,\n level,\n components: {\n root: 'div',\n },\n isAsideVisible,\n isActionsVisible,\n root: slot.always(\n getIntrinsicElementProps(as, {\n tabIndex: -1,\n [dataTreeItemValueAttrName]: value,\n ...rest,\n ref,\n role: 'treeitem',\n 'aria-level': level,\n 'aria-checked': selectionMode === 'multiselect' ? checked : undefined,\n // aria-selected is required according to WAI-ARIA spec\n // https://www.w3.org/TR/wai-aria-1.1/#treeitem\n // Casting: when selectionMode is 'single', checked is a boolean\n 'aria-selected': selectionMode === 'single' ? (checked as boolean) : 'false',\n 'aria-expanded': itemType === 'branch' ? open : undefined,\n onClick: handleClick,\n onKeyDown: handleKeyDown,\n onMouseOver: handleMouseOver,\n onFocus: handleFocus,\n onMouseOut: handleMouseOut,\n onBlur: handleBlur,\n onChange: handleChange,\n } as const),\n { elementType: 'div' },\n ),\n };\n}\n\nfunction warnIfNoProperPropsFlatTreeItem(\n props: Pick<TreeItemProps, 'aria-setsize' | 'aria-posinset' | 'aria-level' | 'parentValue'>,\n) {\n if (process.env.NODE_ENV !== 'production') {\n if (\n props['aria-posinset'] === undefined ||\n props['aria-setsize'] === undefined ||\n props['aria-level'] === undefined ||\n (props.parentValue === undefined && props['aria-level'] !== 1)\n ) {\n // eslint-disable-next-line no-console\n console.error(/** #__DE-INDENT__ */ `\n @fluentui/react-tree [${useTreeItem_unstable.name}]:\n A flat treeitem must have \"aria-posinset\", \"aria-setsize\", \"aria-level\"\n and \"parentValue\" (if \"aria-level\" > 1) to ensure a11y and navigation.\n\n - \"aria-posinset\": the position of this treeitem in the current level of the tree.\n - \"aria-setsize\": the number of siblings in this level of the tree.\n - \"aria-level\": the current level of the treeitem.\n - \"parentValue\": the \"value\" property of the parent item of this item.\n `);\n }\n }\n}\n"],"names":["React","ReactDOM","getIntrinsicElementProps","useId","useMergedRefs","useEventCallback","slot","elementContains","Space","treeDataTypes","useTreeContext_unstable","useSubtreeContext_unstable","useTreeItemContext_unstable","dataTreeItemValueAttrName","useTreeItem_unstable","props","ref","treeType","ctx","warnIfNoProperPropsFlatTreeItem","requestTreeResponse","level","contextLevel","parentValue","value","internalValue","onClick","onKeyDown","onMouseOver","onFocus","onMouseOut","onBlur","onChange","as","itemType","rest","isActionsVisible","setActionsVisible","useState","isAsideVisible","setAsideVisible","handleActionsRef","useCallback","actionsElement","actionsRef","useRef","expandIconRef","layoutRef","subtreeRef","selectionRef","open","openItems","has","selectionMode","checked","checkedItems","get","handleClick","event","isDefaultPrevented","isEventFromActions","current","target","isEventFromSubtree","isEventFromSelection","isEventFromExpandIcon","unstable_batchedUpdates","data","currentTarget","type","ExpandIconClick","Click","onOpenChange","requestType","handleKeyDown","key","click","preventDefault","Enter","End","Home","ArrowUp","ArrowDown","ArrowLeft","ArrowRight","isTypeAheadCharacter","length","match","altKey","ctrlKey","metaKey","TypeAhead","setActionsVisibleIfNotFromSubtree","isTargetFromSubtree","Boolean","setActionsInvisibleIfNotFromSubtree","isRelatedTargetFromActions","relatedTarget","handleMouseOver","handleFocus","handleMouseOut","handleBlur","handleChange","components","root","always","tabIndex","role","undefined","elementType","process","env","NODE_ENV","console","error","name"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["useTreeItem.tsx"],"sourcesContent":["import * as React from 'react';\nimport * as ReactDOM from 'react-dom';\nimport {\n getIntrinsicElementProps,\n useId,\n useEventCallback,\n slot,\n elementContains,\n useMergedRefs,\n} from '@fluentui/react-utilities';\nimport type { TreeItemProps, TreeItemState, TreeItemValue } from './TreeItem.types';\nimport { Space } from '@fluentui/keyboard-keys';\nimport { treeDataTypes } from '../../utils/tokens';\nimport { useTreeContext_unstable, useSubtreeContext_unstable, useTreeItemContext_unstable } from '../../contexts';\nimport { dataTreeItemValueAttrName } from '../../utils/getTreeItemValueFromElement';\n\n/**\n * Create the state required to render TreeItem.\n *\n * The returned state can be modified with hooks such as useTreeItemStyles_unstable,\n * before being passed to renderTreeItem_unstable.\n *\n * @param props - props from this instance of TreeItem\n * @param ref - reference to root HTMLElement of TreeItem\n */\nexport function useTreeItem_unstable(props: TreeItemProps, ref: React.Ref<HTMLDivElement>): TreeItemState {\n const treeType = useTreeContext_unstable(ctx => ctx.treeType);\n if (treeType === 'flat') {\n warnIfNoProperPropsFlatTreeItem(props);\n }\n const requestTreeResponse = useTreeContext_unstable(ctx => ctx.requestTreeResponse);\n const { level: contextLevel } = useSubtreeContext_unstable();\n const parentValue = useTreeItemContext_unstable(ctx => props.parentValue ?? ctx.value);\n\n // note, if the value is not externally provided,\n // then selection and expansion will not work properly\n const internalValue = useId('fuiTreeItemValue-');\n const value: TreeItemValue = props.value ?? internalValue;\n\n const {\n onClick,\n onKeyDown,\n onMouseOver,\n onFocus,\n onMouseOut,\n onBlur,\n onChange,\n as = 'div',\n itemType = 'leaf',\n 'aria-level': level = contextLevel,\n ...rest\n } = props;\n\n const actionsRef = React.useRef<HTMLDivElement>(null);\n const expandIconRef = React.useRef<HTMLDivElement>(null);\n const layoutRef = React.useRef<HTMLDivElement>(null);\n const subtreeRef = React.useRef<HTMLDivElement>(null);\n const selectionRef = React.useRef<HTMLInputElement>(null);\n const treeItemRef = React.useRef<HTMLDivElement>(null);\n\n const open = useTreeContext_unstable(ctx => props.open ?? ctx.openItems.has(value));\n const selectionMode = useTreeContext_unstable(ctx => ctx.selectionMode);\n const checked = useTreeContext_unstable(ctx => ctx.checkedItems.get(value) ?? false);\n\n const handleClick = useEventCallback((event: React.MouseEvent<HTMLDivElement>) => {\n onClick?.(event);\n if (event.isDefaultPrevented()) {\n return;\n }\n const isEventFromActions = actionsRef.current && elementContains(actionsRef.current, event.target as Node);\n if (isEventFromActions) {\n return;\n }\n const isEventFromSubtree = subtreeRef.current && elementContains(subtreeRef.current, event.target as Node);\n if (isEventFromSubtree) {\n return;\n }\n const isEventFromSelection = selectionRef.current && elementContains(selectionRef.current, event.target as Node);\n if (isEventFromSelection) {\n return;\n }\n const isEventFromExpandIcon = expandIconRef.current && elementContains(expandIconRef.current, event.target as Node);\n\n ReactDOM.unstable_batchedUpdates(() => {\n const data = {\n event,\n value,\n open: !open,\n target: event.currentTarget,\n type: isEventFromExpandIcon ? treeDataTypes.ExpandIconClick : treeDataTypes.Click,\n } as const;\n props.onOpenChange?.(event, data);\n requestTreeResponse({\n ...data,\n itemType,\n requestType: 'open',\n });\n requestTreeResponse({\n ...data,\n itemType,\n parentValue,\n requestType: 'navigate',\n type: treeDataTypes.Click,\n });\n });\n });\n\n const handleKeyDown = useEventCallback((event: React.KeyboardEvent<HTMLDivElement>) => {\n onKeyDown?.(event);\n // Ignore keyboard events that do not originate from the current tree item.\n if (event.isDefaultPrevented() || event.currentTarget !== event.target) {\n return;\n }\n switch (event.key) {\n case Space:\n if (selectionMode !== 'none') {\n selectionRef.current?.click();\n // Prevents the page from scrolling down when the spacebar is pressed\n event.preventDefault();\n }\n return;\n case treeDataTypes.Enter: {\n return event.currentTarget.click();\n }\n case treeDataTypes.End:\n case treeDataTypes.Home:\n case treeDataTypes.ArrowUp:\n case treeDataTypes.ArrowDown:\n return requestTreeResponse({\n requestType: 'navigate',\n event,\n value,\n itemType,\n parentValue,\n type: event.key,\n target: event.currentTarget,\n });\n case treeDataTypes.ArrowLeft: {\n // do not navigate to parent if the item is on the top level\n if (level === 1 && !open) {\n return;\n }\n const data = {\n value,\n event,\n open: !open,\n type: event.key,\n target: event.currentTarget,\n } as const;\n if (open) {\n props.onOpenChange?.(event, data);\n }\n return requestTreeResponse({\n ...data,\n itemType,\n parentValue,\n requestType: open ? 'open' : 'navigate',\n });\n }\n case treeDataTypes.ArrowRight:\n // do not navigate or open if the item is a leaf\n if (itemType === 'leaf') {\n return;\n }\n const data = {\n value,\n event,\n open: !open,\n type: event.key,\n target: event.currentTarget,\n } as const;\n if (!open) {\n props.onOpenChange?.(event, data);\n }\n return requestTreeResponse({\n ...data,\n itemType,\n parentValue,\n requestType: open ? 'navigate' : 'open',\n });\n }\n const isTypeAheadCharacter =\n event.key.length === 1 && event.key.match(/\\w/) && !event.altKey && !event.ctrlKey && !event.metaKey;\n if (isTypeAheadCharacter) {\n requestTreeResponse({\n requestType: 'navigate',\n event,\n target: event.currentTarget,\n value,\n itemType,\n type: treeDataTypes.TypeAhead,\n parentValue,\n });\n }\n });\n\n const handleChange = useEventCallback((event: React.ChangeEvent<HTMLInputElement>) => {\n onChange?.(event);\n if (event.isDefaultPrevented()) {\n return;\n }\n const isEventFromSubtree = subtreeRef.current && elementContains(subtreeRef.current, event.target as Node);\n if (isEventFromSubtree) {\n return;\n }\n requestTreeResponse({\n requestType: 'selection',\n event,\n value,\n itemType,\n type: 'Change',\n target: event.currentTarget,\n checked: checked === 'mixed' ? true : !checked,\n });\n });\n\n return {\n value,\n open,\n checked,\n subtreeRef,\n layoutRef,\n selectionRef,\n expandIconRef,\n treeItemRef,\n actionsRef,\n itemType,\n level,\n components: {\n root: 'div',\n },\n // FIXME: this property is not necessary anymore, but as removing it would be a breaking change, we need to keep it as false\n isAsideVisible: false,\n // FIXME: this property is not necessary anymore, but as removing it would be a breaking change, we need to keep it as false\n isActionsVisible: false,\n root: slot.always(\n getIntrinsicElementProps(as, {\n tabIndex: -1,\n [dataTreeItemValueAttrName]: value,\n ...rest,\n ref: useMergedRefs(ref, treeItemRef),\n role: 'treeitem',\n 'aria-level': level,\n 'aria-checked': selectionMode === 'multiselect' ? checked : undefined,\n // aria-selected is required according to WAI-ARIA spec\n // https://www.w3.org/TR/wai-aria-1.1/#treeitem\n // Casting: when selectionMode is 'single', checked is a boolean\n 'aria-selected': selectionMode === 'single' ? (checked as boolean) : 'false',\n 'aria-expanded': itemType === 'branch' ? open : undefined,\n onClick: handleClick,\n onKeyDown: handleKeyDown,\n onChange: handleChange,\n } as const),\n { elementType: 'div' },\n ),\n };\n}\n\nfunction warnIfNoProperPropsFlatTreeItem(\n props: Pick<TreeItemProps, 'aria-setsize' | 'aria-posinset' | 'aria-level' | 'parentValue'>,\n) {\n if (process.env.NODE_ENV !== 'production') {\n if (\n props['aria-posinset'] === undefined ||\n props['aria-setsize'] === undefined ||\n props['aria-level'] === undefined ||\n (props.parentValue === undefined && props['aria-level'] !== 1)\n ) {\n // eslint-disable-next-line no-console\n console.error(/** #__DE-INDENT__ */ `\n @fluentui/react-tree [${useTreeItem_unstable.name}]:\n A flat treeitem must have \"aria-posinset\", \"aria-setsize\", \"aria-level\"\n and \"parentValue\" (if \"aria-level\" > 1) to ensure a11y and navigation.\n\n - \"aria-posinset\": the position of this treeitem in the current level of the tree.\n - \"aria-setsize\": the number of siblings in this level of the tree.\n - \"aria-level\": the current level of the treeitem.\n - \"parentValue\": the \"value\" property of the parent item of this item.\n `);\n }\n }\n}\n"],"names":["React","ReactDOM","getIntrinsicElementProps","useId","useEventCallback","slot","elementContains","useMergedRefs","Space","treeDataTypes","useTreeContext_unstable","useSubtreeContext_unstable","useTreeItemContext_unstable","dataTreeItemValueAttrName","useTreeItem_unstable","props","ref","treeType","ctx","warnIfNoProperPropsFlatTreeItem","requestTreeResponse","level","contextLevel","parentValue","value","internalValue","onClick","onKeyDown","onMouseOver","onFocus","onMouseOut","onBlur","onChange","as","itemType","rest","actionsRef","useRef","expandIconRef","layoutRef","subtreeRef","selectionRef","treeItemRef","open","openItems","has","selectionMode","checked","checkedItems","get","handleClick","event","isDefaultPrevented","isEventFromActions","current","target","isEventFromSubtree","isEventFromSelection","isEventFromExpandIcon","unstable_batchedUpdates","data","currentTarget","type","ExpandIconClick","Click","onOpenChange","requestType","handleKeyDown","key","click","preventDefault","Enter","End","Home","ArrowUp","ArrowDown","ArrowLeft","ArrowRight","isTypeAheadCharacter","length","match","altKey","ctrlKey","metaKey","TypeAhead","handleChange","components","root","isAsideVisible","isActionsVisible","always","tabIndex","role","undefined","elementType","process","env","NODE_ENV","console","error","name"],"mappings":"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"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export function useTreeItemContextValues_unstable(state) {
|
|
2
|
-
const { value, itemType, layoutRef, subtreeRef, open, expandIconRef, actionsRef,
|
|
2
|
+
const { value, itemType, layoutRef, subtreeRef, open, expandIconRef, actionsRef, treeItemRef, // eslint-disable-next-line deprecation/deprecation
|
|
3
|
+
isActionsVisible, // eslint-disable-next-line deprecation/deprecation
|
|
4
|
+
isAsideVisible, selectionRef, checked } = state;
|
|
3
5
|
/**
|
|
4
6
|
* This context is created with "@fluentui/react-context-selector",
|
|
5
7
|
* there is no sense to memoize it
|
|
@@ -14,6 +16,7 @@ export function useTreeItemContextValues_unstable(state) {
|
|
|
14
16
|
isActionsVisible,
|
|
15
17
|
isAsideVisible,
|
|
16
18
|
actionsRef,
|
|
19
|
+
treeItemRef,
|
|
17
20
|
expandIconRef
|
|
18
21
|
};
|
|
19
22
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["useTreeItemContextValues.ts"],"sourcesContent":["import type { TreeItemContextValues, TreeItemState } from './TreeItem.types';\nimport type { TreeItemContextValue } from '../../contexts';\n\nexport function useTreeItemContextValues_unstable(state: TreeItemState): TreeItemContextValues {\n const {\n value,\n itemType,\n layoutRef,\n subtreeRef,\n open,\n expandIconRef,\n actionsRef,\n isActionsVisible,\n isAsideVisible,\n selectionRef,\n checked,\n } = state;\n\n /**\n * This context is created with \"@fluentui/react-context-selector\",\n * there is no sense to memoize it\n */\n const treeItem: TreeItemContextValue = {\n value,\n checked,\n itemType,\n layoutRef,\n subtreeRef,\n open,\n selectionRef,\n isActionsVisible,\n isAsideVisible,\n actionsRef,\n expandIconRef,\n };\n\n return { treeItem };\n}\n"],"names":["useTreeItemContextValues_unstable","state","value","itemType","layoutRef","subtreeRef","open","expandIconRef","actionsRef","isActionsVisible","isAsideVisible","selectionRef","checked","treeItem"],"mappings":"AAGA,OAAO,SAASA,kCAAkCC,KAAoB;IACpE,MAAM,EACJC,KAAK,EACLC,QAAQ,EACRC,SAAS,EACTC,UAAU,EACVC,IAAI,EACJC,aAAa,EACbC,UAAU,EACVC,gBAAgB,
|
|
1
|
+
{"version":3,"sources":["useTreeItemContextValues.ts"],"sourcesContent":["import type { TreeItemContextValues, TreeItemState } from './TreeItem.types';\nimport type { TreeItemContextValue } from '../../contexts';\n\nexport function useTreeItemContextValues_unstable(state: TreeItemState): TreeItemContextValues {\n const {\n value,\n itemType,\n layoutRef,\n subtreeRef,\n open,\n expandIconRef,\n actionsRef,\n treeItemRef,\n // eslint-disable-next-line deprecation/deprecation\n isActionsVisible,\n // eslint-disable-next-line deprecation/deprecation\n isAsideVisible,\n selectionRef,\n checked,\n } = state;\n\n /**\n * This context is created with \"@fluentui/react-context-selector\",\n * there is no sense to memoize it\n */\n const treeItem: TreeItemContextValue = {\n value,\n checked,\n itemType,\n layoutRef,\n subtreeRef,\n open,\n selectionRef,\n isActionsVisible,\n isAsideVisible,\n actionsRef,\n treeItemRef,\n expandIconRef,\n };\n\n return { treeItem };\n}\n"],"names":["useTreeItemContextValues_unstable","state","value","itemType","layoutRef","subtreeRef","open","expandIconRef","actionsRef","treeItemRef","isActionsVisible","isAsideVisible","selectionRef","checked","treeItem"],"mappings":"AAGA,OAAO,SAASA,kCAAkCC,KAAoB;IACpE,MAAM,EACJC,KAAK,EACLC,QAAQ,EACRC,SAAS,EACTC,UAAU,EACVC,IAAI,EACJC,aAAa,EACbC,UAAU,EACVC,WAAW,EACX,mDAAmD;IACnDC,gBAAgB,EAChB,mDAAmD;IACnDC,cAAc,EACdC,YAAY,EACZC,OAAO,EACR,GAAGZ;IAEJ;;;GAGC,GACD,MAAMa,WAAiC;QACrCZ;QACAW;QACAV;QACAC;QACAC;QACAC;QACAM;QACAF;QACAC;QACAH;QACAC;QACAF;IACF;IAEA,OAAO;QAAEO;IAAS;AACpB"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { getIntrinsicElementProps, isResolvedShorthand, useMergedRefs, slot } from '@fluentui/react-utilities';
|
|
2
|
+
import { getIntrinsicElementProps, isResolvedShorthand, useMergedRefs, slot, useEventCallback, elementContains, useControllableState } from '@fluentui/react-utilities';
|
|
3
3
|
import { useTreeItemContext_unstable, useTreeContext_unstable } from '../../contexts';
|
|
4
4
|
import { Checkbox } from '@fluentui/react-checkbox';
|
|
5
5
|
import { Radio } from '@fluentui/react-radio';
|
|
@@ -17,7 +17,7 @@ import { useArrowNavigationGroup } from '@fluentui/react-tabster';
|
|
|
17
17
|
const { main, iconAfter, iconBefore } = props;
|
|
18
18
|
const layoutRef = useTreeItemContext_unstable((ctx)=>ctx.layoutRef);
|
|
19
19
|
const selectionMode = useTreeContext_unstable((ctx)=>ctx.selectionMode);
|
|
20
|
-
const [
|
|
20
|
+
const [isActionsVisibleFromProps, actionsShorthand] = isResolvedShorthand(props.actions) ? [
|
|
21
21
|
props.actions.visible,
|
|
22
22
|
{
|
|
23
23
|
...props.actions,
|
|
@@ -27,13 +27,46 @@ import { useArrowNavigationGroup } from '@fluentui/react-tabster';
|
|
|
27
27
|
undefined,
|
|
28
28
|
props.actions
|
|
29
29
|
];
|
|
30
|
-
const isActionsVisible =
|
|
31
|
-
|
|
30
|
+
const [isActionsVisible, setIsActionsVisible] = useControllableState({
|
|
31
|
+
state: isActionsVisibleFromProps,
|
|
32
|
+
initialState: false
|
|
33
|
+
});
|
|
32
34
|
const selectionRef = useTreeItemContext_unstable((ctx)=>ctx.selectionRef);
|
|
33
35
|
const expandIconRef = useTreeItemContext_unstable((ctx)=>ctx.expandIconRef);
|
|
34
36
|
const actionsRef = useTreeItemContext_unstable((ctx)=>ctx.actionsRef);
|
|
37
|
+
const actionsRefInternal = React.useRef(null);
|
|
38
|
+
const treeItemRef = useTreeItemContext_unstable((ctx)=>ctx.treeItemRef);
|
|
39
|
+
const subtreeRef = useTreeItemContext_unstable((ctx)=>ctx.subtreeRef);
|
|
35
40
|
const checked = useTreeItemContext_unstable((ctx)=>ctx.checked);
|
|
36
41
|
const isBranch = useTreeItemContext_unstable((ctx)=>ctx.itemType === 'branch');
|
|
42
|
+
// FIXME: Asserting is required here, as converting this to RefObject on context type would be a breaking change
|
|
43
|
+
assertIsRefObject(treeItemRef);
|
|
44
|
+
// FIXME: Asserting is required here, as converting this to RefObject on context type would be a breaking change
|
|
45
|
+
assertIsRefObject(subtreeRef);
|
|
46
|
+
const setActionsVisibleIfNotFromSubtree = React.useCallback((event)=>{
|
|
47
|
+
const isTargetFromSubtree = Boolean(subtreeRef.current && elementContains(subtreeRef.current, event.target));
|
|
48
|
+
if (!isTargetFromSubtree) {
|
|
49
|
+
setIsActionsVisible(true);
|
|
50
|
+
}
|
|
51
|
+
}, [
|
|
52
|
+
subtreeRef,
|
|
53
|
+
setIsActionsVisible
|
|
54
|
+
]);
|
|
55
|
+
const setActionsInvisibleIfNotFromSubtree = React.useCallback((event)=>{
|
|
56
|
+
const isRelatedTargetFromActions = Boolean(actionsRefInternal.current && elementContains(actionsRefInternal.current, event.relatedTarget));
|
|
57
|
+
if (isRelatedTargetFromActions) {
|
|
58
|
+
setIsActionsVisible(true);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const isTargetFromSubtree = Boolean(subtreeRef.current && elementContains(subtreeRef.current, event.target));
|
|
62
|
+
if (!isTargetFromSubtree) {
|
|
63
|
+
setIsActionsVisible(false);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
}, [
|
|
67
|
+
subtreeRef,
|
|
68
|
+
setIsActionsVisible
|
|
69
|
+
]);
|
|
37
70
|
const expandIcon = slot.optional(props.expandIcon, {
|
|
38
71
|
renderByDefault: isBranch,
|
|
39
72
|
defaultProps: {
|
|
@@ -57,10 +90,45 @@ import { useArrowNavigationGroup } from '@fluentui/react-tabster';
|
|
|
57
90
|
},
|
|
58
91
|
elementType: 'div'
|
|
59
92
|
}) : undefined;
|
|
60
|
-
const actionsRefs = useMergedRefs(actions === null || actions === void 0 ? void 0 : actions.ref, actionsRef);
|
|
93
|
+
const actionsRefs = useMergedRefs(actions === null || actions === void 0 ? void 0 : actions.ref, actionsRef, actionsRefInternal);
|
|
94
|
+
const handleActionsBlur = useEventCallback((event)=>{
|
|
95
|
+
if (isResolvedShorthand(actionsShorthand)) {
|
|
96
|
+
var _actionsShorthand_onBlur;
|
|
97
|
+
(_actionsShorthand_onBlur = actionsShorthand.onBlur) === null || _actionsShorthand_onBlur === void 0 ? void 0 : _actionsShorthand_onBlur.call(actionsShorthand, event);
|
|
98
|
+
}
|
|
99
|
+
const isRelatedTargetFromActions = Boolean(elementContains(event.currentTarget, event.relatedTarget));
|
|
100
|
+
setIsActionsVisible(isRelatedTargetFromActions);
|
|
101
|
+
});
|
|
61
102
|
if (actions) {
|
|
62
103
|
actions.ref = actionsRefs;
|
|
104
|
+
actions.onBlur = handleActionsBlur;
|
|
63
105
|
}
|
|
106
|
+
const hasActions = Boolean(actionsShorthand);
|
|
107
|
+
React.useEffect(()=>{
|
|
108
|
+
if (treeItemRef.current && hasActions && isActionsVisibleFromProps === undefined) {
|
|
109
|
+
const treeItemElement = treeItemRef.current;
|
|
110
|
+
const handleMouseOver = setActionsVisibleIfNotFromSubtree;
|
|
111
|
+
const handleMouseOut = setActionsInvisibleIfNotFromSubtree;
|
|
112
|
+
const handleFocus = setActionsVisibleIfNotFromSubtree;
|
|
113
|
+
const handleBlur = setActionsInvisibleIfNotFromSubtree;
|
|
114
|
+
treeItemElement.addEventListener('mouseover', handleMouseOver);
|
|
115
|
+
treeItemElement.addEventListener('mouseout', handleMouseOut);
|
|
116
|
+
treeItemElement.addEventListener('focus', handleFocus);
|
|
117
|
+
treeItemElement.addEventListener('blur', handleBlur);
|
|
118
|
+
return ()=>{
|
|
119
|
+
treeItemElement.removeEventListener('mouseover', handleMouseOver);
|
|
120
|
+
treeItemElement.removeEventListener('mouseout', handleMouseOut);
|
|
121
|
+
treeItemElement.removeEventListener('focus', handleFocus);
|
|
122
|
+
treeItemElement.removeEventListener('blur', handleBlur);
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}, [
|
|
126
|
+
hasActions,
|
|
127
|
+
treeItemRef,
|
|
128
|
+
isActionsVisibleFromProps,
|
|
129
|
+
setActionsVisibleIfNotFromSubtree,
|
|
130
|
+
setActionsInvisibleIfNotFromSubtree
|
|
131
|
+
]);
|
|
64
132
|
return {
|
|
65
133
|
components: {
|
|
66
134
|
root: 'div',
|
|
@@ -100,7 +168,7 @@ import { useArrowNavigationGroup } from '@fluentui/react-tabster';
|
|
|
100
168
|
},
|
|
101
169
|
elementType: 'div'
|
|
102
170
|
}),
|
|
103
|
-
aside:
|
|
171
|
+
aside: !isActionsVisible ? slot.optional(props.aside, {
|
|
104
172
|
defaultProps: {
|
|
105
173
|
'aria-hidden': true
|
|
106
174
|
},
|
|
@@ -120,3 +188,13 @@ import { useArrowNavigationGroup } from '@fluentui/react-tabster';
|
|
|
120
188
|
})
|
|
121
189
|
};
|
|
122
190
|
};
|
|
191
|
+
function assertIsRefObject(ref) {
|
|
192
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
193
|
+
if (typeof ref !== 'object' || ref === null || !('current' in ref)) {
|
|
194
|
+
throw new Error(`
|
|
195
|
+
@fluentui/react-tree [${useTreeItemLayout_unstable.name}]:
|
|
196
|
+
Internal Error: contextual ref is not a RefObject! Please report this bug immediately, as contextual refs should be RefObjects.
|
|
197
|
+
`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|