@fluentui/react-tree 9.0.0-beta.24 → 9.0.0-beta.26

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.
Files changed (109) hide show
  1. package/CHANGELOG.json +118 -1
  2. package/CHANGELOG.md +32 -2
  3. package/dist/index.d.ts +192 -52
  4. package/lib/components/Tree/Tree.types.js +1 -1
  5. package/lib/components/Tree/Tree.types.js.map +1 -1
  6. package/lib/components/Tree/useRootTree.js +71 -73
  7. package/lib/components/Tree/useRootTree.js.map +1 -1
  8. package/lib/components/Tree/useSubtree.js +4 -0
  9. package/lib/components/Tree/useSubtree.js.map +1 -1
  10. package/lib/components/Tree/useTreeContextValues.js +4 -2
  11. package/lib/components/Tree/useTreeContextValues.js.map +1 -1
  12. package/lib/components/TreeItem/TreeItem.types.js.map +1 -1
  13. package/lib/components/TreeItem/renderTreeItem.js +4 -2
  14. package/lib/components/TreeItem/renderTreeItem.js.map +1 -1
  15. package/lib/components/TreeItem/useTreeItem.js +104 -18
  16. package/lib/components/TreeItem/useTreeItem.js.map +1 -1
  17. package/lib/components/TreeItem/useTreeItemContextValues.js +15 -6
  18. package/lib/components/TreeItem/useTreeItemContextValues.js.map +1 -1
  19. package/lib/components/TreeItemLayout/TreeItemLayout.types.js.map +1 -1
  20. package/lib/components/TreeItemLayout/renderTreeItemLayout.js +1 -1
  21. package/lib/components/TreeItemLayout/renderTreeItemLayout.js.map +1 -1
  22. package/lib/components/TreeItemLayout/useTreeItemLayout.js +14 -30
  23. package/lib/components/TreeItemLayout/useTreeItemLayout.js.map +1 -1
  24. package/lib/components/TreeItemLayout/useTreeItemLayoutStyles.styles.js +15 -8
  25. package/lib/components/TreeItemLayout/useTreeItemLayoutStyles.styles.js.map +1 -1
  26. package/lib/components/TreeItemPersonaLayout/TreeItemPersonaLayout.types.js.map +1 -1
  27. package/lib/components/TreeItemPersonaLayout/renderTreeItemPersonaLayout.js.map +1 -1
  28. package/lib/components/TreeItemPersonaLayout/useTreeItemPersonaLayout.js.map +1 -1
  29. package/lib/contexts/index.js +1 -0
  30. package/lib/contexts/index.js.map +1 -1
  31. package/lib/contexts/treeContext.js +5 -2
  32. package/lib/contexts/treeContext.js.map +1 -1
  33. package/lib/contexts/treeItemContext.js +0 -4
  34. package/lib/contexts/treeItemContext.js.map +1 -1
  35. package/lib/contexts/treeItemSlotsContext.js +9 -0
  36. package/lib/contexts/treeItemSlotsContext.js.map +1 -0
  37. package/lib/hooks/index.js +3 -1
  38. package/lib/hooks/index.js.map +1 -1
  39. package/lib/hooks/useControllableOpenItems.js +25 -0
  40. package/lib/hooks/useControllableOpenItems.js.map +1 -0
  41. package/lib/hooks/useFlatControllableCheckedItems.js +76 -0
  42. package/lib/hooks/useFlatControllableCheckedItems.js.map +1 -0
  43. package/lib/hooks/useFlatTree.js +17 -6
  44. package/lib/hooks/useFlatTree.js.map +1 -1
  45. package/lib/hooks/useNestedControllableCheckedItems.js +107 -0
  46. package/lib/hooks/useNestedControllableCheckedItems.js.map +1 -0
  47. package/lib/index.js.map +1 -1
  48. package/lib/utils/ImmutableMap.js +37 -0
  49. package/lib/utils/ImmutableMap.js.map +1 -0
  50. package/lib/utils/ImmutableSet.js +17 -9
  51. package/lib/utils/ImmutableSet.js.map +1 -1
  52. package/lib/utils/createFlatTreeItems.js +60 -8
  53. package/lib/utils/createFlatTreeItems.js.map +1 -1
  54. package/lib/utils/flattenTree.js +0 -5
  55. package/lib/utils/flattenTree.js.map +1 -1
  56. package/lib/utils/tokens.js +2 -1
  57. package/lib/utils/tokens.js.map +1 -1
  58. package/lib-commonjs/components/Tree/Tree.types.js +0 -2
  59. package/lib-commonjs/components/Tree/Tree.types.js.map +1 -1
  60. package/lib-commonjs/components/Tree/useRootTree.js +70 -72
  61. package/lib-commonjs/components/Tree/useRootTree.js.map +1 -1
  62. package/lib-commonjs/components/Tree/useSubtree.js +4 -0
  63. package/lib-commonjs/components/Tree/useSubtree.js.map +1 -1
  64. package/lib-commonjs/components/Tree/useTreeContextValues.js +4 -2
  65. package/lib-commonjs/components/Tree/useTreeContextValues.js.map +1 -1
  66. package/lib-commonjs/components/TreeItem/renderTreeItem.js +3 -1
  67. package/lib-commonjs/components/TreeItem/renderTreeItem.js.map +1 -1
  68. package/lib-commonjs/components/TreeItem/useTreeItem.js +103 -17
  69. package/lib-commonjs/components/TreeItem/useTreeItem.js.map +1 -1
  70. package/lib-commonjs/components/TreeItem/useTreeItemContextValues.js +16 -6
  71. package/lib-commonjs/components/TreeItem/useTreeItemContextValues.js.map +1 -1
  72. package/lib-commonjs/components/TreeItemLayout/renderTreeItemLayout.js +1 -1
  73. package/lib-commonjs/components/TreeItemLayout/renderTreeItemLayout.js.map +1 -1
  74. package/lib-commonjs/components/TreeItemLayout/useTreeItemLayout.js +14 -29
  75. package/lib-commonjs/components/TreeItemLayout/useTreeItemLayout.js.map +1 -1
  76. package/lib-commonjs/components/TreeItemLayout/useTreeItemLayoutStyles.styles.js +12 -8
  77. package/lib-commonjs/components/TreeItemLayout/useTreeItemLayoutStyles.styles.js.map +1 -1
  78. package/lib-commonjs/contexts/index.js +1 -0
  79. package/lib-commonjs/contexts/index.js.map +1 -1
  80. package/lib-commonjs/contexts/treeContext.js +4 -1
  81. package/lib-commonjs/contexts/treeContext.js.map +1 -1
  82. package/lib-commonjs/contexts/treeItemContext.js +0 -4
  83. package/lib-commonjs/contexts/treeItemContext.js.map +1 -1
  84. package/lib-commonjs/contexts/treeItemSlotsContext.js +25 -0
  85. package/lib-commonjs/contexts/treeItemSlotsContext.js.map +1 -0
  86. package/lib-commonjs/hooks/index.js +3 -1
  87. package/lib-commonjs/hooks/index.js.map +1 -1
  88. package/lib-commonjs/hooks/{useOpenItemsState.js → useControllableOpenItems.js} +15 -14
  89. package/lib-commonjs/hooks/useControllableOpenItems.js.map +1 -0
  90. package/lib-commonjs/hooks/useFlatControllableCheckedItems.js +91 -0
  91. package/lib-commonjs/hooks/useFlatControllableCheckedItems.js.map +1 -0
  92. package/lib-commonjs/hooks/useFlatTree.js +16 -5
  93. package/lib-commonjs/hooks/useFlatTree.js.map +1 -1
  94. package/lib-commonjs/hooks/useNestedControllableCheckedItems.js +116 -0
  95. package/lib-commonjs/hooks/useNestedControllableCheckedItems.js.map +1 -0
  96. package/lib-commonjs/utils/ImmutableMap.js +45 -0
  97. package/lib-commonjs/utils/ImmutableMap.js.map +1 -0
  98. package/lib-commonjs/utils/ImmutableSet.js +22 -16
  99. package/lib-commonjs/utils/ImmutableSet.js.map +1 -1
  100. package/lib-commonjs/utils/createFlatTreeItems.js +60 -8
  101. package/lib-commonjs/utils/createFlatTreeItems.js.map +1 -1
  102. package/lib-commonjs/utils/flattenTree.js +0 -5
  103. package/lib-commonjs/utils/flattenTree.js.map +1 -1
  104. package/lib-commonjs/utils/tokens.js +2 -1
  105. package/lib-commonjs/utils/tokens.js.map +1 -1
  106. package/package.json +9 -7
  107. package/lib/hooks/useOpenItemsState.js +0 -28
  108. package/lib/hooks/useOpenItemsState.js.map +0 -1
  109. package/lib-commonjs/hooks/useOpenItemsState.js.map +0 -1
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import * as ReactDOM from 'react-dom';
3
3
  import { getNativeElementProps, useEventCallback, useMergedRefs } from '@fluentui/react-utilities';
4
- import { useNestedTreeNavigation, useOpenItemsState } from '../../hooks';
4
+ import { useControllableOpenItems, useNestedTreeNavigation, useNestedControllableCheckedItems, createNextOpenItems } from '../../hooks';
5
5
  import { treeDataTypes } from '../../utils/tokens';
6
6
  /**
7
7
  * Create the state required to render the root level Tree.
@@ -10,8 +10,9 @@ import { treeDataTypes } from '../../utils/tokens';
10
10
  * @param ref - reference to root HTMLElement of Tree
11
11
  */ export function useRootTree(props, ref) {
12
12
  warnIfNoProperPropsRootTree(props);
13
- const { appearance ='subtle' , size ='medium' } = props;
14
- const [openItems, updateOpenItems] = useOpenItemsState(props);
13
+ const { appearance ='subtle' , size ='medium' , selectionMode ='none' } = props;
14
+ const [openItems, setOpenItems] = useControllableOpenItems(props);
15
+ const [checkedItems] = useNestedControllableCheckedItems(props);
15
16
  const [navigate, navigationRef] = useNestedTreeNavigation();
16
17
  const requestOpenChange = (data)=>{
17
18
  var _props_onOpenChange;
@@ -19,7 +20,14 @@ import { treeDataTypes } from '../../utils/tokens';
19
20
  if (data.event.isDefaultPrevented()) {
20
21
  return;
21
22
  }
22
- return updateOpenItems(data);
23
+ return setOpenItems(createNextOpenItems(data, openItems));
24
+ };
25
+ const requestCheckedChange = (data)=>{
26
+ var _props_onCheckedChange;
27
+ (_props_onCheckedChange = props.onCheckedChange) === null || _props_onCheckedChange === void 0 ? void 0 : _props_onCheckedChange.call(props, data.event, data);
28
+ // TODO:
29
+ // we should implement the logic for nested tree selection
30
+ // return setCheckedItems(checkedItems);
23
31
  };
24
32
  const requestNavigation = (data)=>{
25
33
  var _props_onNavigation_unstable;
@@ -32,105 +40,95 @@ import { treeDataTypes } from '../../utils/tokens';
32
40
  data.event.preventDefault();
33
41
  }
34
42
  };
35
- const handleTreeItemClick = ({ event , value , itemType , type })=>{
36
- ReactDOM.unstable_batchedUpdates(()=>{
37
- requestOpenChange({
38
- event,
39
- value,
40
- open: itemType === 'branch' && !openItems.has(value),
41
- type,
42
- target: event.currentTarget
43
- });
44
- requestNavigation({
45
- event,
46
- value,
47
- target: event.currentTarget,
48
- type: treeDataTypes.Click
49
- });
50
- });
51
- };
52
- const handleTreeItemKeyDown = ({ event , type , value , itemType })=>{
53
- const open = openItems.has(value);
54
- switch(type){
43
+ const requestTreeResponse = useEventCallback((request)=>{
44
+ switch(request.type){
45
+ case treeDataTypes.Click:
46
+ case treeDataTypes.ExpandIconClick:
47
+ {
48
+ return ReactDOM.unstable_batchedUpdates(()=>{
49
+ requestOpenChange({
50
+ ...request,
51
+ open: request.itemType === 'branch' && !openItems.has(request.value)
52
+ });
53
+ requestNavigation({
54
+ ...request,
55
+ type: treeDataTypes.Click
56
+ });
57
+ });
58
+ }
55
59
  case treeDataTypes.ArrowRight:
56
- if (itemType === 'leaf') {
57
- return;
60
+ {
61
+ if (request.itemType === 'leaf') {
62
+ return;
63
+ }
64
+ const open = openItems.has(request.value);
65
+ if (!open) {
66
+ return requestOpenChange({
67
+ ...request,
68
+ open: true
69
+ });
70
+ }
71
+ return requestNavigation(request);
58
72
  }
59
- if (!open) {
73
+ case treeDataTypes.Enter:
74
+ {
75
+ const open = openItems.has(request.value);
60
76
  return requestOpenChange({
61
- event,
62
- value,
63
- open: true,
64
- type: treeDataTypes.ArrowRight,
65
- target: event.currentTarget
77
+ ...request,
78
+ open: request.itemType === 'branch' && !open
66
79
  });
67
80
  }
68
- return requestNavigation({
69
- event,
70
- value,
71
- type,
72
- target: event.currentTarget
73
- });
74
- case treeDataTypes.Enter:
75
- return requestOpenChange({
76
- event,
77
- value,
78
- open: itemType === 'branch' && !open,
79
- type: treeDataTypes.Enter,
80
- target: event.currentTarget
81
- });
82
81
  case treeDataTypes.ArrowLeft:
83
- if (open && itemType === 'branch') {
84
- return requestOpenChange({
85
- event,
86
- value,
87
- open: false,
88
- type: treeDataTypes.ArrowLeft,
89
- target: event.currentTarget
82
+ {
83
+ const open = openItems.has(request.value);
84
+ if (open && request.itemType === 'branch') {
85
+ return requestOpenChange({
86
+ ...request,
87
+ open: false,
88
+ type: treeDataTypes.ArrowLeft
89
+ });
90
+ }
91
+ return requestNavigation({
92
+ ...request,
93
+ type: treeDataTypes.ArrowLeft
90
94
  });
91
95
  }
92
- return requestNavigation({
93
- event,
94
- value,
95
- target: event.currentTarget,
96
- type: treeDataTypes.ArrowLeft
97
- });
98
96
  case treeDataTypes.End:
99
97
  case treeDataTypes.Home:
100
98
  case treeDataTypes.ArrowUp:
101
99
  case treeDataTypes.ArrowDown:
102
100
  case treeDataTypes.TypeAhead:
103
101
  return requestNavigation({
104
- event,
105
- value,
106
- type,
107
- target: event.currentTarget
102
+ ...request,
103
+ target: request.event.currentTarget
108
104
  });
109
- }
110
- };
111
- const requestTreeResponse = useEventCallback((request)=>{
112
- switch(request.event.type){
113
- case 'click':
114
- // casting is required here as we're narrowing down the event to only click events
115
- return handleTreeItemClick(request);
116
- case 'keydown':
117
- // casting is required here as we're narrowing down the event to only keyboard events
118
- return handleTreeItemKeyDown(request);
105
+ case treeDataTypes.Change:
106
+ {
107
+ const previousCheckedValue = checkedItems.get(request.value);
108
+ return requestCheckedChange({
109
+ ...request,
110
+ selectionMode: selectionMode,
111
+ checked: previousCheckedValue === 'mixed' ? true : !previousCheckedValue
112
+ });
113
+ }
119
114
  }
120
115
  });
121
116
  return {
122
117
  components: {
123
118
  root: 'div'
124
119
  },
120
+ selectionMode,
125
121
  open: true,
126
122
  appearance,
127
123
  size,
128
124
  level: 1,
129
125
  openItems,
126
+ checkedItems,
130
127
  requestTreeResponse,
131
128
  root: getNativeElementProps('div', {
132
129
  ref: useMergedRefs(navigationRef, ref),
133
130
  role: 'tree',
131
+ 'aria-multiselectable': selectionMode === 'multiselect' ? true : undefined,
134
132
  ...props
135
133
  })
136
134
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["useRootTree.ts"],"sourcesContent":["import * as React from 'react';\nimport * as ReactDOM from 'react-dom';\nimport { getNativeElementProps, useEventCallback, useMergedRefs } from '@fluentui/react-utilities';\nimport { TreeOpenChangeData, TreeProps, TreeState, TreeNavigationData_unstable } from './Tree.types';\nimport { useNestedTreeNavigation, useOpenItemsState } from '../../hooks';\nimport { treeDataTypes } from '../../utils/tokens';\nimport { TreeItemRequest } from '../../contexts/index';\n\n/**\n * Create the state required to render the root level Tree.\n *\n * @param props - props from this instance of Tree\n * @param ref - reference to root HTMLElement of Tree\n */\nexport function useRootTree(props: TreeProps, ref: React.Ref<HTMLElement>): TreeState {\n warnIfNoProperPropsRootTree(props);\n\n const { appearance = 'subtle', size = 'medium' } = props;\n\n const [openItems, updateOpenItems] = useOpenItemsState(props);\n const [navigate, navigationRef] = useNestedTreeNavigation();\n\n const requestOpenChange = (data: TreeOpenChangeData) => {\n props.onOpenChange?.(data.event, data);\n if (data.event.isDefaultPrevented()) {\n return;\n }\n return updateOpenItems(data);\n };\n\n const requestNavigation = (data: TreeNavigationData_unstable) => {\n props.onNavigation_unstable?.(data.event, data);\n if (data.event.isDefaultPrevented()) {\n return;\n }\n navigate(data);\n if (data.type === treeDataTypes.ArrowDown || data.type === treeDataTypes.ArrowUp) {\n data.event.preventDefault();\n }\n };\n\n const handleTreeItemClick = ({\n event,\n value,\n itemType,\n type,\n }: Extract<TreeItemRequest, { type: 'Click' | 'ExpandIconClick' }>) => {\n ReactDOM.unstable_batchedUpdates(() => {\n requestOpenChange({\n event,\n value,\n open: itemType === 'branch' && !openItems.has(value),\n type,\n target: event.currentTarget,\n });\n requestNavigation({ event, value, target: event.currentTarget, type: treeDataTypes.Click });\n });\n };\n\n const handleTreeItemKeyDown = ({\n event,\n type,\n value,\n itemType,\n }: Exclude<TreeItemRequest, { type: 'Click' | 'ExpandIconClick' }>) => {\n const open = openItems.has(value);\n switch (type) {\n case treeDataTypes.ArrowRight:\n if (itemType === 'leaf') {\n return;\n }\n if (!open) {\n return requestOpenChange({\n event,\n value,\n open: true,\n type: treeDataTypes.ArrowRight,\n target: event.currentTarget,\n });\n }\n return requestNavigation({ event, value, type, target: event.currentTarget });\n case treeDataTypes.Enter:\n return requestOpenChange({\n event,\n value,\n open: itemType === 'branch' && !open,\n type: treeDataTypes.Enter,\n target: event.currentTarget,\n });\n case treeDataTypes.ArrowLeft:\n if (open && itemType === 'branch') {\n return requestOpenChange({\n event,\n value,\n open: false,\n type: treeDataTypes.ArrowLeft,\n target: event.currentTarget,\n });\n }\n return requestNavigation({ event, value, target: event.currentTarget, type: treeDataTypes.ArrowLeft });\n case treeDataTypes.End:\n case treeDataTypes.Home:\n case treeDataTypes.ArrowUp:\n case treeDataTypes.ArrowDown:\n case treeDataTypes.TypeAhead:\n return requestNavigation({ event, value, type, target: event.currentTarget });\n }\n };\n\n const requestTreeResponse = useEventCallback((request: TreeItemRequest) => {\n switch (request.event.type) {\n case 'click':\n // casting is required here as we're narrowing down the event to only click events\n return handleTreeItemClick(request as Extract<TreeItemRequest, { type: 'Click' | 'ExpandIconClick' }>);\n case 'keydown':\n // casting is required here as we're narrowing down the event to only keyboard events\n return handleTreeItemKeyDown(request as Exclude<TreeItemRequest, { type: 'Click' | 'ExpandIconClick' }>);\n }\n });\n\n return {\n components: {\n root: 'div',\n },\n open: true,\n appearance,\n size,\n level: 1,\n openItems,\n requestTreeResponse,\n root: getNativeElementProps('div', {\n ref: useMergedRefs(navigationRef, ref),\n role: 'tree',\n ...props,\n }),\n };\n}\n\nfunction warnIfNoProperPropsRootTree(props: Pick<TreeProps, 'aria-label' | 'aria-labelledby'>) {\n if (process.env.NODE_ENV === 'development') {\n if (!props['aria-label'] && !props['aria-labelledby']) {\n // eslint-disable-next-line no-console\n console.warn('Tree must have either a `aria-label` or `aria-labelledby` property defined');\n }\n }\n}\n"],"names":["React","ReactDOM","getNativeElementProps","useEventCallback","useMergedRefs","useNestedTreeNavigation","useOpenItemsState","treeDataTypes","useRootTree","props","ref","warnIfNoProperPropsRootTree","appearance","size","openItems","updateOpenItems","navigate","navigationRef","requestOpenChange","data","onOpenChange","event","isDefaultPrevented","requestNavigation","onNavigation_unstable","type","ArrowDown","ArrowUp","preventDefault","handleTreeItemClick","value","itemType","unstable_batchedUpdates","open","has","target","currentTarget","Click","handleTreeItemKeyDown","ArrowRight","Enter","ArrowLeft","End","Home","TypeAhead","requestTreeResponse","request","components","root","level","role","process","env","NODE_ENV","console","warn"],"mappings":"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"}
1
+ {"version":3,"sources":["useRootTree.ts"],"sourcesContent":["import * as React from 'react';\nimport * as ReactDOM from 'react-dom';\nimport { SelectionMode, getNativeElementProps, useEventCallback, useMergedRefs } from '@fluentui/react-utilities';\nimport {\n TreeOpenChangeData,\n TreeProps,\n TreeState,\n TreeNavigationData_unstable,\n TreeCheckedChangeData,\n} from './Tree.types';\nimport {\n useControllableOpenItems,\n useNestedTreeNavigation,\n useNestedControllableCheckedItems,\n createNextOpenItems,\n} from '../../hooks';\nimport { treeDataTypes } from '../../utils/tokens';\nimport { TreeItemRequest } from '../../contexts';\n\n/**\n * Create the state required to render the root level Tree.\n *\n * @param props - props from this instance of Tree\n * @param ref - reference to root HTMLElement of Tree\n */\nexport function useRootTree(props: TreeProps, ref: React.Ref<HTMLElement>): TreeState {\n warnIfNoProperPropsRootTree(props);\n\n const { appearance = 'subtle', size = 'medium', selectionMode = 'none' } = props;\n\n const [openItems, setOpenItems] = useControllableOpenItems(props);\n\n const [checkedItems] = useNestedControllableCheckedItems(props);\n const [navigate, navigationRef] = useNestedTreeNavigation();\n\n const requestOpenChange = (data: TreeOpenChangeData) => {\n props.onOpenChange?.(data.event, data);\n if (data.event.isDefaultPrevented()) {\n return;\n }\n return setOpenItems(createNextOpenItems(data, openItems));\n };\n\n const requestCheckedChange = (data: TreeCheckedChangeData) => {\n props.onCheckedChange?.(data.event, data);\n // TODO:\n // we should implement the logic for nested tree selection\n // return setCheckedItems(checkedItems);\n };\n\n const requestNavigation = (data: TreeNavigationData_unstable) => {\n props.onNavigation_unstable?.(data.event, data);\n if (data.event.isDefaultPrevented()) {\n return;\n }\n navigate(data);\n if (data.type === treeDataTypes.ArrowDown || data.type === treeDataTypes.ArrowUp) {\n data.event.preventDefault();\n }\n };\n\n const requestTreeResponse = useEventCallback((request: TreeItemRequest) => {\n switch (request.type) {\n case treeDataTypes.Click:\n case treeDataTypes.ExpandIconClick: {\n return ReactDOM.unstable_batchedUpdates(() => {\n requestOpenChange({ ...request, open: request.itemType === 'branch' && !openItems.has(request.value) });\n requestNavigation({ ...request, type: treeDataTypes.Click });\n });\n }\n case treeDataTypes.ArrowRight: {\n if (request.itemType === 'leaf') {\n return;\n }\n const open = openItems.has(request.value);\n if (!open) {\n return requestOpenChange({ ...request, open: true });\n }\n return requestNavigation(request);\n }\n case treeDataTypes.Enter: {\n const open = openItems.has(request.value);\n return requestOpenChange({ ...request, open: request.itemType === 'branch' && !open });\n }\n case treeDataTypes.ArrowLeft: {\n const open = openItems.has(request.value);\n if (open && request.itemType === 'branch') {\n return requestOpenChange({ ...request, open: false, type: treeDataTypes.ArrowLeft });\n }\n return requestNavigation({ ...request, type: treeDataTypes.ArrowLeft });\n }\n case treeDataTypes.End:\n case treeDataTypes.Home:\n case treeDataTypes.ArrowUp:\n case treeDataTypes.ArrowDown:\n case treeDataTypes.TypeAhead:\n return requestNavigation({ ...request, target: request.event.currentTarget });\n case treeDataTypes.Change: {\n const previousCheckedValue = checkedItems.get(request.value);\n return requestCheckedChange({\n ...request,\n selectionMode: selectionMode as SelectionMode,\n checked: previousCheckedValue === 'mixed' ? true : !previousCheckedValue,\n });\n }\n }\n });\n\n return {\n components: {\n root: 'div',\n },\n selectionMode,\n open: true,\n appearance,\n size,\n level: 1,\n openItems,\n checkedItems,\n requestTreeResponse,\n root: getNativeElementProps('div', {\n ref: useMergedRefs(navigationRef, ref),\n role: 'tree',\n 'aria-multiselectable': selectionMode === 'multiselect' ? true : undefined,\n ...props,\n }),\n };\n}\n\nfunction warnIfNoProperPropsRootTree(props: Pick<TreeProps, 'aria-label' | 'aria-labelledby'>) {\n if (process.env.NODE_ENV === 'development') {\n if (!props['aria-label'] && !props['aria-labelledby']) {\n // eslint-disable-next-line no-console\n console.warn('Tree must have either a `aria-label` or `aria-labelledby` property defined');\n }\n }\n}\n"],"names":["React","ReactDOM","getNativeElementProps","useEventCallback","useMergedRefs","useControllableOpenItems","useNestedTreeNavigation","useNestedControllableCheckedItems","createNextOpenItems","treeDataTypes","useRootTree","props","ref","warnIfNoProperPropsRootTree","appearance","size","selectionMode","openItems","setOpenItems","checkedItems","navigate","navigationRef","requestOpenChange","data","onOpenChange","event","isDefaultPrevented","requestCheckedChange","onCheckedChange","requestNavigation","onNavigation_unstable","type","ArrowDown","ArrowUp","preventDefault","requestTreeResponse","request","Click","ExpandIconClick","unstable_batchedUpdates","open","itemType","has","value","ArrowRight","Enter","ArrowLeft","End","Home","TypeAhead","target","currentTarget","Change","previousCheckedValue","get","checked","components","root","level","role","undefined","process","env","NODE_ENV","console","warn"],"mappings":"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"}
@@ -13,7 +13,9 @@ import { useTreeContext_unstable, useTreeItemContext_unstable } from '../../cont
13
13
  const value = useTreeItemContext_unstable((ctx)=>ctx.value);
14
14
  const { appearance =contextAppearance !== null && contextAppearance !== void 0 ? contextAppearance : 'subtle' , size =contextSize !== null && contextSize !== void 0 ? contextSize : 'medium' } = props;
15
15
  const parentLevel = useTreeContext_unstable((ctx)=>ctx.level);
16
+ const selectionMode = useTreeContext_unstable((ctx)=>ctx.selectionMode);
16
17
  const openItems = useTreeContext_unstable((ctx)=>ctx.openItems);
18
+ const checkedItems = useTreeContext_unstable((ctx)=>ctx.checkedItems);
17
19
  const requestTreeResponse = useTreeContext_unstable((ctx)=>ctx.requestTreeResponse);
18
20
  const open = openItems.has(value);
19
21
  return {
@@ -23,6 +25,7 @@ import { useTreeContext_unstable, useTreeItemContext_unstable } from '../../cont
23
25
  },
24
26
  appearance,
25
27
  size,
28
+ selectionMode,
26
29
  level: parentLevel + 1,
27
30
  root: getNativeElementProps('div', {
28
31
  ref: useMergedRefs(ref, subtreeRef),
@@ -30,6 +33,7 @@ import { useTreeContext_unstable, useTreeItemContext_unstable } from '../../cont
30
33
  ...props
31
34
  }),
32
35
  openItems,
36
+ checkedItems,
33
37
  requestTreeResponse
34
38
  };
35
39
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["useSubtree.ts"],"sourcesContent":["import * as React from 'react';\nimport { getNativeElementProps, useMergedRefs } from '@fluentui/react-utilities';\nimport { TreeProps, TreeState } from './Tree.types';\nimport { useTreeContext_unstable, useTreeItemContext_unstable } from '../../contexts';\n\n/**\n * Create the state required to render a sub-level Tree.\n *\n * @param props - props from this instance of Tree\n * @param ref - reference to root HTMLElement of Tree\n */\nexport function useSubtree(props: TreeProps, ref: React.Ref<HTMLElement>): TreeState {\n const contextAppearance = useTreeContext_unstable(ctx => ctx.appearance);\n const contextSize = useTreeContext_unstable(ctx => ctx.size);\n const subtreeRef = useTreeItemContext_unstable(ctx => ctx.subtreeRef);\n const value = useTreeItemContext_unstable(ctx => ctx.value);\n\n const { appearance = contextAppearance ?? 'subtle', size = contextSize ?? 'medium' } = props;\n\n const parentLevel = useTreeContext_unstable(ctx => ctx.level);\n const openItems = useTreeContext_unstable(ctx => ctx.openItems);\n const requestTreeResponse = useTreeContext_unstable(ctx => ctx.requestTreeResponse);\n\n const open = openItems.has(value);\n\n return {\n open,\n components: {\n root: 'div',\n },\n appearance,\n size,\n level: parentLevel + 1,\n root: getNativeElementProps('div', {\n ref: useMergedRefs(ref, subtreeRef),\n role: 'group',\n ...props,\n }),\n openItems,\n requestTreeResponse,\n };\n}\n"],"names":["React","getNativeElementProps","useMergedRefs","useTreeContext_unstable","useTreeItemContext_unstable","useSubtree","props","ref","contextAppearance","ctx","appearance","contextSize","size","subtreeRef","value","parentLevel","level","openItems","requestTreeResponse","open","has","components","root","role"],"mappings":"AAAA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,qBAAqB,EAAEC,aAAa,QAAQ,4BAA4B;AAEjF,SAASC,uBAAuB,EAAEC,2BAA2B,QAAQ,iBAAiB;AAEtF;;;;;CAKC,GACD,OAAO,SAASC,WAAWC,KAAgB,EAAEC,GAA2B,EAAa;IACnF,MAAMC,oBAAoBL,wBAAwBM,CAAAA,MAAOA,IAAIC,UAAU;IACvE,MAAMC,cAAcR,wBAAwBM,CAAAA,MAAOA,IAAIG,IAAI;IAC3D,MAAMC,aAAaT,4BAA4BK,CAAAA,MAAOA,IAAII,UAAU;IACpE,MAAMC,QAAQV,4BAA4BK,CAAAA,MAAOA,IAAIK,KAAK;IAE1D,MAAM,EAAEJ,YAAaF,8BAAAA,+BAAAA,oBAAqB,QAAQ,CAAA,EAAEI,MAAOD,wBAAAA,yBAAAA,cAAe,QAAQ,CAAA,EAAE,GAAGL;IAEvF,MAAMS,cAAcZ,wBAAwBM,CAAAA,MAAOA,IAAIO,KAAK;IAC5D,MAAMC,YAAYd,wBAAwBM,CAAAA,MAAOA,IAAIQ,SAAS;IAC9D,MAAMC,sBAAsBf,wBAAwBM,CAAAA,MAAOA,IAAIS,mBAAmB;IAElF,MAAMC,OAAOF,UAAUG,GAAG,CAACN;IAE3B,OAAO;QACLK;QACAE,YAAY;YACVC,MAAM;QACR;QACAZ;QACAE;QACAI,OAAOD,cAAc;QACrBO,MAAMrB,sBAAsB,OAAO;YACjCM,KAAKL,cAAcK,KAAKM;YACxBU,MAAM;YACN,GAAGjB,KAAK;QACV;QACAW;QACAC;IACF;AACF,CAAC"}
1
+ {"version":3,"sources":["useSubtree.ts"],"sourcesContent":["import * as React from 'react';\nimport { getNativeElementProps, useMergedRefs } from '@fluentui/react-utilities';\nimport { TreeProps, TreeState } from './Tree.types';\nimport { useTreeContext_unstable, useTreeItemContext_unstable } from '../../contexts';\n\n/**\n * Create the state required to render a sub-level Tree.\n *\n * @param props - props from this instance of Tree\n * @param ref - reference to root HTMLElement of Tree\n */\nexport function useSubtree(props: TreeProps, ref: React.Ref<HTMLElement>): TreeState {\n const contextAppearance = useTreeContext_unstable(ctx => ctx.appearance);\n const contextSize = useTreeContext_unstable(ctx => ctx.size);\n const subtreeRef = useTreeItemContext_unstable(ctx => ctx.subtreeRef);\n const value = useTreeItemContext_unstable(ctx => ctx.value);\n\n const { appearance = contextAppearance ?? 'subtle', size = contextSize ?? 'medium' } = props;\n\n const parentLevel = useTreeContext_unstable(ctx => ctx.level);\n const selectionMode = useTreeContext_unstable(ctx => ctx.selectionMode);\n const openItems = useTreeContext_unstable(ctx => ctx.openItems);\n const checkedItems = useTreeContext_unstable(ctx => ctx.checkedItems);\n const requestTreeResponse = useTreeContext_unstable(ctx => ctx.requestTreeResponse);\n\n const open = openItems.has(value);\n\n return {\n open,\n components: {\n root: 'div',\n },\n appearance,\n size,\n selectionMode,\n level: parentLevel + 1,\n root: getNativeElementProps('div', {\n ref: useMergedRefs(ref, subtreeRef),\n role: 'group',\n ...props,\n }),\n openItems,\n checkedItems,\n requestTreeResponse,\n };\n}\n"],"names":["React","getNativeElementProps","useMergedRefs","useTreeContext_unstable","useTreeItemContext_unstable","useSubtree","props","ref","contextAppearance","ctx","appearance","contextSize","size","subtreeRef","value","parentLevel","level","selectionMode","openItems","checkedItems","requestTreeResponse","open","has","components","root","role"],"mappings":"AAAA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,qBAAqB,EAAEC,aAAa,QAAQ,4BAA4B;AAEjF,SAASC,uBAAuB,EAAEC,2BAA2B,QAAQ,iBAAiB;AAEtF;;;;;CAKC,GACD,OAAO,SAASC,WAAWC,KAAgB,EAAEC,GAA2B,EAAa;IACnF,MAAMC,oBAAoBL,wBAAwBM,CAAAA,MAAOA,IAAIC,UAAU;IACvE,MAAMC,cAAcR,wBAAwBM,CAAAA,MAAOA,IAAIG,IAAI;IAC3D,MAAMC,aAAaT,4BAA4BK,CAAAA,MAAOA,IAAII,UAAU;IACpE,MAAMC,QAAQV,4BAA4BK,CAAAA,MAAOA,IAAIK,KAAK;IAE1D,MAAM,EAAEJ,YAAaF,8BAAAA,+BAAAA,oBAAqB,QAAQ,CAAA,EAAEI,MAAOD,wBAAAA,yBAAAA,cAAe,QAAQ,CAAA,EAAE,GAAGL;IAEvF,MAAMS,cAAcZ,wBAAwBM,CAAAA,MAAOA,IAAIO,KAAK;IAC5D,MAAMC,gBAAgBd,wBAAwBM,CAAAA,MAAOA,IAAIQ,aAAa;IACtE,MAAMC,YAAYf,wBAAwBM,CAAAA,MAAOA,IAAIS,SAAS;IAC9D,MAAMC,eAAehB,wBAAwBM,CAAAA,MAAOA,IAAIU,YAAY;IACpE,MAAMC,sBAAsBjB,wBAAwBM,CAAAA,MAAOA,IAAIW,mBAAmB;IAElF,MAAMC,OAAOH,UAAUI,GAAG,CAACR;IAE3B,OAAO;QACLO;QACAE,YAAY;YACVC,MAAM;QACR;QACAd;QACAE;QACAK;QACAD,OAAOD,cAAc;QACrBS,MAAMvB,sBAAsB,OAAO;YACjCM,KAAKL,cAAcK,KAAKM;YACxBY,MAAM;YACN,GAAGnB,KAAK;QACV;QACAY;QACAC;QACAC;IACF;AACF,CAAC"}
@@ -1,13 +1,15 @@
1
1
  export function useTreeContextValues_unstable(state) {
2
- const { openItems , level , appearance , size , requestTreeResponse } = state;
2
+ const { openItems , checkedItems , selectionMode , level , appearance , size , requestTreeResponse } = state;
3
3
  /**
4
4
  * This context is created with "@fluentui/react-context-selector",
5
5
  * there is no sense to memoize it
6
6
  */ const tree = {
7
- appearance,
8
7
  size,
9
8
  level,
10
9
  openItems,
10
+ appearance,
11
+ checkedItems,
12
+ selectionMode,
11
13
  requestTreeResponse
12
14
  };
13
15
  return {
@@ -1 +1 @@
1
- {"version":3,"sources":["useTreeContextValues.ts"],"sourcesContent":["import { TreeContextValue } from '../../contexts';\nimport type { TreeContextValues, TreeState } from './Tree.types';\n\nexport function useTreeContextValues_unstable(state: TreeState): TreeContextValues {\n const { openItems, level, appearance, size, requestTreeResponse } = state;\n /**\n * This context is created with \"@fluentui/react-context-selector\",\n * there is no sense to memoize it\n */\n const tree: TreeContextValue = {\n appearance,\n size,\n level,\n openItems,\n requestTreeResponse,\n };\n\n return { tree };\n}\n"],"names":["useTreeContextValues_unstable","state","openItems","level","appearance","size","requestTreeResponse","tree"],"mappings":"AAGA,OAAO,SAASA,8BAA8BC,KAAgB,EAAqB;IACjF,MAAM,EAAEC,UAAS,EAAEC,MAAK,EAAEC,WAAU,EAAEC,KAAI,EAAEC,oBAAmB,EAAE,GAAGL;IACpE;;;GAGC,GACD,MAAMM,OAAyB;QAC7BH;QACAC;QACAF;QACAD;QACAI;IACF;IAEA,OAAO;QAAEC;IAAK;AAChB,CAAC"}
1
+ {"version":3,"sources":["useTreeContextValues.ts"],"sourcesContent":["import { TreeContextValue } from '../../contexts';\nimport type { TreeContextValues, TreeState } from './Tree.types';\n\nexport function useTreeContextValues_unstable(state: TreeState): TreeContextValues {\n const { openItems, checkedItems, selectionMode, level, appearance, size, requestTreeResponse } = state;\n /**\n * This context is created with \"@fluentui/react-context-selector\",\n * there is no sense to memoize it\n */\n const tree: TreeContextValue = {\n size,\n level,\n openItems,\n appearance,\n checkedItems,\n selectionMode,\n requestTreeResponse,\n };\n\n return { tree };\n}\n"],"names":["useTreeContextValues_unstable","state","openItems","checkedItems","selectionMode","level","appearance","size","requestTreeResponse","tree"],"mappings":"AAGA,OAAO,SAASA,8BAA8BC,KAAgB,EAAqB;IACjF,MAAM,EAAEC,UAAS,EAAEC,aAAY,EAAEC,cAAa,EAAEC,MAAK,EAAEC,WAAU,EAAEC,KAAI,EAAEC,oBAAmB,EAAE,GAAGP;IACjG;;;GAGC,GACD,MAAMQ,OAAyB;QAC7BF;QACAF;QACAH;QACAI;QACAH;QACAC;QACAI;IACF;IAEA,OAAO;QAAEC;IAAK;AAChB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"sources":["TreeItem.types.ts"],"sourcesContent":["import type { ComponentProps, ComponentState, ExtractSlotProps, Slot } from '@fluentui/react-utilities';\nimport type { TreeItemContextValue } from '../../contexts';\nimport { treeItemLevelToken } from '../../utils/tokens';\nimport * as React from 'react';\n\nexport type TreeItemCSSProperties = React.CSSProperties & { [treeItemLevelToken]?: string | number };\n\nexport type TreeItemType = 'leaf' | 'branch';\n\nexport type TreeItemSlots = {\n root: Slot<ExtractSlotProps<Slot<'div'> & { style?: TreeItemCSSProperties }>>;\n};\n\nexport type TreeItemValue = string | number;\n\nexport type TreeItemContextValues = { treeItem: TreeItemContextValue };\n\n/**\n * TreeItem Props\n */\nexport type TreeItemProps = ComponentProps<Partial<TreeItemSlots>> & {\n itemType: TreeItemType;\n value?: TreeItemValue;\n};\n\n/**\n * State used in rendering TreeItem\n */\nexport type TreeItemState = ComponentState<TreeItemSlots> &\n TreeItemContextValue & {\n level: number;\n itemType: TreeItemType;\n };\n"],"names":["React"],"mappings":"AAGA,YAAYA,WAAW,QAAQ"}
1
+ {"version":3,"sources":["TreeItem.types.ts"],"sourcesContent":["import type { ComponentProps, ComponentState, ExtractSlotProps, Slot } from '@fluentui/react-utilities';\nimport type { TreeItemContextValue } from '../../contexts';\nimport { treeItemLevelToken } from '../../utils/tokens';\nimport * as React from 'react';\nimport { TreeItemSlotsContextValue } from '../../contexts/treeItemSlotsContext';\nimport type { Checkbox } from '@fluentui/react-checkbox';\nimport type { Radio } from '@fluentui/react-radio';\n\nexport type TreeItemCSSProperties = React.CSSProperties & { [treeItemLevelToken]?: string | number };\n\nexport type TreeItemType = 'leaf' | 'branch';\n\nexport type TreeItemSlots = {\n root: Slot<ExtractSlotProps<Slot<'div'> & { style?: TreeItemCSSProperties }>>;\n /**\n * Expand icon slot,\n * by default renders a chevron icon to indicate opening and closing\n */\n expandIcon?: Slot<'div'>;\n aside?: Slot<'div'>;\n /**\n * actionable elements are normally buttons, menus, or other focusable elements.\n * Those elements are only visibly available if the given tree item is currently active.\n */\n actions?: Slot<\n ExtractSlotProps<\n Slot<'div'> & {\n /**\n * Forces visibility of the aside/action content\n */\n visible?: boolean;\n }\n >\n >;\n /**\n * Selection indicator if selection type is checkbox\n */\n checkboxIndicator?: Slot<typeof Checkbox>;\n /**\n * Selection indicator if selection type is radio\n */\n radioIndicator?: Slot<typeof Radio>;\n};\n\nexport type TreeItemInternalSlot = Pick<TreeItemSlots, 'root'>;\n\nexport type TreeItemValue = string | number;\n\nexport type TreeItemContextValues = {\n treeItem: TreeItemContextValue;\n treeItemSlots: TreeItemSlotsContextValue;\n};\n\n/**\n * TreeItem Props\n */\nexport type TreeItemProps = ComponentProps<Partial<TreeItemSlots>> & {\n itemType: TreeItemType;\n value?: TreeItemValue;\n};\n\n/**\n * State used in rendering TreeItem\n */\nexport type TreeItemState = ComponentState<TreeItemInternalSlot> &\n TreeItemContextValue &\n TreeItemSlotsContextValue & {\n level: number;\n itemType: TreeItemType;\n };\n"],"names":["React"],"mappings":"AAGA,YAAYA,WAAW,QAAQ"}
@@ -1,11 +1,13 @@
1
1
  /** @jsxRuntime classic */ /** @jsx createElement */ import { createElement } from '@fluentui/react-jsx-runtime';
2
2
  import { getSlotsNext } from '@fluentui/react-utilities';
3
- import { TreeItemProvider } from '../../contexts';
3
+ import { TreeItemProvider, TreeItemSlotsProvider } from '../../contexts';
4
4
  /**
5
5
  * Render the final JSX of TreeItem
6
6
  */ export const renderTreeItem_unstable = (state, contextValues)=>{
7
7
  const { slots , slotProps } = getSlotsNext(state);
8
8
  return /*#__PURE__*/ createElement(slots.root, slotProps.root, /*#__PURE__*/ createElement(TreeItemProvider, {
9
9
  value: contextValues.treeItem
10
- }, slotProps.root.children));
10
+ }, /*#__PURE__*/ createElement(TreeItemSlotsProvider, {
11
+ value: contextValues.treeItemSlots
12
+ }, slotProps.root.children)));
11
13
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["renderTreeItem.tsx"],"sourcesContent":["/** @jsxRuntime classic */\n/** @jsx createElement */\n\nimport { createElement } from '@fluentui/react-jsx-runtime';\nimport { getSlotsNext } from '@fluentui/react-utilities';\nimport type { TreeItemState, TreeItemSlots, TreeItemContextValues } from './TreeItem.types';\nimport { TreeItemProvider } from '../../contexts';\n\n/**\n * Render the final JSX of TreeItem\n */\nexport const renderTreeItem_unstable = (state: TreeItemState, contextValues: TreeItemContextValues) => {\n const { slots, slotProps } = getSlotsNext<TreeItemSlots>(state);\n\n return (\n <slots.root {...slotProps.root}>\n <TreeItemProvider value={contextValues.treeItem}>{slotProps.root.children}</TreeItemProvider>\n </slots.root>\n );\n};\n"],"names":["createElement","getSlotsNext","TreeItemProvider","renderTreeItem_unstable","state","contextValues","slots","slotProps","root","value","treeItem","children"],"mappings":"AAAA,wBAAwB,GACxB,uBAAuB,GAEvB,SAASA,aAAa,QAAQ,8BAA8B;AAC5D,SAASC,YAAY,QAAQ,4BAA4B;AAEzD,SAASC,gBAAgB,QAAQ,iBAAiB;AAElD;;CAEC,GACD,OAAO,MAAMC,0BAA0B,CAACC,OAAsBC,gBAAyC;IACrG,MAAM,EAAEC,MAAK,EAAEC,UAAS,EAAE,GAAGN,aAA4BG;IAEzD,qBACE,AAdJ,cAcKE,MAAME,IAAI,EAAKD,UAAUC,IAAI,gBAC5B,AAfN,cAeON;QAAiBO,OAAOJ,cAAcK,QAAQ;OAAGH,UAAUC,IAAI,CAACG,QAAQ;AAG/E,EAAE"}
1
+ {"version":3,"sources":["renderTreeItem.tsx"],"sourcesContent":["/** @jsxRuntime classic */\n/** @jsx createElement */\n\nimport { createElement } from '@fluentui/react-jsx-runtime';\nimport { getSlotsNext } from '@fluentui/react-utilities';\nimport type { TreeItemState, TreeItemContextValues, TreeItemInternalSlot } from './TreeItem.types';\nimport { TreeItemProvider, TreeItemSlotsProvider } from '../../contexts';\n\n/**\n * Render the final JSX of TreeItem\n */\nexport const renderTreeItem_unstable = (state: TreeItemState, contextValues: TreeItemContextValues) => {\n const { slots, slotProps } = getSlotsNext<TreeItemInternalSlot>(state);\n\n return (\n <slots.root {...slotProps.root}>\n <TreeItemProvider value={contextValues.treeItem}>\n <TreeItemSlotsProvider value={contextValues.treeItemSlots}>{slotProps.root.children}</TreeItemSlotsProvider>\n </TreeItemProvider>\n </slots.root>\n );\n};\n"],"names":["createElement","getSlotsNext","TreeItemProvider","TreeItemSlotsProvider","renderTreeItem_unstable","state","contextValues","slots","slotProps","root","value","treeItem","treeItemSlots","children"],"mappings":"AAAA,wBAAwB,GACxB,uBAAuB,GAEvB,SAASA,aAAa,QAAQ,8BAA8B;AAC5D,SAASC,YAAY,QAAQ,4BAA4B;AAEzD,SAASC,gBAAgB,EAAEC,qBAAqB,QAAQ,iBAAiB;AAEzE;;CAEC,GACD,OAAO,MAAMC,0BAA0B,CAACC,OAAsBC,gBAAyC;IACrG,MAAM,EAAEC,MAAK,EAAEC,UAAS,EAAE,GAAGP,aAAmCI;IAEhE,qBACE,AAdJ,cAcKE,MAAME,IAAI,EAAKD,UAAUC,IAAI,gBAC5B,AAfN,cAeOP;QAAiBQ,OAAOJ,cAAcK,QAAQ;qBAC7C,AAhBR,cAgBSR;QAAsBO,OAAOJ,cAAcM,aAAa;OAAGJ,UAAUC,IAAI,CAACI,QAAQ;AAI3F,EAAE"}
@@ -1,10 +1,12 @@
1
1
  import * as React from 'react';
2
- import { getNativeElementProps, useId, useMergedRefs } from '@fluentui/react-utilities';
2
+ import { getNativeElementProps, isResolvedShorthand, resolveShorthand, useControllableState, useId, useMergedRefs } from '@fluentui/react-utilities';
3
3
  import { useEventCallback } from '@fluentui/react-utilities';
4
4
  import { elementContains } from '@fluentui/react-portal';
5
5
  import { useTreeContext_unstable } from '../../contexts/index';
6
- import { treeDataTypes } from '../../utils/tokens';
7
6
  import { dataTreeItemValueAttrName } from '../../utils/getTreeItemValueFromElement';
7
+ import { TreeItemChevron } from '../TreeItemChevron';
8
+ import { Space } from '@fluentui/keyboard-keys';
9
+ import { treeDataTypes } from '../../utils/tokens';
8
10
  /**
9
11
  * Create the state required to render TreeItem.
10
12
  *
@@ -17,18 +19,38 @@ import { dataTreeItemValueAttrName } from '../../utils/getTreeItemValueFromEleme
17
19
  var _props_value;
18
20
  const contextLevel = useTreeContext_unstable((ctx)=>ctx.level);
19
21
  const value = useId('fuiTreeItemValue-', (_props_value = props.value) === null || _props_value === void 0 ? void 0 : _props_value.toString());
20
- const { onClick , onKeyDown , as ='div' , itemType ='leaf' , 'aria-level': level = contextLevel , ...rest } = props;
22
+ const { onClick , onKeyDown , as ='div' , itemType ='leaf' , 'aria-level': level = contextLevel , expandIcon , aside , ...rest } = props;
21
23
  const requestTreeResponse = useTreeContext_unstable((ctx)=>ctx.requestTreeResponse);
22
- const [isActionsVisible, setActionsVisible] = React.useState(false);
24
+ const [isActionsVisibleExternal, actions] = isResolvedShorthand(props.actions) ? [
25
+ props.actions.visible,
26
+ {
27
+ ...props.actions,
28
+ visible: undefined
29
+ }
30
+ ] : [
31
+ undefined,
32
+ props.actions
33
+ ];
34
+ const [isActionsVisible, setActionsVisible] = useControllableState({
35
+ state: isActionsVisibleExternal,
36
+ defaultState: false,
37
+ initialState: false
38
+ });
23
39
  const [isAsideVisible, setAsideVisible] = React.useState(true);
24
- const handleActionsRef = (actions)=>{
25
- setAsideVisible(actions === null);
40
+ const handleActionsRef = (actionsElement)=>{
41
+ setAsideVisible(actionsElement === null);
26
42
  };
27
- const open = useTreeContext_unstable((ctx)=>ctx.openItems.has(value));
28
43
  const actionsRef = React.useRef(null);
29
44
  const expandIconRef = React.useRef(null);
30
45
  const layoutRef = React.useRef(null);
31
46
  const subtreeRef = React.useRef(null);
47
+ const selectionRef = React.useRef(null);
48
+ const open = useTreeContext_unstable((ctx)=>ctx.openItems.has(value));
49
+ var _ctx_checkedItems_get;
50
+ const checked = useTreeContext_unstable((ctx)=>(_ctx_checkedItems_get = ctx.checkedItems.get(value)) !== null && _ctx_checkedItems_get !== void 0 ? _ctx_checkedItems_get : false);
51
+ const selectionMode = useTreeContext_unstable((ctx)=>ctx.selectionMode);
52
+ const actionsRefs = useMergedRefs(isResolvedShorthand(actions) ? actions.ref : undefined, handleActionsRef, actionsRef);
53
+ const expandIconRefs = useMergedRefs(isResolvedShorthand(expandIcon) ? expandIcon.ref : undefined, expandIconRef);
32
54
  const handleClick = useEventCallback((event)=>{
33
55
  onClick === null || onClick === void 0 ? void 0 : onClick(event);
34
56
  if (event.isDefaultPrevented()) {
@@ -42,23 +64,33 @@ import { dataTreeItemValueAttrName } from '../../utils/getTreeItemValueFromEleme
42
64
  if (isEventFromSubtree) {
43
65
  return;
44
66
  }
67
+ const isEventFromSelection = selectionRef.current && elementContains(selectionRef.current, event.target);
68
+ if (isEventFromSelection) {
69
+ return;
70
+ }
45
71
  const isFromExpandIcon = expandIconRef.current && elementContains(expandIconRef.current, event.target);
46
72
  requestTreeResponse({
47
73
  event,
48
- itemType,
49
74
  value,
75
+ itemType,
76
+ target: event.currentTarget,
50
77
  type: isFromExpandIcon ? treeDataTypes.ExpandIconClick : treeDataTypes.Click
51
78
  });
52
79
  });
53
80
  const handleKeyDown = useEventCallback((event)=>{
54
81
  onKeyDown === null || onKeyDown === void 0 ? void 0 : onKeyDown(event);
55
- if (event.isDefaultPrevented()) {
56
- return;
57
- }
58
- if (event.currentTarget !== event.target) {
82
+ // Ignore keyboard events that do not originate from the current tree item.
83
+ if (event.isDefaultPrevented() || event.currentTarget !== event.target) {
59
84
  return;
60
85
  }
61
86
  switch(event.key){
87
+ case Space:
88
+ if (selectionMode !== 'none') {
89
+ var _selectionRef_current;
90
+ (_selectionRef_current = selectionRef.current) === null || _selectionRef_current === void 0 ? void 0 : _selectionRef_current.click();
91
+ event.preventDefault();
92
+ }
93
+ return;
62
94
  case treeDataTypes.End:
63
95
  case treeDataTypes.Home:
64
96
  case treeDataTypes.Enter:
@@ -68,6 +100,7 @@ import { dataTreeItemValueAttrName } from '../../utils/getTreeItemValueFromEleme
68
100
  case treeDataTypes.ArrowRight:
69
101
  return requestTreeResponse({
70
102
  event,
103
+ target: event.currentTarget,
71
104
  value,
72
105
  itemType,
73
106
  type: event.key
@@ -77,6 +110,7 @@ import { dataTreeItemValueAttrName } from '../../utils/getTreeItemValueFromEleme
77
110
  if (isTypeAheadCharacter) {
78
111
  requestTreeResponse({
79
112
  event,
113
+ target: event.currentTarget,
80
114
  value,
81
115
  itemType,
82
116
  type: treeDataTypes.TypeAhead
@@ -99,16 +133,53 @@ import { dataTreeItemValueAttrName } from '../../utils/getTreeItemValueFromEleme
99
133
  return setActionsVisible(false);
100
134
  }
101
135
  });
136
+ const handleChange = useEventCallback((event)=>{
137
+ if (event.isDefaultPrevented()) {
138
+ return;
139
+ }
140
+ const isEventFromSubtree = subtreeRef.current && elementContains(subtreeRef.current, event.target);
141
+ if (isEventFromSubtree) {
142
+ return;
143
+ }
144
+ requestTreeResponse({
145
+ event,
146
+ value,
147
+ itemType,
148
+ type: 'Change',
149
+ target: event.currentTarget
150
+ });
151
+ });
152
+ const isBranch = itemType === 'branch';
153
+ const actionsSlot = React.useMemo(()=>isActionsVisible ? resolveShorthand(actions) : undefined, [
154
+ actions,
155
+ isActionsVisible
156
+ ]);
157
+ if (actionsSlot) {
158
+ actionsSlot.ref = actionsRefs;
159
+ }
160
+ const asideSlot = React.useMemo(()=>isAsideVisible ? resolveShorthand(aside) : undefined, [
161
+ aside,
162
+ isAsideVisible
163
+ ]);
164
+ const expandIconSlot = React.useMemo(()=>resolveShorthand(expandIcon, {
165
+ required: isBranch,
166
+ defaultProps: {
167
+ children: /*#__PURE__*/ React.createElement(TreeItemChevron, null),
168
+ 'aria-hidden': true
169
+ }
170
+ }), [
171
+ expandIcon,
172
+ isBranch
173
+ ]);
174
+ if (expandIconSlot) {
175
+ expandIconSlot.ref = expandIconRefs;
176
+ }
102
177
  return {
103
178
  value,
104
179
  open,
105
180
  subtreeRef,
106
- actionsRef: useMergedRefs(actionsRef, handleActionsRef),
107
- expandIconRef,
108
181
  layoutRef,
109
182
  itemType,
110
- isActionsVisible,
111
- isAsideVisible,
112
183
  level,
113
184
  components: {
114
185
  root: 'div'
@@ -120,13 +191,28 @@ import { dataTreeItemValueAttrName } from '../../utils/getTreeItemValueFromEleme
120
191
  role: 'treeitem',
121
192
  'aria-level': level,
122
193
  [dataTreeItemValueAttrName]: value,
123
- 'aria-expanded': itemType === 'branch' ? open : undefined,
194
+ 'aria-checked': selectionMode === 'multiselect' ? checked : undefined,
195
+ 'aria-selected': selectionMode === 'single' ? checked : undefined,
196
+ 'aria-expanded': isBranch ? open : undefined,
124
197
  onClick: handleClick,
125
198
  onKeyDown: handleKeyDown,
126
199
  onMouseOver: handleActionsVisible,
127
200
  onFocus: handleActionsVisible,
128
201
  onMouseOut: handleActionsInvisible,
129
- onBlur: handleActionsInvisible
202
+ onBlur: handleActionsInvisible,
203
+ onChange: handleChange
204
+ }),
205
+ actions: actionsSlot,
206
+ aside: asideSlot,
207
+ expandIcon: expandIconSlot,
208
+ selector: selectionMode === 'none' ? undefined : resolveShorthand(selectionMode === 'multiselect' ? props.checkboxIndicator : props.radioIndicator, {
209
+ required: true,
210
+ defaultProps: {
211
+ checked,
212
+ tabIndex: -1,
213
+ 'aria-hidden': true,
214
+ ref: selectionRef
215
+ }
130
216
  })
131
217
  };
132
218
  }