@fluentui/react-tree 9.7.6 → 9.7.8

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 (57) hide show
  1. package/CHANGELOG.md +21 -2
  2. package/dist/index.d.ts +58 -86
  3. package/lib/components/FlatTree/useFlatControllableCheckedItems.js +15 -13
  4. package/lib/components/FlatTree/useFlatControllableCheckedItems.js.map +1 -1
  5. package/lib/components/FlatTree/useHeadlessFlatTree.js +4 -2
  6. package/lib/components/FlatTree/useHeadlessFlatTree.js.map +1 -1
  7. package/lib/components/Tree/Tree.types.js.map +1 -1
  8. package/lib/components/Tree/renderTree.js +3 -3
  9. package/lib/components/Tree/renderTree.js.map +1 -1
  10. package/lib/components/Tree/useNestedControllableCheckedItems.js +1 -1
  11. package/lib/components/Tree/useNestedControllableCheckedItems.js.map +1 -1
  12. package/lib/components/Tree/useTree.js +4 -2
  13. package/lib/components/Tree/useTree.js.map +1 -1
  14. package/lib/components/TreeItemChevron.js +5 -1
  15. package/lib/components/TreeItemChevron.js.map +1 -1
  16. package/lib/hooks/useControllableOpenItems.js +3 -12
  17. package/lib/hooks/useControllableOpenItems.js.map +1 -1
  18. package/lib/hooks/useRootTree.js +14 -6
  19. package/lib/hooks/useRootTree.js.map +1 -1
  20. package/lib/hooks/useSubtree.js +15 -1
  21. package/lib/hooks/useSubtree.js.map +1 -1
  22. package/lib/utils/ImmutableMap.js +71 -40
  23. package/lib/utils/ImmutableMap.js.map +1 -1
  24. package/lib/utils/ImmutableSet.js +65 -44
  25. package/lib/utils/ImmutableSet.js.map +1 -1
  26. package/lib/utils/createCheckedItems.js +5 -17
  27. package/lib/utils/createCheckedItems.js.map +1 -1
  28. package/lib-commonjs/components/FlatTree/useFlatControllableCheckedItems.js +15 -13
  29. package/lib-commonjs/components/FlatTree/useFlatControllableCheckedItems.js.map +1 -1
  30. package/lib-commonjs/components/FlatTree/useHeadlessFlatTree.js +4 -2
  31. package/lib-commonjs/components/FlatTree/useHeadlessFlatTree.js.map +1 -1
  32. package/lib-commonjs/components/Tree/Tree.types.js.map +1 -1
  33. package/lib-commonjs/components/Tree/renderTree.js +3 -3
  34. package/lib-commonjs/components/Tree/renderTree.js.map +1 -1
  35. package/lib-commonjs/components/Tree/useNestedControllableCheckedItems.js +1 -1
  36. package/lib-commonjs/components/Tree/useNestedControllableCheckedItems.js.map +1 -1
  37. package/lib-commonjs/components/Tree/useTree.js +4 -2
  38. package/lib-commonjs/components/Tree/useTree.js.map +1 -1
  39. package/lib-commonjs/components/TreeItemChevron.js +5 -1
  40. package/lib-commonjs/components/TreeItemChevron.js.map +1 -1
  41. package/lib-commonjs/hooks/useControllableOpenItems.js +3 -12
  42. package/lib-commonjs/hooks/useControllableOpenItems.js.map +1 -1
  43. package/lib-commonjs/hooks/useRootTree.js +14 -6
  44. package/lib-commonjs/hooks/useRootTree.js.map +1 -1
  45. package/lib-commonjs/hooks/useSubtree.js +15 -1
  46. package/lib-commonjs/hooks/useSubtree.js.map +1 -1
  47. package/lib-commonjs/utils/ImmutableMap.js +71 -40
  48. package/lib-commonjs/utils/ImmutableMap.js.map +1 -1
  49. package/lib-commonjs/utils/ImmutableSet.js +61 -45
  50. package/lib-commonjs/utils/ImmutableSet.js.map +1 -1
  51. package/lib-commonjs/utils/createCheckedItems.js +5 -17
  52. package/lib-commonjs/utils/createCheckedItems.js.map +1 -1
  53. package/package.json +4 -2
  54. package/lib/utils/createOpenItems.js +0 -10
  55. package/lib/utils/createOpenItems.js.map +0 -1
  56. package/lib-commonjs/utils/createOpenItems.js +0 -20
  57. package/lib-commonjs/utils/createOpenItems.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,12 +1,31 @@
1
1
  # Change Log - @fluentui/react-tree
2
2
 
3
- This log was last generated on Tue, 30 Jul 2024 18:45:10 GMT and should not be manually modified.
3
+ This log was last generated on Tue, 06 Aug 2024 21:39:53 GMT and should not be manually modified.
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
+ ## [9.7.8](https://github.com/microsoft/fluentui/tree/@fluentui/react-tree_v9.7.8)
8
+
9
+ Tue, 06 Aug 2024 21:39:53 GMT
10
+ [Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-tree_v9.7.7..@fluentui/react-tree_v9.7.8)
11
+
12
+ ### Patches
13
+
14
+ - chore: improve ImmutableSet and ImmutableMap internal implementation ([PR #32167](https://github.com/microsoft/fluentui/pull/32167) by bernardo.sunderhus@gmail.com)
15
+
16
+ ## [9.7.7](https://github.com/microsoft/fluentui/tree/@fluentui/react-tree_v9.7.7)
17
+
18
+ Mon, 05 Aug 2024 22:33:04 GMT
19
+ [Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-tree_v9.7.6..@fluentui/react-tree_v9.7.7)
20
+
21
+ ### Patches
22
+
23
+ - feat: add collapse motion to Tree ([PR #32163](https://github.com/microsoft/fluentui/pull/32163) by olkatruk@microsoft.com)
24
+ - Bump @fluentui/react-avatar to v9.6.35 ([PR #32077](https://github.com/microsoft/fluentui/pull/32077) by beachball)
25
+
7
26
  ## [9.7.6](https://github.com/microsoft/fluentui/tree/@fluentui/react-tree_v9.7.6)
8
27
 
9
- Tue, 30 Jul 2024 18:45:10 GMT
28
+ Tue, 30 Jul 2024 18:47:35 GMT
10
29
  [Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-tree_v9.7.5..@fluentui/react-tree_v9.7.6)
11
30
 
12
31
  ### Patches
package/dist/index.d.ts CHANGED
@@ -20,6 +20,7 @@ import type { EventHandler } from '@fluentui/react-utilities';
20
20
  import type { ExtractSlotProps } from '@fluentui/react-utilities';
21
21
  import { ForwardRefComponent } from '@fluentui/react-utilities';
22
22
  import type { Home } from '@fluentui/keyboard-keys';
23
+ import type { PresenceMotionSlotProps } from '@fluentui/react-motion';
23
24
  import { Radio } from '@fluentui/react-radio';
24
25
  import { RadioProps } from '@fluentui/react-radio';
25
26
  import * as React_2 from 'react';
@@ -27,28 +28,6 @@ import type { SelectionMode as SelectionMode_2 } from '@fluentui/react-utilities
27
28
  import type { Slot } from '@fluentui/react-utilities';
28
29
  import type { SlotClassNames } from '@fluentui/react-utilities';
29
30
 
30
- /**
31
- * properly creates an ImmutableMap instance from an iterable
32
- */
33
- declare function createImmutableMap<Key, Value>(iterable?: Iterable<[Key, Value]>): ImmutableMap<Key, Value>;
34
-
35
- /**
36
- * properly creates an ImmutableSet instance from an iterable
37
- */
38
- declare function createImmutableSet<Value>(iterable?: Iterable<Value>): ImmutableSet<Value>;
39
-
40
- /**
41
- * Avoid using *dangerouslyCreateImmutableMap*, since this method will expose internally used set, use createImmutableMap instead,
42
- * @param internalMap - a set that is used internally to store values.
43
- */
44
- declare function dangerouslyCreateImmutableMap<Key, Value>(internalMap: Map<Key, Value>): ImmutableMap<Key, Value>;
45
-
46
- /**
47
- * Avoid using *dangerouslyCreateImmutableSet*, since this method will expose internally used set, use createImmutableSet instead,
48
- * @param internalSet - a set that is used internally to store values.
49
- */
50
- declare function dangerouslyCreateImmutableSet<Value>(internalSet: Set<Value>): ImmutableSet<Value>;
51
-
52
31
  declare type FlattenedTreeItem<Props extends TreeItemProps> = HeadlessFlatTreeItemProps & Props;
53
32
 
54
33
  /**
@@ -106,7 +85,7 @@ export declare type FlattenTreeItem<Props extends TreeItemProps> = Omit<Props, '
106
85
  */
107
86
  export declare const FlatTree: ForwardRefComponent<FlatTreeProps>;
108
87
 
109
- export declare const flatTreeClassNames: SlotClassNames<FlatTreeSlots>;
88
+ export declare const flatTreeClassNames: SlotClassNames<Omit<FlatTreeSlots, 'collapseMotion'>>;
110
89
 
111
90
  declare type FlatTreeContextValues = {
112
91
  tree: TreeContextValue;
@@ -296,85 +275,77 @@ declare type HeadlessTreeItemProps = Omit<TreeItemProps, 'itemType' | 'value'> &
296
275
  parentValue?: TreeItemValue;
297
276
  };
298
277
 
299
- declare interface ImmutableMap<Key, Value> {
300
- clear(): ImmutableMap<Key, Value>;
301
- delete(key: Key): ImmutableMap<Key, Value>;
278
+ declare class ImmutableMap<Key, Value> implements Iterable<[Key, Value]> {
279
+ static empty: ImmutableMap<never, never>;
280
+ readonly size: number;
281
+ private [internalMapSymbol];
282
+ static dangerouslyGetInternalMap<Key, Value>(immutableMap: ImmutableMap<Key, Value>): Map<Key, Value>;
283
+ static copy<Key, Value>(immutableMap: ImmutableMap<Key, Value>): ImmutableMap<Key, Value>;
302
284
  /**
303
- * Returns a specified element from the Map object. If the value that is associated to the provided key is an object, then you will get a reference to that object and any change made to that object will effectively modify it inside the Map.
304
- * @returns Returns the element associated with the specified key. If no element is associated with the specified key, undefined is returned.
285
+ * Creates a new {@link ImmutableMap} from an iterable.
286
+ * If the iterable is undefined, {@link ImmutableMap.empty} will be returned.
287
+ * If the iterable is already an {@link ImmutableMap}, it will be returned as is no copy will be made.
305
288
  */
306
- get(key: Key): Value | undefined;
289
+ static from<T extends [unknown, unknown]>(iterable?: Iterable<T>): ImmutableMap<T[0], T[1]>;
307
290
  /**
308
- * @returns boolean indicating whether an element with the specified key exists or not.
291
+ * Creates a new {@link ImmutableMap} from an iterable with an auxiliary map function to modify the iterable.
292
+ * If the iterable is undefined, {@link ImmutableMap.empty} will be returned.
293
+ * If the iterable is already an {@link ImmutableMap}, it will be returned as is no copy will be made.
294
+ * The map function will be called for each element in the iterable.
309
295
  */
310
- has(key: Key): boolean;
296
+ static from<T, U extends [unknown, unknown]>(iterable: Iterable<T> | undefined, mapFn: (value: T) => U): ImmutableMap<U[0], U[1]>;
297
+ static [Symbol.hasInstance](instance: unknown): boolean;
311
298
  /**
312
- * Adds a new element with a specified key and value to the Map. If an element with the same key already exists, the element will be updated.
299
+ * Do not use this constructor directly, use {@link ImmutableMap.from} instead.
300
+ * {@link ImmutableMap.from} handles instance verification (which might be problematic on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof#instanceof_and_multiple_realms | multiple realms}),
301
+ * avoid unnecessary copies, supports iterables and ensures that the internal map is never exposed.
302
+ *
303
+ *⚠️⚠️ _By using this constructor directly, you might end up with a mutable map, as it is not guaranteed that the internal map is not exposed._ ⚠️⚠️
313
304
  */
305
+ constructor(internalMap: Map<Key, Value>);
306
+ delete(key: Key): ImmutableMap<Key, Value>;
307
+ get(key: Key): Value | undefined;
308
+ has(key: Key): boolean;
314
309
  set(key: Key, value: Value): ImmutableMap<Key, Value>;
315
- /**
316
- * @returns the number of elements in the Map.
317
- */
318
- readonly size: number;
319
- /** Iterates over entries in the Map. */
320
- [Symbol.iterator](): IterableIterator<[Key, Value]>;
321
- /**
322
- * @internal
323
- * Exposes the internal map used to store values.
324
- * This is an internal API and should not be used directly.
325
- */
326
- dangerouslyGetInternalMap_unstable(): Map<Key, Value>;
310
+ [Symbol.iterator](): Iterator<[Key, Value]>;
327
311
  }
328
312
 
329
- declare const ImmutableMap: {
330
- empty: ImmutableMap<never, never>;
331
- create: typeof createImmutableMap;
332
- isImmutableMap: typeof isImmutableMap;
333
- dangerouslyCreate_unstable: typeof dangerouslyCreateImmutableMap;
334
- };
335
-
336
- declare interface ImmutableSet<Value> {
337
- /**
338
- * The number of (unique) elements in a ImmutableSet.
339
- */
313
+ /**
314
+ * @public
315
+ *
316
+ * Small immutable wrapper around the native Set implementation.
317
+ * Every operation that would modify the set returns a new copy instance.
318
+ */
319
+ declare class ImmutableSet<T> implements Iterable<T> {
320
+ static empty: ImmutableSet<never>;
340
321
  readonly size: number;
322
+ private [internalSetSymbol];
323
+ static dangerouslyGetInternalSet<Value>(set: ImmutableSet<Value>): Set<Value>;
324
+ static copy<T>(immutableSet: ImmutableSet<T>): ImmutableSet<T>;
341
325
  /**
342
- * Creates a new ImmutableSet containing all previous element plus the one provided as argument
343
- * @param value - new value to be included in the new ImmutableSet instance
344
- */
345
- add(value: Value): ImmutableSet<Value>;
346
- /**
347
- * Returns a reference to ImmutableSet.emptySet
348
- */
349
- clear(): ImmutableSet<Value>;
350
- /**
351
- * Creates a new ImmutableSet with the original items and removes a specified value from the new ImmutableSet.
326
+ * Creates a new {@link ImmutableSet} from an iterable.
327
+ * If the iterable is undefined, {@link ImmutableSet.empty} will be returned.
328
+ * If the iterable is already an {@link ImmutableSet}, it will be returned as is no copy will be made.
352
329
  */
353
- delete(value: Value): ImmutableSet<Value>;
330
+ static from<Value>(iterable?: Iterable<Value>): ImmutableSet<Value>;
331
+ static [Symbol.hasInstance](instance: unknown): boolean;
354
332
  /**
355
- * @returns a boolean indicating whether an element with the specified value exists in the ImmutableSet or not.
356
- */
357
- has(value: Value): boolean;
358
- /** Iterates over values in the ImmutableSet. */
359
- [Symbol.iterator](): IterableIterator<Value>;
360
- /**
361
- * @internal
362
- * Exposes the internal set used to store values.
363
- * This is an internal API and should not be used directly.
333
+ * Do not use this constructor directly, use {@link ImmutableSet.from} instead.
334
+ * {@link ImmutableSet.from} handles instance verification (which might be problematic on {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof#instanceof_and_multiple_realms | multiple realms}),
335
+ * avoid unnecessary copies, supports iterables and ensures that the internal set is never exposed.
336
+ *
337
+ *⚠️⚠️ _By using this constructor directly, you might end up with a mutable set, as it is not guaranteed that the internal set is not exposed._ ⚠️⚠️
364
338
  */
365
- dangerouslyGetInternalSet_unstable(): Set<Value>;
339
+ constructor(internalSet: Set<T>);
340
+ add(value: T): ImmutableSet<T>;
341
+ delete(value: T): ImmutableSet<T>;
342
+ has(value: T): boolean;
343
+ [Symbol.iterator](): Iterator<T>;
366
344
  }
367
345
 
368
- declare const ImmutableSet: {
369
- empty: ImmutableSet<never>;
370
- create: typeof createImmutableSet;
371
- isImmutableSet: typeof isImmutableSet;
372
- dangerouslyCreate_unstable: typeof dangerouslyCreateImmutableSet;
373
- };
374
-
375
- declare function isImmutableMap<Key, Value>(value: unknown): value is ImmutableMap<Key, Value>;
346
+ declare const internalMapSymbol: unique symbol;
376
347
 
377
- declare function isImmutableSet<Value>(value: unknown): value is ImmutableSet<Value>;
348
+ declare const internalSetSymbol: unique symbol;
378
349
 
379
350
  declare type MultiSelectValue = NonNullable<CheckboxProps['checked']>;
380
351
 
@@ -426,7 +397,7 @@ export declare type TreeCheckedChangeData = {
426
397
 
427
398
  export declare type TreeCheckedChangeEvent = TreeCheckedChangeData['event'];
428
399
 
429
- export declare const treeClassNames: SlotClassNames<TreeSlots>;
400
+ export declare const treeClassNames: SlotClassNames<Omit<TreeSlots, 'collapseMotion'>>;
430
401
 
431
402
  export declare type TreeContextValue = {
432
403
  contextType?: 'root';
@@ -843,6 +814,7 @@ export declare type TreeSelectionValue = MultiSelectValue | SingleSelectValue;
843
814
 
844
815
  export declare type TreeSlots = {
845
816
  root: Slot<'div'>;
817
+ collapseMotion?: Slot<PresenceMotionSlotProps>;
846
818
  };
847
819
 
848
820
  /**
@@ -14,7 +14,7 @@ export function useFlatControllableCheckedItems(props, headlessTree) {
14
14
  }
15
15
  export function createNextFlatCheckedItems(data, previousCheckedItems, headlessTree) {
16
16
  if (data.selectionMode === 'single') {
17
- return ImmutableMap.create([
17
+ return ImmutableMap.from([
18
18
  [
19
19
  data.value,
20
20
  data.checked
@@ -30,40 +30,42 @@ Tree item ${data.value} not found.`);
30
30
  }
31
31
  return previousCheckedItems;
32
32
  }
33
- const nextCheckedItems = new Map(previousCheckedItems);
33
+ let nextCheckedItems = previousCheckedItems;
34
34
  for (const children of headlessTree.subtree(data.value)){
35
- nextCheckedItems.set(children.value, data.checked);
35
+ nextCheckedItems = nextCheckedItems.set(children.value, data.checked);
36
36
  }
37
- nextCheckedItems.set(data.value, data.checked);
37
+ nextCheckedItems = nextCheckedItems.set(data.value, data.checked);
38
38
  let isAncestorsMixed = false;
39
39
  for (const parent of headlessTree.ancestors(treeItem.value)){
40
40
  // if one parent is mixed, all ancestors are mixed
41
41
  if (isAncestorsMixed) {
42
- nextCheckedItems.set(parent.value, 'mixed');
42
+ nextCheckedItems = nextCheckedItems.set(parent.value, 'mixed');
43
43
  continue;
44
44
  }
45
- const checkedChildren = [];
45
+ let checkedChildrenAmount = 0;
46
46
  for (const child of headlessTree.children(parent.value)){
47
- var _nextCheckedItems_get;
48
- if (((_nextCheckedItems_get = nextCheckedItems.get(child.value)) !== null && _nextCheckedItems_get !== void 0 ? _nextCheckedItems_get : false) === data.checked) {
49
- checkedChildren.push(child);
47
+ if ((nextCheckedItems.get(child.value) || false) === data.checked) {
48
+ checkedChildrenAmount++;
50
49
  }
51
50
  }
52
- if (checkedChildren.length === parent.childrenValues.length) {
53
- nextCheckedItems.set(parent.value, data.checked);
51
+ // if all children are checked, parent is checked
52
+ if (checkedChildrenAmount === parent.childrenValues.length) {
53
+ nextCheckedItems = nextCheckedItems.set(parent.value, data.checked);
54
54
  } else {
55
55
  // if one parent is mixed, all ancestors are mixed
56
56
  isAncestorsMixed = true;
57
- nextCheckedItems.set(parent.value, 'mixed');
57
+ nextCheckedItems = nextCheckedItems.set(parent.value, 'mixed');
58
58
  }
59
59
  }
60
- return ImmutableMap.dangerouslyCreate_unstable(nextCheckedItems);
60
+ return nextCheckedItems;
61
61
  }
62
62
  function initializeCheckedItems(props, headlessTree) {
63
63
  if (!props.selectionMode) {
64
64
  return ImmutableMap.empty;
65
65
  }
66
66
  let state = createCheckedItems(props.defaultCheckedItems);
67
+ // if selectionMode is multiselect, we need to calculate the checked state of all children
68
+ // and ancestors of the defaultCheckedItems
67
69
  if (props.selectionMode === 'multiselect') {
68
70
  for (const [value, checked] of state){
69
71
  state = createNextFlatCheckedItems({
@@ -1 +1 @@
1
- {"version":3,"sources":["useFlatControllableCheckedItems.ts"],"sourcesContent":["import { useControllableState } from '@fluentui/react-utilities';\nimport { TreeItemValue } from '../../TreeItem';\nimport { ImmutableMap } from '../../utils/ImmutableMap';\nimport * as React from 'react';\nimport type { HeadlessTree, HeadlessTreeItemProps } from '../../utils/createHeadlessTree';\nimport { createCheckedItems } from '../../utils/createCheckedItems';\nimport type { TreeCheckedChangeData } from '../Tree/Tree.types';\nimport { HeadlessFlatTreeOptions } from './useHeadlessFlatTree';\n\nexport function useFlatControllableCheckedItems<Props extends HeadlessTreeItemProps>(\n props: Pick<HeadlessFlatTreeOptions, 'checkedItems' | 'defaultCheckedItems' | 'selectionMode'>,\n headlessTree: HeadlessTree<Props>,\n) {\n return useControllableState({\n initialState: ImmutableMap.empty,\n state: React.useMemo(\n () => (props.selectionMode ? props.checkedItems && createCheckedItems(props.checkedItems) : undefined),\n [props.checkedItems, props.selectionMode],\n ),\n defaultState: props.defaultCheckedItems ? () => initializeCheckedItems(props, headlessTree) : undefined,\n });\n}\n\nexport function createNextFlatCheckedItems(\n data: Pick<TreeCheckedChangeData, 'value' | 'checked' | 'selectionMode'>,\n previousCheckedItems: ImmutableMap<TreeItemValue, 'mixed' | boolean>,\n headlessTree: HeadlessTree<HeadlessTreeItemProps>,\n): ImmutableMap<TreeItemValue, 'mixed' | boolean> {\n if (data.selectionMode === 'single') {\n return ImmutableMap.create([[data.value, data.checked]]);\n }\n const treeItem = headlessTree.get(data.value);\n if (!treeItem) {\n if (process.env.NODE_ENV !== 'production') {\n // eslint-disable-next-line no-console\n console.error(/* #__DE-INDENT__ */ `\n @fluentui/react-tree [useHeadlessFlatTree]:\n Tree item ${data.value} not found.\n `);\n }\n return previousCheckedItems;\n }\n const nextCheckedItems = new Map(previousCheckedItems);\n for (const children of headlessTree.subtree(data.value)) {\n nextCheckedItems.set(children.value, data.checked);\n }\n nextCheckedItems.set(data.value, data.checked);\n\n let isAncestorsMixed = false;\n for (const parent of headlessTree.ancestors(treeItem.value)) {\n // if one parent is mixed, all ancestors are mixed\n if (isAncestorsMixed) {\n nextCheckedItems.set(parent.value, 'mixed');\n continue;\n }\n const checkedChildren = [];\n for (const child of headlessTree.children(parent.value)) {\n if ((nextCheckedItems.get(child.value) ?? false) === data.checked) {\n checkedChildren.push(child);\n }\n }\n if (checkedChildren.length === parent.childrenValues.length) {\n nextCheckedItems.set(parent.value, data.checked);\n } else {\n // if one parent is mixed, all ancestors are mixed\n isAncestorsMixed = true;\n nextCheckedItems.set(parent.value, 'mixed');\n }\n }\n return ImmutableMap.dangerouslyCreate_unstable(nextCheckedItems);\n}\n\nfunction initializeCheckedItems(\n props: Pick<HeadlessFlatTreeOptions, 'selectionMode' | 'defaultCheckedItems'>,\n headlessTree: HeadlessTree<HeadlessTreeItemProps>,\n) {\n if (!props.selectionMode) {\n return ImmutableMap.empty;\n }\n let state = createCheckedItems(props.defaultCheckedItems);\n if (props.selectionMode === 'multiselect') {\n for (const [value, checked] of state) {\n state = createNextFlatCheckedItems({ value, checked, selectionMode: props.selectionMode }, state, headlessTree);\n }\n }\n return state;\n}\n"],"names":["useControllableState","ImmutableMap","React","createCheckedItems","useFlatControllableCheckedItems","props","headlessTree","initialState","empty","state","useMemo","selectionMode","checkedItems","undefined","defaultState","defaultCheckedItems","initializeCheckedItems","createNextFlatCheckedItems","data","previousCheckedItems","create","value","checked","treeItem","get","process","env","NODE_ENV","console","error","nextCheckedItems","Map","children","subtree","set","isAncestorsMixed","parent","ancestors","checkedChildren","child","push","length","childrenValues","dangerouslyCreate_unstable"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,SAASA,oBAAoB,QAAQ,4BAA4B;AAEjE,SAASC,YAAY,QAAQ,2BAA2B;AACxD,YAAYC,WAAW,QAAQ;AAE/B,SAASC,kBAAkB,QAAQ,iCAAiC;AAIpE,OAAO,SAASC,gCACdC,KAA8F,EAC9FC,YAAiC;IAEjC,OAAON,qBAAqB;QAC1BO,cAAcN,aAAaO,KAAK;QAChCC,OAAOP,MAAMQ,OAAO,CAClB,IAAOL,MAAMM,aAAa,GAAGN,MAAMO,YAAY,IAAIT,mBAAmBE,MAAMO,YAAY,IAAIC,WAC5F;YAACR,MAAMO,YAAY;YAAEP,MAAMM,aAAa;SAAC;QAE3CG,cAAcT,MAAMU,mBAAmB,GAAG,IAAMC,uBAAuBX,OAAOC,gBAAgBO;IAChG;AACF;AAEA,OAAO,SAASI,2BACdC,IAAwE,EACxEC,oBAAoE,EACpEb,YAAiD;IAEjD,IAAIY,KAAKP,aAAa,KAAK,UAAU;QACnC,OAAOV,aAAamB,MAAM,CAAC;YAAC;gBAACF,KAAKG,KAAK;gBAAEH,KAAKI,OAAO;aAAC;SAAC;IACzD;IACA,MAAMC,WAAWjB,aAAakB,GAAG,CAACN,KAAKG,KAAK;IAC5C,IAAI,CAACE,UAAU;QACb,IAAIE,QAAQC,GAAG,CAACC,QAAQ,KAAK,cAAc;YACzC,sCAAsC;YACtCC,QAAQC,KAAK,CAAsB,CAAC;UAExB,EAAEX,KAAKG,KAAK,CAAC,WACzB,CAAC;QACH;QACA,OAAOF;IACT;IACA,MAAMW,mBAAmB,IAAIC,IAAIZ;IACjC,KAAK,MAAMa,YAAY1B,aAAa2B,OAAO,CAACf,KAAKG,KAAK,EAAG;QACvDS,iBAAiBI,GAAG,CAACF,SAASX,KAAK,EAAEH,KAAKI,OAAO;IACnD;IACAQ,iBAAiBI,GAAG,CAAChB,KAAKG,KAAK,EAAEH,KAAKI,OAAO;IAE7C,IAAIa,mBAAmB;IACvB,KAAK,MAAMC,UAAU9B,aAAa+B,SAAS,CAACd,SAASF,KAAK,EAAG;QAC3D,kDAAkD;QAClD,IAAIc,kBAAkB;YACpBL,iBAAiBI,GAAG,CAACE,OAAOf,KAAK,EAAE;YACnC;QACF;QACA,MAAMiB,kBAAkB,EAAE;QAC1B,KAAK,MAAMC,SAASjC,aAAa0B,QAAQ,CAACI,OAAOf,KAAK,EAAG;gBAClDS;YAAL,IAAI,AAACA,CAAAA,CAAAA,wBAAAA,iBAAiBN,GAAG,CAACe,MAAMlB,KAAK,eAAhCS,mCAAAA,wBAAqC,KAAI,MAAOZ,KAAKI,OAAO,EAAE;gBACjEgB,gBAAgBE,IAAI,CAACD;YACvB;QACF;QACA,IAAID,gBAAgBG,MAAM,KAAKL,OAAOM,cAAc,CAACD,MAAM,EAAE;YAC3DX,iBAAiBI,GAAG,CAACE,OAAOf,KAAK,EAAEH,KAAKI,OAAO;QACjD,OAAO;YACL,kDAAkD;YAClDa,mBAAmB;YACnBL,iBAAiBI,GAAG,CAACE,OAAOf,KAAK,EAAE;QACrC;IACF;IACA,OAAOpB,aAAa0C,0BAA0B,CAACb;AACjD;AAEA,SAASd,uBACPX,KAA6E,EAC7EC,YAAiD;IAEjD,IAAI,CAACD,MAAMM,aAAa,EAAE;QACxB,OAAOV,aAAaO,KAAK;IAC3B;IACA,IAAIC,QAAQN,mBAAmBE,MAAMU,mBAAmB;IACxD,IAAIV,MAAMM,aAAa,KAAK,eAAe;QACzC,KAAK,MAAM,CAACU,OAAOC,QAAQ,IAAIb,MAAO;YACpCA,QAAQQ,2BAA2B;gBAAEI;gBAAOC;gBAASX,eAAeN,MAAMM,aAAa;YAAC,GAAGF,OAAOH;QACpG;IACF;IACA,OAAOG;AACT"}
1
+ {"version":3,"sources":["useFlatControllableCheckedItems.ts"],"sourcesContent":["import { useControllableState } from '@fluentui/react-utilities';\nimport { TreeItemValue } from '../../TreeItem';\nimport { ImmutableMap } from '../../utils/ImmutableMap';\nimport * as React from 'react';\nimport type { HeadlessTree, HeadlessTreeItemProps } from '../../utils/createHeadlessTree';\nimport { createCheckedItems } from '../../utils/createCheckedItems';\nimport type { TreeCheckedChangeData } from '../Tree/Tree.types';\nimport { HeadlessFlatTreeOptions } from './useHeadlessFlatTree';\n\nexport function useFlatControllableCheckedItems<Props extends HeadlessTreeItemProps>(\n props: Pick<HeadlessFlatTreeOptions, 'checkedItems' | 'defaultCheckedItems' | 'selectionMode'>,\n headlessTree: HeadlessTree<Props>,\n) {\n return useControllableState({\n initialState: ImmutableMap.empty,\n state: React.useMemo(\n () => (props.selectionMode ? props.checkedItems && createCheckedItems(props.checkedItems) : undefined),\n [props.checkedItems, props.selectionMode],\n ),\n defaultState: props.defaultCheckedItems ? () => initializeCheckedItems(props, headlessTree) : undefined,\n });\n}\n\nexport function createNextFlatCheckedItems(\n data: Pick<TreeCheckedChangeData, 'value' | 'checked' | 'selectionMode'>,\n previousCheckedItems: ImmutableMap<TreeItemValue, 'mixed' | boolean>,\n headlessTree: HeadlessTree<HeadlessTreeItemProps>,\n): ImmutableMap<TreeItemValue, 'mixed' | boolean> {\n if (data.selectionMode === 'single') {\n return ImmutableMap.from([[data.value, data.checked]]);\n }\n const treeItem = headlessTree.get(data.value);\n if (!treeItem) {\n if (process.env.NODE_ENV !== 'production') {\n // eslint-disable-next-line no-console\n console.error(/* #__DE-INDENT__ */ `\n @fluentui/react-tree [useHeadlessFlatTree]:\n Tree item ${data.value} not found.\n `);\n }\n return previousCheckedItems;\n }\n let nextCheckedItems = previousCheckedItems;\n for (const children of headlessTree.subtree(data.value)) {\n nextCheckedItems = nextCheckedItems.set(children.value, data.checked);\n }\n nextCheckedItems = nextCheckedItems.set(data.value, data.checked);\n\n let isAncestorsMixed = false;\n for (const parent of headlessTree.ancestors(treeItem.value)) {\n // if one parent is mixed, all ancestors are mixed\n if (isAncestorsMixed) {\n nextCheckedItems = nextCheckedItems.set(parent.value, 'mixed');\n continue;\n }\n let checkedChildrenAmount = 0;\n for (const child of headlessTree.children(parent.value)) {\n if ((nextCheckedItems.get(child.value) || false) === data.checked) {\n checkedChildrenAmount++;\n }\n }\n // if all children are checked, parent is checked\n if (checkedChildrenAmount === parent.childrenValues.length) {\n nextCheckedItems = nextCheckedItems.set(parent.value, data.checked);\n } else {\n // if one parent is mixed, all ancestors are mixed\n isAncestorsMixed = true;\n nextCheckedItems = nextCheckedItems.set(parent.value, 'mixed');\n }\n }\n return nextCheckedItems;\n}\n\nfunction initializeCheckedItems(\n props: Pick<HeadlessFlatTreeOptions, 'selectionMode' | 'defaultCheckedItems'>,\n headlessTree: HeadlessTree<HeadlessTreeItemProps>,\n) {\n if (!props.selectionMode) {\n return ImmutableMap.empty;\n }\n let state = createCheckedItems(props.defaultCheckedItems);\n // if selectionMode is multiselect, we need to calculate the checked state of all children\n // and ancestors of the defaultCheckedItems\n if (props.selectionMode === 'multiselect') {\n for (const [value, checked] of state) {\n state = createNextFlatCheckedItems({ value, checked, selectionMode: props.selectionMode }, state, headlessTree);\n }\n }\n return state;\n}\n"],"names":["useControllableState","ImmutableMap","React","createCheckedItems","useFlatControllableCheckedItems","props","headlessTree","initialState","empty","state","useMemo","selectionMode","checkedItems","undefined","defaultState","defaultCheckedItems","initializeCheckedItems","createNextFlatCheckedItems","data","previousCheckedItems","from","value","checked","treeItem","get","process","env","NODE_ENV","console","error","nextCheckedItems","children","subtree","set","isAncestorsMixed","parent","ancestors","checkedChildrenAmount","child","childrenValues","length"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,SAASA,oBAAoB,QAAQ,4BAA4B;AAEjE,SAASC,YAAY,QAAQ,2BAA2B;AACxD,YAAYC,WAAW,QAAQ;AAE/B,SAASC,kBAAkB,QAAQ,iCAAiC;AAIpE,OAAO,SAASC,gCACdC,KAA8F,EAC9FC,YAAiC;IAEjC,OAAON,qBAAqB;QAC1BO,cAAcN,aAAaO,KAAK;QAChCC,OAAOP,MAAMQ,OAAO,CAClB,IAAOL,MAAMM,aAAa,GAAGN,MAAMO,YAAY,IAAIT,mBAAmBE,MAAMO,YAAY,IAAIC,WAC5F;YAACR,MAAMO,YAAY;YAAEP,MAAMM,aAAa;SAAC;QAE3CG,cAAcT,MAAMU,mBAAmB,GAAG,IAAMC,uBAAuBX,OAAOC,gBAAgBO;IAChG;AACF;AAEA,OAAO,SAASI,2BACdC,IAAwE,EACxEC,oBAAoE,EACpEb,YAAiD;IAEjD,IAAIY,KAAKP,aAAa,KAAK,UAAU;QACnC,OAAOV,aAAamB,IAAI,CAAC;YAAC;gBAACF,KAAKG,KAAK;gBAAEH,KAAKI,OAAO;aAAC;SAAC;IACvD;IACA,MAAMC,WAAWjB,aAAakB,GAAG,CAACN,KAAKG,KAAK;IAC5C,IAAI,CAACE,UAAU;QACb,IAAIE,QAAQC,GAAG,CAACC,QAAQ,KAAK,cAAc;YACzC,sCAAsC;YACtCC,QAAQC,KAAK,CAAsB,CAAC;UAExB,EAAEX,KAAKG,KAAK,CAAC,WACzB,CAAC;QACH;QACA,OAAOF;IACT;IACA,IAAIW,mBAAmBX;IACvB,KAAK,MAAMY,YAAYzB,aAAa0B,OAAO,CAACd,KAAKG,KAAK,EAAG;QACvDS,mBAAmBA,iBAAiBG,GAAG,CAACF,SAASV,KAAK,EAAEH,KAAKI,OAAO;IACtE;IACAQ,mBAAmBA,iBAAiBG,GAAG,CAACf,KAAKG,KAAK,EAAEH,KAAKI,OAAO;IAEhE,IAAIY,mBAAmB;IACvB,KAAK,MAAMC,UAAU7B,aAAa8B,SAAS,CAACb,SAASF,KAAK,EAAG;QAC3D,kDAAkD;QAClD,IAAIa,kBAAkB;YACpBJ,mBAAmBA,iBAAiBG,GAAG,CAACE,OAAOd,KAAK,EAAE;YACtD;QACF;QACA,IAAIgB,wBAAwB;QAC5B,KAAK,MAAMC,SAAShC,aAAayB,QAAQ,CAACI,OAAOd,KAAK,EAAG;YACvD,IAAI,AAACS,CAAAA,iBAAiBN,GAAG,CAACc,MAAMjB,KAAK,KAAK,KAAI,MAAOH,KAAKI,OAAO,EAAE;gBACjEe;YACF;QACF;QACA,iDAAiD;QACjD,IAAIA,0BAA0BF,OAAOI,cAAc,CAACC,MAAM,EAAE;YAC1DV,mBAAmBA,iBAAiBG,GAAG,CAACE,OAAOd,KAAK,EAAEH,KAAKI,OAAO;QACpE,OAAO;YACL,kDAAkD;YAClDY,mBAAmB;YACnBJ,mBAAmBA,iBAAiBG,GAAG,CAACE,OAAOd,KAAK,EAAE;QACxD;IACF;IACA,OAAOS;AACT;AAEA,SAASd,uBACPX,KAA6E,EAC7EC,YAAiD;IAEjD,IAAI,CAACD,MAAMM,aAAa,EAAE;QACxB,OAAOV,aAAaO,KAAK;IAC3B;IACA,IAAIC,QAAQN,mBAAmBE,MAAMU,mBAAmB;IACxD,0FAA0F;IAC1F,2CAA2C;IAC3C,IAAIV,MAAMM,aAAa,KAAK,eAAe;QACzC,KAAK,MAAM,CAACU,OAAOC,QAAQ,IAAIb,MAAO;YACpCA,QAAQQ,2BAA2B;gBAAEI;gBAAOC;gBAASX,eAAeN,MAAMM,aAAa;YAAC,GAAGF,OAAOH;QACpG;IACF;IACA,OAAOG;AACT"}
@@ -5,7 +5,9 @@ import { treeDataTypes } from '../../utils/tokens';
5
5
  import { useFlatTreeNavigation } from '../../hooks/useFlatTreeNavigation';
6
6
  import { createNextOpenItems, useControllableOpenItems } from '../../hooks/useControllableOpenItems';
7
7
  import { dataTreeItemValueAttrName } from '../../utils/getTreeItemValueFromElement';
8
+ import { ImmutableSet } from '../../utils/ImmutableSet';
8
9
  import { createNextFlatCheckedItems, useFlatControllableCheckedItems } from './useFlatControllableCheckedItems';
10
+ import { ImmutableMap } from '../../utils/ImmutableMap';
9
11
  /**
10
12
  * this hook provides FlatTree API to manage all required mechanisms to convert a list of items into renderable TreeItems
11
13
  * in multiple scenarios including virtualization.
@@ -31,7 +33,7 @@ import { createNextFlatCheckedItems, useFlatControllableCheckedItems } from './u
31
33
  const nextOpenItems = createNextOpenItems(data, openItems);
32
34
  (_options_onOpenChange = options.onOpenChange) === null || _options_onOpenChange === void 0 ? void 0 : _options_onOpenChange.call(options, event, {
33
35
  ...data,
34
- openItems: nextOpenItems.dangerouslyGetInternalSet_unstable()
36
+ openItems: ImmutableSet.dangerouslyGetInternalSet(nextOpenItems)
35
37
  });
36
38
  setOpenItems(nextOpenItems);
37
39
  });
@@ -40,7 +42,7 @@ import { createNextFlatCheckedItems, useFlatControllableCheckedItems } from './u
40
42
  const nextCheckedItems = createNextFlatCheckedItems(data, checkedItems, headlessTree);
41
43
  (_options_onCheckedChange = options.onCheckedChange) === null || _options_onCheckedChange === void 0 ? void 0 : _options_onCheckedChange.call(options, event, {
42
44
  ...data,
43
- checkedItems: nextCheckedItems.dangerouslyGetInternalMap_unstable()
45
+ checkedItems: ImmutableMap.dangerouslyGetInternalMap(nextCheckedItems)
44
46
  });
45
47
  setCheckedItems(nextCheckedItems);
46
48
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["useHeadlessFlatTree.ts"],"sourcesContent":["import { useEventCallback, useMergedRefs } from '@fluentui/react-utilities';\nimport * as React from 'react';\nimport { HeadlessTreeItem, HeadlessTreeItemProps, createHeadlessTree } from '../../utils/createHeadlessTree';\nimport { treeDataTypes } from '../../utils/tokens';\nimport { useFlatTreeNavigation } from '../../hooks/useFlatTreeNavigation';\nimport { createNextOpenItems, useControllableOpenItems } from '../../hooks/useControllableOpenItems';\nimport type { TreeItemValue } from '../../TreeItem';\nimport { dataTreeItemValueAttrName } from '../../utils/getTreeItemValueFromElement';\nimport { ImmutableSet } from '../../utils/ImmutableSet';\nimport { createNextFlatCheckedItems, useFlatControllableCheckedItems } from './useFlatControllableCheckedItems';\nimport { FlatTreeProps } from './FlatTree.types';\nimport {\n TreeCheckedChangeData,\n TreeCheckedChangeEvent,\n TreeNavigationData_unstable,\n TreeOpenChangeData,\n TreeOpenChangeEvent,\n TreeProps,\n} from '../Tree/Tree.types';\n\nexport type HeadlessFlatTreeItemProps = HeadlessTreeItemProps;\nexport type HeadlessFlatTreeItem<Props extends HeadlessFlatTreeItemProps> = HeadlessTreeItem<Props>;\n\n/**\n * FlatTree API to manage all required mechanisms to convert a list of items into renderable TreeItems\n * in multiple scenarios including virtualization.\n *\n * !!A flat tree is an unofficial spec for tree!!\n *\n * It should be used on cases where more complex interactions with a Tree is required.\n *\n * On simple scenarios it is advised to simply use a nested structure instead.\n */\nexport type HeadlessFlatTree<Props extends HeadlessFlatTreeItemProps> = {\n /**\n * returns the properties required for the Tree component to work properly.\n * That includes:\n * `openItems`, `onOpenChange`, `onNavigation_unstable` and `ref`\n */\n getTreeProps(): Required<\n Pick<FlatTreeProps, 'openItems' | 'onOpenChange' | 'onNavigation' | 'checkedItems' | 'onCheckedChange'>\n > & {\n ref: React.Ref<HTMLDivElement>;\n openItems: ImmutableSet<TreeItemValue>;\n };\n /**\n * internal method used to react to an `onNavigation` event.\n * This method ensures proper navigation on keyboard and mouse interaction.\n * In case of virtualization it might be required to cancel default provided `onNavigation`\n * event and then call this method manually.\n *\n * @example\n * ```ts\n * // react-window\n * const handleNavigation = (event, data) => {\n * event.preventDefault();\n * const nextItem = tree.getNextNavigableItem(data);\n * // scroll to item using virtualization scroll mechanism\n * if (nextItem && tree.getElementFromItem(nextItem)) {\n * listRef.current.scrollToItem(nextItem.index);\n * }\n * // wait for scrolling to happen and then invoke navigate method\n * requestAnimationFrame(() => {\n * tree.navigate(data);\n * });\n * };\n *```\n */\n navigate(data: TreeNavigationData_unstable): void;\n /**\n * returns next item to be focused on a navigation.\n * This method is provided to decouple the element that needs to be focused from\n * the action of focusing it itself.\n *\n * On the case of TypeAhead navigation this method returns the current item.\n */\n getNextNavigableItem(\n visibleItems: HeadlessTreeItem<Props>[],\n data: TreeNavigationData_unstable,\n ): HeadlessTreeItem<Props> | undefined;\n /**\n * similar to getElementById but for FlatTreeItems\n */\n getElementFromItem(item: HeadlessTreeItem<Props>): HTMLElement | null;\n /**\n * an iterable containing all visually available flat tree items\n */\n items(): IterableIterator<HeadlessTreeItem<Props>>;\n};\n\nexport type HeadlessFlatTreeOptions = Pick<\n FlatTreeProps,\n 'onOpenChange' | 'onNavigation' | 'selectionMode' | 'onCheckedChange'\n> &\n Pick<TreeProps, 'defaultOpenItems' | 'openItems' | 'checkedItems'> & {\n defaultCheckedItems?: TreeProps['checkedItems'];\n };\n\n/**\n * @internal\n */\ntype HeadlessFlatTreeReturn<Props extends HeadlessFlatTreeItemProps> = HeadlessFlatTree<Props> & {\n getItem(value: TreeItemValue): HeadlessTreeItem<Props> | undefined;\n};\n\n/**\n * this hook provides FlatTree API to manage all required mechanisms to convert a list of items into renderable TreeItems\n * in multiple scenarios including virtualization.\n *\n * !!A flat tree is an unofficial spec for tree!!\n *\n * It should be used on cases where more complex interactions with a Tree is required.\n * On simple scenarios it is advised to simply use a nested structure instead.\n *\n * @param props - a list of tree items\n * @param options - in case control over the internal openItems is required\n */\nexport function useHeadlessFlatTree_unstable<Props extends HeadlessTreeItemProps>(\n props: Props[],\n options: HeadlessFlatTreeOptions = {},\n): HeadlessFlatTreeReturn<Props> {\n 'use no memo';\n\n const headlessTree = React.useMemo(() => createHeadlessTree(props), [props]);\n const [openItems, setOpenItems] = useControllableOpenItems(options);\n const [checkedItems, setCheckedItems] = useFlatControllableCheckedItems(options, headlessTree);\n const navigation = useFlatTreeNavigation();\n\n const treeRef = React.useRef<HTMLDivElement>(null);\n const handleOpenChange = useEventCallback((event: TreeOpenChangeEvent, data: TreeOpenChangeData) => {\n const nextOpenItems = createNextOpenItems(data, openItems);\n options.onOpenChange?.(event, {\n ...data,\n openItems: nextOpenItems.dangerouslyGetInternalSet_unstable(),\n });\n setOpenItems(nextOpenItems);\n });\n\n const handleCheckedChange = useEventCallback((event: TreeCheckedChangeEvent, data: TreeCheckedChangeData) => {\n const nextCheckedItems = createNextFlatCheckedItems(data, checkedItems, headlessTree);\n options.onCheckedChange?.(event, {\n ...data,\n checkedItems: nextCheckedItems.dangerouslyGetInternalMap_unstable(),\n });\n setCheckedItems(nextCheckedItems);\n });\n\n const getNextNavigableItem = useEventCallback(\n (visibleItems: HeadlessTreeItem<Props>[], data: TreeNavigationData_unstable) => {\n const item = headlessTree.get(data.value);\n if (item) {\n switch (data.type) {\n case treeDataTypes.TypeAhead:\n return item;\n case treeDataTypes.ArrowLeft:\n return headlessTree.get(item.parentValue!);\n case treeDataTypes.ArrowRight:\n return visibleItems[item.index + 1];\n case treeDataTypes.End:\n return visibleItems[visibleItems.length - 1];\n case treeDataTypes.Home:\n return visibleItems[0];\n case treeDataTypes.ArrowDown:\n return visibleItems[item.index + 1];\n case treeDataTypes.ArrowUp:\n return visibleItems[item.index - 1];\n }\n }\n },\n );\n\n const getElementFromItem = React.useCallback((item: HeadlessTreeItem<Props>) => {\n return treeRef.current?.querySelector(`[${dataTreeItemValueAttrName}=\"${item.value}\"]`) as HTMLElement | null;\n }, []);\n\n const ref = useMergedRefs<HTMLDivElement>(treeRef, navigation.rootRef);\n\n const getTreeProps = React.useCallback(\n () => ({\n ref,\n openItems,\n selectionMode: options.selectionMode,\n checkedItems,\n onOpenChange: handleOpenChange,\n onCheckedChange: handleCheckedChange,\n onNavigation: options.onNavigation ?? noop,\n }),\n // ref, handleOpenChange - useEventCallback, handleCheckedChange - useEventCallback\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [openItems, checkedItems, options.selectionMode, options.onNavigation],\n );\n\n const items = React.useCallback(() => headlessTree.visibleItems(openItems), [openItems, headlessTree]);\n\n const getItem = React.useCallback((value: TreeItemValue) => headlessTree.get(value), [headlessTree]);\n\n return React.useMemo<HeadlessFlatTreeReturn<Props>>(\n () => ({\n navigate: navigation.navigate,\n getTreeProps,\n getNextNavigableItem,\n getElementFromItem,\n items,\n getItem,\n }),\n [navigation.navigate, getTreeProps, getNextNavigableItem, getElementFromItem, items, getItem],\n );\n}\n\n/** @internal */\nfunction noop() {\n /* noop */\n}\n"],"names":["useEventCallback","useMergedRefs","React","createHeadlessTree","treeDataTypes","useFlatTreeNavigation","createNextOpenItems","useControllableOpenItems","dataTreeItemValueAttrName","createNextFlatCheckedItems","useFlatControllableCheckedItems","useHeadlessFlatTree_unstable","props","options","headlessTree","useMemo","openItems","setOpenItems","checkedItems","setCheckedItems","navigation","treeRef","useRef","handleOpenChange","event","data","nextOpenItems","onOpenChange","dangerouslyGetInternalSet_unstable","handleCheckedChange","nextCheckedItems","onCheckedChange","dangerouslyGetInternalMap_unstable","getNextNavigableItem","visibleItems","item","get","value","type","TypeAhead","ArrowLeft","parentValue","ArrowRight","index","End","length","Home","ArrowDown","ArrowUp","getElementFromItem","useCallback","current","querySelector","ref","rootRef","getTreeProps","selectionMode","onNavigation","noop","items","getItem","navigate"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
1
+ {"version":3,"sources":["useHeadlessFlatTree.ts"],"sourcesContent":["import { useEventCallback, useMergedRefs } from '@fluentui/react-utilities';\nimport * as React from 'react';\nimport { HeadlessTreeItem, HeadlessTreeItemProps, createHeadlessTree } from '../../utils/createHeadlessTree';\nimport { treeDataTypes } from '../../utils/tokens';\nimport { useFlatTreeNavigation } from '../../hooks/useFlatTreeNavigation';\nimport { createNextOpenItems, useControllableOpenItems } from '../../hooks/useControllableOpenItems';\nimport type { TreeItemValue } from '../../TreeItem';\nimport { dataTreeItemValueAttrName } from '../../utils/getTreeItemValueFromElement';\nimport { ImmutableSet } from '../../utils/ImmutableSet';\nimport { createNextFlatCheckedItems, useFlatControllableCheckedItems } from './useFlatControllableCheckedItems';\nimport { FlatTreeProps } from './FlatTree.types';\nimport {\n TreeCheckedChangeData,\n TreeCheckedChangeEvent,\n TreeNavigationData_unstable,\n TreeOpenChangeData,\n TreeOpenChangeEvent,\n TreeProps,\n} from '../Tree/Tree.types';\nimport { ImmutableMap } from '../../utils/ImmutableMap';\n\nexport type HeadlessFlatTreeItemProps = HeadlessTreeItemProps;\nexport type HeadlessFlatTreeItem<Props extends HeadlessFlatTreeItemProps> = HeadlessTreeItem<Props>;\n\n/**\n * FlatTree API to manage all required mechanisms to convert a list of items into renderable TreeItems\n * in multiple scenarios including virtualization.\n *\n * !!A flat tree is an unofficial spec for tree!!\n *\n * It should be used on cases where more complex interactions with a Tree is required.\n *\n * On simple scenarios it is advised to simply use a nested structure instead.\n */\nexport type HeadlessFlatTree<Props extends HeadlessFlatTreeItemProps> = {\n /**\n * returns the properties required for the Tree component to work properly.\n * That includes:\n * `openItems`, `onOpenChange`, `onNavigation_unstable` and `ref`\n */\n getTreeProps(): Required<\n Pick<FlatTreeProps, 'openItems' | 'onOpenChange' | 'onNavigation' | 'checkedItems' | 'onCheckedChange'>\n > & {\n ref: React.Ref<HTMLDivElement>;\n openItems: ImmutableSet<TreeItemValue>;\n };\n /**\n * internal method used to react to an `onNavigation` event.\n * This method ensures proper navigation on keyboard and mouse interaction.\n * In case of virtualization it might be required to cancel default provided `onNavigation`\n * event and then call this method manually.\n *\n * @example\n * ```ts\n * // react-window\n * const handleNavigation = (event, data) => {\n * event.preventDefault();\n * const nextItem = tree.getNextNavigableItem(data);\n * // scroll to item using virtualization scroll mechanism\n * if (nextItem && tree.getElementFromItem(nextItem)) {\n * listRef.current.scrollToItem(nextItem.index);\n * }\n * // wait for scrolling to happen and then invoke navigate method\n * requestAnimationFrame(() => {\n * tree.navigate(data);\n * });\n * };\n *```\n */\n navigate(data: TreeNavigationData_unstable): void;\n /**\n * returns next item to be focused on a navigation.\n * This method is provided to decouple the element that needs to be focused from\n * the action of focusing it itself.\n *\n * On the case of TypeAhead navigation this method returns the current item.\n */\n getNextNavigableItem(\n visibleItems: HeadlessTreeItem<Props>[],\n data: TreeNavigationData_unstable,\n ): HeadlessTreeItem<Props> | undefined;\n /**\n * similar to getElementById but for FlatTreeItems\n */\n getElementFromItem(item: HeadlessTreeItem<Props>): HTMLElement | null;\n /**\n * an iterable containing all visually available flat tree items\n */\n items(): IterableIterator<HeadlessTreeItem<Props>>;\n};\n\nexport type HeadlessFlatTreeOptions = Pick<\n FlatTreeProps,\n 'onOpenChange' | 'onNavigation' | 'selectionMode' | 'onCheckedChange'\n> &\n Pick<TreeProps, 'defaultOpenItems' | 'openItems' | 'checkedItems'> & {\n defaultCheckedItems?: TreeProps['checkedItems'];\n };\n\n/**\n * @internal\n */\ntype HeadlessFlatTreeReturn<Props extends HeadlessFlatTreeItemProps> = HeadlessFlatTree<Props> & {\n getItem(value: TreeItemValue): HeadlessTreeItem<Props> | undefined;\n};\n\n/**\n * this hook provides FlatTree API to manage all required mechanisms to convert a list of items into renderable TreeItems\n * in multiple scenarios including virtualization.\n *\n * !!A flat tree is an unofficial spec for tree!!\n *\n * It should be used on cases where more complex interactions with a Tree is required.\n * On simple scenarios it is advised to simply use a nested structure instead.\n *\n * @param props - a list of tree items\n * @param options - in case control over the internal openItems is required\n */\nexport function useHeadlessFlatTree_unstable<Props extends HeadlessTreeItemProps>(\n props: Props[],\n options: HeadlessFlatTreeOptions = {},\n): HeadlessFlatTreeReturn<Props> {\n 'use no memo';\n\n const headlessTree = React.useMemo(() => createHeadlessTree(props), [props]);\n const [openItems, setOpenItems] = useControllableOpenItems(options);\n const [checkedItems, setCheckedItems] = useFlatControllableCheckedItems(options, headlessTree);\n const navigation = useFlatTreeNavigation();\n\n const treeRef = React.useRef<HTMLDivElement>(null);\n const handleOpenChange = useEventCallback((event: TreeOpenChangeEvent, data: TreeOpenChangeData) => {\n const nextOpenItems = createNextOpenItems(data, openItems);\n options.onOpenChange?.(event, {\n ...data,\n openItems: ImmutableSet.dangerouslyGetInternalSet(nextOpenItems),\n });\n setOpenItems(nextOpenItems);\n });\n\n const handleCheckedChange = useEventCallback((event: TreeCheckedChangeEvent, data: TreeCheckedChangeData) => {\n const nextCheckedItems = createNextFlatCheckedItems(data, checkedItems, headlessTree);\n options.onCheckedChange?.(event, {\n ...data,\n checkedItems: ImmutableMap.dangerouslyGetInternalMap(nextCheckedItems),\n });\n setCheckedItems(nextCheckedItems);\n });\n\n const getNextNavigableItem = useEventCallback(\n (visibleItems: HeadlessTreeItem<Props>[], data: TreeNavigationData_unstable) => {\n const item = headlessTree.get(data.value);\n if (item) {\n switch (data.type) {\n case treeDataTypes.TypeAhead:\n return item;\n case treeDataTypes.ArrowLeft:\n return headlessTree.get(item.parentValue!);\n case treeDataTypes.ArrowRight:\n return visibleItems[item.index + 1];\n case treeDataTypes.End:\n return visibleItems[visibleItems.length - 1];\n case treeDataTypes.Home:\n return visibleItems[0];\n case treeDataTypes.ArrowDown:\n return visibleItems[item.index + 1];\n case treeDataTypes.ArrowUp:\n return visibleItems[item.index - 1];\n }\n }\n },\n );\n\n const getElementFromItem = React.useCallback((item: HeadlessTreeItem<Props>) => {\n return treeRef.current?.querySelector(`[${dataTreeItemValueAttrName}=\"${item.value}\"]`) as HTMLElement | null;\n }, []);\n\n const ref = useMergedRefs<HTMLDivElement>(treeRef, navigation.rootRef);\n\n const getTreeProps = React.useCallback(\n () => ({\n ref,\n openItems,\n selectionMode: options.selectionMode,\n checkedItems,\n onOpenChange: handleOpenChange,\n onCheckedChange: handleCheckedChange,\n onNavigation: options.onNavigation ?? noop,\n }),\n // ref, handleOpenChange - useEventCallback, handleCheckedChange - useEventCallback\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [openItems, checkedItems, options.selectionMode, options.onNavigation],\n );\n\n const items = React.useCallback(() => headlessTree.visibleItems(openItems), [openItems, headlessTree]);\n\n const getItem = React.useCallback((value: TreeItemValue) => headlessTree.get(value), [headlessTree]);\n\n return React.useMemo<HeadlessFlatTreeReturn<Props>>(\n () => ({\n navigate: navigation.navigate,\n getTreeProps,\n getNextNavigableItem,\n getElementFromItem,\n items,\n getItem,\n }),\n [navigation.navigate, getTreeProps, getNextNavigableItem, getElementFromItem, items, getItem],\n );\n}\n\n/** @internal */\nfunction noop() {\n /* noop */\n}\n"],"names":["useEventCallback","useMergedRefs","React","createHeadlessTree","treeDataTypes","useFlatTreeNavigation","createNextOpenItems","useControllableOpenItems","dataTreeItemValueAttrName","ImmutableSet","createNextFlatCheckedItems","useFlatControllableCheckedItems","ImmutableMap","useHeadlessFlatTree_unstable","props","options","headlessTree","useMemo","openItems","setOpenItems","checkedItems","setCheckedItems","navigation","treeRef","useRef","handleOpenChange","event","data","nextOpenItems","onOpenChange","dangerouslyGetInternalSet","handleCheckedChange","nextCheckedItems","onCheckedChange","dangerouslyGetInternalMap","getNextNavigableItem","visibleItems","item","get","value","type","TypeAhead","ArrowLeft","parentValue","ArrowRight","index","End","length","Home","ArrowDown","ArrowUp","getElementFromItem","useCallback","current","querySelector","ref","rootRef","getTreeProps","selectionMode","onNavigation","noop","items","getItem","navigate"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["Tree.types.ts"],"sourcesContent":["import type * as React from 'react';\nimport type { ComponentProps, ComponentState, SelectionMode, Slot } from '@fluentui/react-utilities';\nimport type { TreeContextValue, SubtreeContextValue } from '../../contexts';\nimport type { ArrowDown, ArrowLeft, ArrowRight, ArrowUp, End, Enter, Home } from '@fluentui/keyboard-keys';\nimport type { TreeItemValue } from '../TreeItem/TreeItem.types';\nimport { CheckboxProps } from '@fluentui/react-checkbox';\nimport { RadioProps } from '@fluentui/react-radio';\n\ntype MultiSelectValue = NonNullable<CheckboxProps['checked']>;\ntype SingleSelectValue = NonNullable<RadioProps['checked']>;\nexport type TreeSelectionValue = MultiSelectValue | SingleSelectValue;\n\nexport type TreeSlots = {\n root: Slot<'div'>;\n};\n\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport type TreeNavigationData_unstable = {\n target: HTMLElement;\n value: TreeItemValue;\n parentValue: TreeItemValue | undefined;\n} & (\n | { event: React.MouseEvent<HTMLElement>; type: 'Click' }\n | { event: React.KeyboardEvent<HTMLElement>; type: 'TypeAhead' }\n | { event: React.KeyboardEvent<HTMLElement>; type: typeof ArrowRight }\n | { event: React.KeyboardEvent<HTMLElement>; type: typeof ArrowLeft }\n | { event: React.KeyboardEvent<HTMLElement>; type: typeof ArrowUp }\n | { event: React.KeyboardEvent<HTMLElement>; type: typeof ArrowDown }\n | { event: React.KeyboardEvent<HTMLElement>; type: typeof Home }\n | { event: React.KeyboardEvent<HTMLElement>; type: typeof End }\n);\n\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport type TreeNavigationEvent_unstable = TreeNavigationData_unstable['event'];\n\nexport type TreeOpenChangeData = {\n open: boolean;\n openItems: Set<TreeItemValue>;\n value: TreeItemValue;\n target: HTMLElement;\n} & (\n | { event: React.MouseEvent<HTMLElement>; type: 'ExpandIconClick' }\n | { event: React.MouseEvent<HTMLElement>; type: 'Click' }\n /**\n * @deprecated\n * Use `type: 'Click'` instead of Enter,\n * an enter press will trigger a click event, which will trigger an open change,\n * so there is no need to have a separate type for it.\n */\n | { event: React.KeyboardEvent<HTMLElement>; type: typeof Enter }\n | { event: React.KeyboardEvent<HTMLElement>; type: typeof ArrowRight }\n | { event: React.KeyboardEvent<HTMLElement>; type: typeof ArrowLeft }\n);\n\n/**\n * @internal\n *\n * To avoid breaking changes on TreeNavigationData\n * we are creating a new type that extends the old one\n * and adds the new methods, and this type will not be exported\n */\ntype TreeNavigationDataParam = TreeNavigationData_unstable & {\n preventScroll(): void;\n isScrollPrevented(): boolean;\n};\n\nexport type TreeOpenChangeEvent = TreeOpenChangeData['event'];\n\nexport type TreeCheckedChangeData = {\n value: TreeItemValue;\n checkedItems: Map<TreeItemValue, TreeSelectionValue>;\n target: HTMLElement;\n event: React.ChangeEvent<HTMLElement>;\n type: 'Change';\n} & (\n | {\n selectionMode: 'multiselect';\n checked: MultiSelectValue;\n }\n | {\n selectionMode: 'single';\n checked: SingleSelectValue;\n }\n);\n\nexport type TreeCheckedChangeEvent = TreeCheckedChangeData['event'];\n\nexport type TreeContextValues = {\n tree: TreeContextValue | SubtreeContextValue;\n};\n\nexport type TreeProps = ComponentProps<TreeSlots> & {\n /**\n * A tree item can have various appearances:\n * - 'subtle' (default): The default tree item styles.\n * - 'subtle-alpha': Minimizes emphasis on hovered or focused states.\n * - 'transparent': Removes background color.\n * @default 'subtle'\n */\n appearance?: 'subtle' | 'subtle-alpha' | 'transparent';\n /**\n * Size of the tree item.\n * @default 'medium'\n */\n size?: 'small' | 'medium';\n /**\n * This refers to a list of ids of opened tree items.\n * Controls the state of the open tree items.\n * These property is ignored for subtrees.\n */\n openItems?: Iterable<TreeItemValue>;\n /**\n * This refers to a list of ids of default opened items.\n * This property is ignored for subtrees.\n */\n defaultOpenItems?: Iterable<TreeItemValue>;\n /**\n * Callback fired when the component changes value from open state.\n * These property is ignored for subtrees.\n *\n * @param event - a React's Synthetic event\n * @param data - A data object with relevant information,\n * such as open value and type of interaction that created the event.\n */\n onOpenChange?(event: TreeOpenChangeEvent, data: TreeOpenChangeData): void;\n\n /**\n * Callback fired when navigation happens inside the component.\n * These property is ignored for subtrees.\n *\n * FIXME: This method is not ideal, as navigation should be handled internally by tabster.\n *\n * @param event - a React's Synthetic event\n * @param data - A data object with relevant information,\n */\n onNavigation?(event: TreeNavigationEvent_unstable, data: TreeNavigationDataParam): void;\n\n /**\n * This refers to the selection mode of the tree.\n * - undefined: No selection can be done.\n * - 'single': Only one tree item can be selected, radio buttons are rendered.\n * - 'multiselect': Multiple tree items can be selected, checkboxes are rendered.\n *\n * @default undefined\n */\n selectionMode?: SelectionMode;\n /**\n * This refers to a list of ids of checked tree items, or a list of tuples of ids and checked state.\n * Controls the state of the checked tree items.\n * These property is ignored for subtrees.\n */\n checkedItems?: Iterable<TreeItemValue | [TreeItemValue, TreeSelectionValue]>;\n /**\n * Callback fired when the component changes value from checked state.\n * These property is ignored for subtrees.\n *\n * @param event - a React's Synthetic event\n * @param data - A data object with relevant information,\n * such as checked value and type of interaction that created the event.\n */\n onCheckedChange?(event: TreeCheckedChangeEvent, data: TreeCheckedChangeData): void;\n};\n\n/**\n * State used in rendering Tree\n */\nexport type TreeState = ComponentState<TreeSlots> & {\n open: boolean;\n} & (TreeContextValue | SubtreeContextValue);\n"],"names":[],"rangeMappings":";;","mappings":"AAmKA;;CAEC,GACD,WAE6C"}
1
+ {"version":3,"sources":["Tree.types.ts"],"sourcesContent":["import type * as React from 'react';\nimport type { PresenceMotionSlotProps } from '@fluentui/react-motion';\nimport type { ComponentProps, ComponentState, SelectionMode, Slot } from '@fluentui/react-utilities';\nimport type { TreeContextValue, SubtreeContextValue } from '../../contexts';\nimport type { ArrowDown, ArrowLeft, ArrowRight, ArrowUp, End, Enter, Home } from '@fluentui/keyboard-keys';\nimport type { TreeItemValue } from '../TreeItem/TreeItem.types';\nimport { CheckboxProps } from '@fluentui/react-checkbox';\nimport { RadioProps } from '@fluentui/react-radio';\n\ntype MultiSelectValue = NonNullable<CheckboxProps['checked']>;\ntype SingleSelectValue = NonNullable<RadioProps['checked']>;\nexport type TreeSelectionValue = MultiSelectValue | SingleSelectValue;\n\nexport type TreeSlots = {\n root: Slot<'div'>;\n collapseMotion?: Slot<PresenceMotionSlotProps>;\n};\n\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport type TreeNavigationData_unstable = {\n target: HTMLElement;\n value: TreeItemValue;\n parentValue: TreeItemValue | undefined;\n} & (\n | { event: React.MouseEvent<HTMLElement>; type: 'Click' }\n | { event: React.KeyboardEvent<HTMLElement>; type: 'TypeAhead' }\n | { event: React.KeyboardEvent<HTMLElement>; type: typeof ArrowRight }\n | { event: React.KeyboardEvent<HTMLElement>; type: typeof ArrowLeft }\n | { event: React.KeyboardEvent<HTMLElement>; type: typeof ArrowUp }\n | { event: React.KeyboardEvent<HTMLElement>; type: typeof ArrowDown }\n | { event: React.KeyboardEvent<HTMLElement>; type: typeof Home }\n | { event: React.KeyboardEvent<HTMLElement>; type: typeof End }\n);\n\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport type TreeNavigationEvent_unstable = TreeNavigationData_unstable['event'];\n\nexport type TreeOpenChangeData = {\n open: boolean;\n openItems: Set<TreeItemValue>;\n value: TreeItemValue;\n target: HTMLElement;\n} & (\n | { event: React.MouseEvent<HTMLElement>; type: 'ExpandIconClick' }\n | { event: React.MouseEvent<HTMLElement>; type: 'Click' }\n /**\n * @deprecated\n * Use `type: 'Click'` instead of Enter,\n * an enter press will trigger a click event, which will trigger an open change,\n * so there is no need to have a separate type for it.\n */\n | { event: React.KeyboardEvent<HTMLElement>; type: typeof Enter }\n | { event: React.KeyboardEvent<HTMLElement>; type: typeof ArrowRight }\n | { event: React.KeyboardEvent<HTMLElement>; type: typeof ArrowLeft }\n);\n\n/**\n * @internal\n *\n * To avoid breaking changes on TreeNavigationData\n * we are creating a new type that extends the old one\n * and adds the new methods, and this type will not be exported\n */\ntype TreeNavigationDataParam = TreeNavigationData_unstable & {\n preventScroll(): void;\n isScrollPrevented(): boolean;\n};\n\nexport type TreeOpenChangeEvent = TreeOpenChangeData['event'];\n\nexport type TreeCheckedChangeData = {\n value: TreeItemValue;\n checkedItems: Map<TreeItemValue, TreeSelectionValue>;\n target: HTMLElement;\n event: React.ChangeEvent<HTMLElement>;\n type: 'Change';\n} & (\n | {\n selectionMode: 'multiselect';\n checked: MultiSelectValue;\n }\n | {\n selectionMode: 'single';\n checked: SingleSelectValue;\n }\n);\n\nexport type TreeCheckedChangeEvent = TreeCheckedChangeData['event'];\n\nexport type TreeContextValues = {\n tree: TreeContextValue | SubtreeContextValue;\n};\n\nexport type TreeProps = ComponentProps<TreeSlots> & {\n /**\n * A tree item can have various appearances:\n * - 'subtle' (default): The default tree item styles.\n * - 'subtle-alpha': Minimizes emphasis on hovered or focused states.\n * - 'transparent': Removes background color.\n * @default 'subtle'\n */\n appearance?: 'subtle' | 'subtle-alpha' | 'transparent';\n /**\n * Size of the tree item.\n * @default 'medium'\n */\n size?: 'small' | 'medium';\n /**\n * This refers to a list of ids of opened tree items.\n * Controls the state of the open tree items.\n * These property is ignored for subtrees.\n */\n openItems?: Iterable<TreeItemValue>;\n /**\n * This refers to a list of ids of default opened items.\n * This property is ignored for subtrees.\n */\n defaultOpenItems?: Iterable<TreeItemValue>;\n /**\n * Callback fired when the component changes value from open state.\n * These property is ignored for subtrees.\n *\n * @param event - a React's Synthetic event\n * @param data - A data object with relevant information,\n * such as open value and type of interaction that created the event.\n */\n onOpenChange?(event: TreeOpenChangeEvent, data: TreeOpenChangeData): void;\n\n /**\n * Callback fired when navigation happens inside the component.\n * These property is ignored for subtrees.\n *\n * FIXME: This method is not ideal, as navigation should be handled internally by tabster.\n *\n * @param event - a React's Synthetic event\n * @param data - A data object with relevant information,\n */\n onNavigation?(event: TreeNavigationEvent_unstable, data: TreeNavigationDataParam): void;\n\n /**\n * This refers to the selection mode of the tree.\n * - undefined: No selection can be done.\n * - 'single': Only one tree item can be selected, radio buttons are rendered.\n * - 'multiselect': Multiple tree items can be selected, checkboxes are rendered.\n *\n * @default undefined\n */\n selectionMode?: SelectionMode;\n /**\n * This refers to a list of ids of checked tree items, or a list of tuples of ids and checked state.\n * Controls the state of the checked tree items.\n * These property is ignored for subtrees.\n */\n checkedItems?: Iterable<TreeItemValue | [TreeItemValue, TreeSelectionValue]>;\n /**\n * Callback fired when the component changes value from checked state.\n * These property is ignored for subtrees.\n *\n * @param event - a React's Synthetic event\n * @param data - A data object with relevant information,\n * such as checked value and type of interaction that created the event.\n */\n onCheckedChange?(event: TreeCheckedChangeEvent, data: TreeCheckedChangeData): void;\n};\n\n/**\n * State used in rendering Tree\n */\nexport type TreeState = ComponentState<TreeSlots> & {\n open: boolean;\n} & (TreeContextValue | SubtreeContextValue);\n"],"names":[],"rangeMappings":";;","mappings":"AAqKA;;CAEC,GACD,WAE6C"}
@@ -5,8 +5,8 @@ export const renderTree_unstable = (state, contextValues)=>{
5
5
  assertSlots(state);
6
6
  return /*#__PURE__*/ _jsx(TreeProvider, {
7
7
  value: contextValues.tree,
8
- children: state.open && /*#__PURE__*/ _jsx(state.root, {
9
- children: state.root.children
10
- })
8
+ children: state.collapseMotion ? /*#__PURE__*/ _jsx(state.collapseMotion, {
9
+ children: /*#__PURE__*/ _jsx(state.root, {})
10
+ }) : /*#__PURE__*/ _jsx(state.root, {})
11
11
  });
12
12
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["renderTree.tsx"],"sourcesContent":["/** @jsxRuntime automatic */\n/** @jsxImportSource @fluentui/react-jsx-runtime */\nimport { assertSlots } from '@fluentui/react-utilities';\nimport type { TreeContextValues, TreeSlots, TreeState } from '../Tree/Tree.types';\nimport { TreeProvider } from '../TreeProvider';\n\nexport const renderTree_unstable = (state: TreeState, contextValues: TreeContextValues) => {\n assertSlots<TreeSlots>(state);\n return (\n <TreeProvider value={contextValues.tree}>\n {state.open && <state.root>{state.root.children}</state.root>}\n </TreeProvider>\n );\n};\n"],"names":["assertSlots","TreeProvider","renderTree_unstable","state","contextValues","value","tree","open","root","children"],"rangeMappings":";;;;;;;;;;;","mappings":"AAAA,0BAA0B,GAC1B,iDAAiD;AACjD,SAASA,WAAW,QAAQ,4BAA4B;AAExD,SAASC,YAAY,QAAQ,kBAAkB;AAE/C,OAAO,MAAMC,sBAAsB,CAACC,OAAkBC;IACpDJ,YAAuBG;IACvB,qBACE,KAACF;QAAaI,OAAOD,cAAcE,IAAI;kBACpCH,MAAMI,IAAI,kBAAI,KAACJ,MAAMK,IAAI;sBAAEL,MAAMK,IAAI,CAACC,QAAQ;;;AAGrD,EAAE"}
1
+ {"version":3,"sources":["renderTree.tsx"],"sourcesContent":["/** @jsxRuntime automatic */\n/** @jsxImportSource @fluentui/react-jsx-runtime */\nimport { assertSlots } from '@fluentui/react-utilities';\nimport type { TreeContextValues, TreeSlots, TreeState } from '../Tree/Tree.types';\nimport { TreeProvider } from '../TreeProvider';\n\nexport const renderTree_unstable = (state: TreeState, contextValues: TreeContextValues) => {\n assertSlots<TreeSlots>(state);\n return (\n <TreeProvider value={contextValues.tree}>\n {state.collapseMotion ? (\n <state.collapseMotion>\n <state.root />\n </state.collapseMotion>\n ) : (\n <state.root />\n )}\n </TreeProvider>\n );\n};\n"],"names":["assertSlots","TreeProvider","renderTree_unstable","state","contextValues","value","tree","collapseMotion","root"],"rangeMappings":";;;;;;;;;;;","mappings":"AAAA,0BAA0B,GAC1B,iDAAiD;AACjD,SAASA,WAAW,QAAQ,4BAA4B;AAExD,SAASC,YAAY,QAAQ,kBAAkB;AAE/C,OAAO,MAAMC,sBAAsB,CAACC,OAAkBC;IACpDJ,YAAuBG;IACvB,qBACE,KAACF;QAAaI,OAAOD,cAAcE,IAAI;kBACpCH,MAAMI,cAAc,iBACnB,KAACJ,MAAMI,cAAc;sBACnB,cAAA,KAACJ,MAAMK,IAAI;2BAGb,KAACL,MAAMK,IAAI;;AAInB,EAAE"}
@@ -8,7 +8,7 @@ export function useNestedCheckedItems(props) {
8
8
  }
9
9
  export function createNextNestedCheckedItems(data, previousCheckedItems) {
10
10
  if (data.selectionMode === 'single') {
11
- return ImmutableMap.create([
11
+ return ImmutableMap.from([
12
12
  [
13
13
  data.value,
14
14
  data.checked
@@ -1 +1 @@
1
- {"version":3,"sources":["useNestedControllableCheckedItems.ts"],"sourcesContent":["import * as React from 'react';\nimport type { TreeCheckedChangeData, TreeProps } from './Tree.types';\nimport { ImmutableMap } from '../../utils/ImmutableMap';\nimport { createCheckedItems } from '../../utils/createCheckedItems';\nimport { TreeItemValue } from '../TreeItem/TreeItem.types';\n\nexport function useNestedCheckedItems(props: Pick<TreeProps, 'checkedItems'>) {\n return React.useMemo(() => createCheckedItems(props.checkedItems), [props.checkedItems]);\n}\n\nexport function createNextNestedCheckedItems(\n data: Pick<TreeCheckedChangeData, 'selectionMode' | 'value' | 'checked'>,\n previousCheckedItems: ImmutableMap<TreeItemValue, 'mixed' | boolean>,\n): ImmutableMap<TreeItemValue, 'mixed' | boolean> {\n if (data.selectionMode === 'single') {\n return ImmutableMap.create([[data.value, data.checked]]);\n }\n if (data.selectionMode === 'multiselect') {\n return previousCheckedItems.set(data.value, data.checked);\n }\n return previousCheckedItems;\n}\n"],"names":["React","ImmutableMap","createCheckedItems","useNestedCheckedItems","props","useMemo","checkedItems","createNextNestedCheckedItems","data","previousCheckedItems","selectionMode","create","value","checked","set"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,YAAYA,WAAW,QAAQ;AAE/B,SAASC,YAAY,QAAQ,2BAA2B;AACxD,SAASC,kBAAkB,QAAQ,iCAAiC;AAGpE,OAAO,SAASC,sBAAsBC,KAAsC;IAC1E,OAAOJ,MAAMK,OAAO,CAAC,IAAMH,mBAAmBE,MAAME,YAAY,GAAG;QAACF,MAAME,YAAY;KAAC;AACzF;AAEA,OAAO,SAASC,6BACdC,IAAwE,EACxEC,oBAAoE;IAEpE,IAAID,KAAKE,aAAa,KAAK,UAAU;QACnC,OAAOT,aAAaU,MAAM,CAAC;YAAC;gBAACH,KAAKI,KAAK;gBAAEJ,KAAKK,OAAO;aAAC;SAAC;IACzD;IACA,IAAIL,KAAKE,aAAa,KAAK,eAAe;QACxC,OAAOD,qBAAqBK,GAAG,CAACN,KAAKI,KAAK,EAAEJ,KAAKK,OAAO;IAC1D;IACA,OAAOJ;AACT"}
1
+ {"version":3,"sources":["useNestedControllableCheckedItems.ts"],"sourcesContent":["import * as React from 'react';\nimport type { TreeCheckedChangeData, TreeProps } from './Tree.types';\nimport { ImmutableMap } from '../../utils/ImmutableMap';\nimport { createCheckedItems } from '../../utils/createCheckedItems';\nimport { TreeItemValue } from '../TreeItem/TreeItem.types';\n\nexport function useNestedCheckedItems(props: Pick<TreeProps, 'checkedItems'>) {\n return React.useMemo(() => createCheckedItems(props.checkedItems), [props.checkedItems]);\n}\n\nexport function createNextNestedCheckedItems(\n data: Pick<TreeCheckedChangeData, 'selectionMode' | 'value' | 'checked'>,\n previousCheckedItems: ImmutableMap<TreeItemValue, 'mixed' | boolean>,\n): ImmutableMap<TreeItemValue, 'mixed' | boolean> {\n if (data.selectionMode === 'single') {\n return ImmutableMap.from([[data.value, data.checked]]);\n }\n if (data.selectionMode === 'multiselect') {\n return previousCheckedItems.set(data.value, data.checked);\n }\n return previousCheckedItems;\n}\n"],"names":["React","ImmutableMap","createCheckedItems","useNestedCheckedItems","props","useMemo","checkedItems","createNextNestedCheckedItems","data","previousCheckedItems","selectionMode","from","value","checked","set"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,YAAYA,WAAW,QAAQ;AAE/B,SAASC,YAAY,QAAQ,2BAA2B;AACxD,SAASC,kBAAkB,QAAQ,iCAAiC;AAGpE,OAAO,SAASC,sBAAsBC,KAAsC;IAC1E,OAAOJ,MAAMK,OAAO,CAAC,IAAMH,mBAAmBE,MAAME,YAAY,GAAG;QAACF,MAAME,YAAY;KAAC;AACzF;AAEA,OAAO,SAASC,6BACdC,IAAwE,EACxEC,oBAAoE;IAEpE,IAAID,KAAKE,aAAa,KAAK,UAAU;QACnC,OAAOT,aAAaU,IAAI,CAAC;YAAC;gBAACH,KAAKI,KAAK;gBAAEJ,KAAKK,OAAO;aAAC;SAAC;IACvD;IACA,IAAIL,KAAKE,aAAa,KAAK,eAAe;QACxC,OAAOD,qBAAqBK,GAAG,CAACN,KAAKI,KAAK,EAAEJ,KAAKK,OAAO;IAC1D;IACA,OAAOJ;AACT"}
@@ -7,6 +7,8 @@ import { useRootTree } from '../../hooks/useRootTree';
7
7
  import { useSubtree } from '../../hooks/useSubtree';
8
8
  import { useTreeNavigation } from '../../hooks/useTreeNavigation';
9
9
  import { useTreeContext_unstable } from '../../contexts/treeContext';
10
+ import { ImmutableSet } from '../../utils/ImmutableSet';
11
+ import { ImmutableMap } from '../../utils/ImmutableMap';
10
12
  export const useTree_unstable = (props, ref)=>{
11
13
  'use no memo';
12
14
  const isRoot = React.useContext(SubtreeContext) === undefined;
@@ -29,7 +31,7 @@ function useNestedRootTree(props, ref) {
29
31
  const nextOpenItems = createNextOpenItems(data, openItems);
30
32
  (_props_onOpenChange = props.onOpenChange) === null || _props_onOpenChange === void 0 ? void 0 : _props_onOpenChange.call(props, event, {
31
33
  ...data,
32
- openItems: nextOpenItems.dangerouslyGetInternalSet_unstable()
34
+ openItems: ImmutableSet.dangerouslyGetInternalSet(nextOpenItems)
33
35
  });
34
36
  setOpenItems(nextOpenItems);
35
37
  }),
@@ -47,7 +49,7 @@ function useNestedRootTree(props, ref) {
47
49
  const nextCheckedItems = createNextNestedCheckedItems(data, checkedItems);
48
50
  (_props_onCheckedChange = props.onCheckedChange) === null || _props_onCheckedChange === void 0 ? void 0 : _props_onCheckedChange.call(props, event, {
49
51
  ...data,
50
- checkedItems: nextCheckedItems.dangerouslyGetInternalMap_unstable()
52
+ checkedItems: ImmutableMap.dangerouslyGetInternalMap(nextCheckedItems)
51
53
  });
52
54
  })
53
55
  }, useMergedRefs(ref, navigation.treeRef)), {
@@ -1 +1 @@
1
- {"version":3,"sources":["useTree.ts"],"sourcesContent":["import * as React from 'react';\nimport { useEventCallback, useMergedRefs } from '@fluentui/react-utilities';\nimport type { TreeProps, TreeState } 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 { useTreeNavigation } from '../../hooks/useTreeNavigation';\nimport { useTreeContext_unstable } from '../../contexts/treeContext';\n\nexport const useTree_unstable = (props: TreeProps, ref: React.Ref<HTMLElement>): TreeState => {\n 'use no memo';\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 ? useNestedRootTree(props, ref) : useNestedSubtree(props, ref);\n};\n\nfunction useNestedRootTree(props: TreeProps, ref: React.Ref<HTMLElement>): TreeState {\n 'use no memo';\n\n const [openItems, setOpenItems] = useControllableOpenItems(props);\n const checkedItems = useNestedCheckedItems(props);\n const navigation = useTreeNavigation();\n\n return Object.assign(\n useRootTree(\n {\n ...props,\n openItems,\n checkedItems,\n onOpenChange: useEventCallback((event, data) => {\n const nextOpenItems = createNextOpenItems(data, openItems);\n props.onOpenChange?.(event, {\n ...data,\n openItems: nextOpenItems.dangerouslyGetInternalSet_unstable(),\n });\n setOpenItems(nextOpenItems);\n }),\n onNavigation: useEventCallback((event, data) => {\n props.onNavigation?.(event, data);\n if (!event.isDefaultPrevented()) {\n navigation.navigate(data, {\n preventScroll: data.isScrollPrevented(),\n });\n }\n }),\n onCheckedChange: useEventCallback((event, data) => {\n const nextCheckedItems = createNextNestedCheckedItems(data, checkedItems);\n props.onCheckedChange?.(event, {\n ...data,\n checkedItems: nextCheckedItems.dangerouslyGetInternalMap_unstable(),\n });\n }),\n },\n useMergedRefs(ref, navigation.treeRef),\n ),\n { treeType: 'nested' } as const,\n );\n}\n\nfunction useNestedSubtree(props: TreeProps, ref: React.Ref<HTMLElement>): TreeState {\n 'use no memo';\n\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","useTreeNavigation","useTreeContext_unstable","useTree_unstable","props","ref","isRoot","useContext","undefined","useNestedRootTree","useNestedSubtree","openItems","setOpenItems","checkedItems","navigation","Object","assign","onOpenChange","event","data","nextOpenItems","dangerouslyGetInternalSet_unstable","onNavigation","isDefaultPrevented","navigate","preventScroll","isScrollPrevented","onCheckedChange","nextCheckedItems","dangerouslyGetInternalMap_unstable","treeRef","treeType","process","env","NODE_ENV","ctx","Error"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,gBAAgB,EAAEC,aAAa,QAAQ,4BAA4B;AAE5E,SAASC,mBAAmB,EAAEC,wBAAwB,QAAQ,uCAAuC;AACrG,SAASC,4BAA4B,EAAEC,qBAAqB,QAAQ,sCAAsC;AAC1G,SAASC,cAAc,QAAQ,gCAAgC;AAC/D,SAASC,WAAW,QAAQ,0BAA0B;AACtD,SAASC,UAAU,QAAQ,yBAAyB;AACpD,SAASC,iBAAiB,QAAQ,gCAAgC;AAClE,SAASC,uBAAuB,QAAQ,6BAA6B;AAErE,OAAO,MAAMC,mBAAmB,CAACC,OAAkBC;IACjD;IAEA,MAAMC,SAASf,MAAMgB,UAAU,CAACT,oBAAoBU;IACpD,uDAAuD;IACvD,sEAAsE;IACtE,sDAAsD;IACtD,OAAOF,SAASG,kBAAkBL,OAAOC,OAAOK,iBAAiBN,OAAOC;AAC1E,EAAE;AAEF,SAASI,kBAAkBL,KAAgB,EAAEC,GAA2B;IACtE;IAEA,MAAM,CAACM,WAAWC,aAAa,GAAGjB,yBAAyBS;IAC3D,MAAMS,eAAehB,sBAAsBO;IAC3C,MAAMU,aAAab;IAEnB,OAAOc,OAAOC,MAAM,CAClBjB,YACE;QACE,GAAGK,KAAK;QACRO;QACAE;QACAI,cAAczB,iBAAiB,CAAC0B,OAAOC;gBAErCf;YADA,MAAMgB,gBAAgB1B,oBAAoByB,MAAMR;aAChDP,sBAAAA,MAAMa,YAAY,cAAlBb,0CAAAA,yBAAAA,OAAqBc,OAAO;gBAC1B,GAAGC,IAAI;gBACPR,WAAWS,cAAcC,kCAAkC;YAC7D;YACAT,aAAaQ;QACf;QACAE,cAAc9B,iBAAiB,CAAC0B,OAAOC;gBACrCf;aAAAA,sBAAAA,MAAMkB,YAAY,cAAlBlB,0CAAAA,yBAAAA,OAAqBc,OAAOC;YAC5B,IAAI,CAACD,MAAMK,kBAAkB,IAAI;gBAC/BT,WAAWU,QAAQ,CAACL,MAAM;oBACxBM,eAAeN,KAAKO,iBAAiB;gBACvC;YACF;QACF;QACAC,iBAAiBnC,iBAAiB,CAAC0B,OAAOC;gBAExCf;YADA,MAAMwB,mBAAmBhC,6BAA6BuB,MAAMN;aAC5DT,yBAAAA,MAAMuB,eAAe,cAArBvB,6CAAAA,4BAAAA,OAAwBc,OAAO;gBAC7B,GAAGC,IAAI;gBACPN,cAAce,iBAAiBC,kCAAkC;YACnE;QACF;IACF,GACApC,cAAcY,KAAKS,WAAWgB,OAAO,IAEvC;QAAEC,UAAU;IAAS;AAEzB;AAEA,SAASrB,iBAAiBN,KAAgB,EAAEC,GAA2B;IACrE;IAEA,IAAI2B,QAAQC,GAAG,CAACC,QAAQ,KAAK,eAAe;QAC1C,qEAAqE;QACrE,sDAAsD;QACtD,MAAMH,WAAW7B,wBAAwBiC,CAAAA,MAAOA,IAAIJ,QAAQ;QAC5D,IAAIA,aAAa,QAAQ;YACvB,MAAM,IAAIK,MAA2B,CAAC;;mEAItC,CAAC;QACH;IACF;IACA,OAAOpC,WAAWI,OAAOC;AAC3B"}
1
+ {"version":3,"sources":["useTree.ts"],"sourcesContent":["import * as React from 'react';\nimport { useEventCallback, useMergedRefs } from '@fluentui/react-utilities';\nimport type { TreeProps, TreeState } 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 { useTreeNavigation } from '../../hooks/useTreeNavigation';\nimport { useTreeContext_unstable } from '../../contexts/treeContext';\nimport { ImmutableSet } from '../../utils/ImmutableSet';\nimport { ImmutableMap } from '../../utils/ImmutableMap';\n\nexport const useTree_unstable = (props: TreeProps, ref: React.Ref<HTMLElement>): TreeState => {\n 'use no memo';\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 ? useNestedRootTree(props, ref) : useNestedSubtree(props, ref);\n};\n\nfunction useNestedRootTree(props: TreeProps, ref: React.Ref<HTMLElement>): TreeState {\n 'use no memo';\n\n const [openItems, setOpenItems] = useControllableOpenItems(props);\n const checkedItems = useNestedCheckedItems(props);\n const navigation = useTreeNavigation();\n\n return Object.assign(\n useRootTree(\n {\n ...props,\n openItems,\n checkedItems,\n onOpenChange: useEventCallback((event, data) => {\n const nextOpenItems = createNextOpenItems(data, openItems);\n props.onOpenChange?.(event, {\n ...data,\n openItems: ImmutableSet.dangerouslyGetInternalSet(nextOpenItems),\n });\n setOpenItems(nextOpenItems);\n }),\n onNavigation: useEventCallback((event, data) => {\n props.onNavigation?.(event, data);\n if (!event.isDefaultPrevented()) {\n navigation.navigate(data, {\n preventScroll: data.isScrollPrevented(),\n });\n }\n }),\n onCheckedChange: useEventCallback((event, data) => {\n const nextCheckedItems = createNextNestedCheckedItems(data, checkedItems);\n props.onCheckedChange?.(event, {\n ...data,\n checkedItems: ImmutableMap.dangerouslyGetInternalMap(nextCheckedItems),\n });\n }),\n },\n useMergedRefs(ref, navigation.treeRef),\n ),\n { treeType: 'nested' } as const,\n );\n}\n\nfunction useNestedSubtree(props: TreeProps, ref: React.Ref<HTMLElement>): TreeState {\n 'use no memo';\n\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","useTreeNavigation","useTreeContext_unstable","ImmutableSet","ImmutableMap","useTree_unstable","props","ref","isRoot","useContext","undefined","useNestedRootTree","useNestedSubtree","openItems","setOpenItems","checkedItems","navigation","Object","assign","onOpenChange","event","data","nextOpenItems","dangerouslyGetInternalSet","onNavigation","isDefaultPrevented","navigate","preventScroll","isScrollPrevented","onCheckedChange","nextCheckedItems","dangerouslyGetInternalMap","treeRef","treeType","process","env","NODE_ENV","ctx","Error"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,gBAAgB,EAAEC,aAAa,QAAQ,4BAA4B;AAE5E,SAASC,mBAAmB,EAAEC,wBAAwB,QAAQ,uCAAuC;AACrG,SAASC,4BAA4B,EAAEC,qBAAqB,QAAQ,sCAAsC;AAC1G,SAASC,cAAc,QAAQ,gCAAgC;AAC/D,SAASC,WAAW,QAAQ,0BAA0B;AACtD,SAASC,UAAU,QAAQ,yBAAyB;AACpD,SAASC,iBAAiB,QAAQ,gCAAgC;AAClE,SAASC,uBAAuB,QAAQ,6BAA6B;AACrE,SAASC,YAAY,QAAQ,2BAA2B;AACxD,SAASC,YAAY,QAAQ,2BAA2B;AAExD,OAAO,MAAMC,mBAAmB,CAACC,OAAkBC;IACjD;IAEA,MAAMC,SAASjB,MAAMkB,UAAU,CAACX,oBAAoBY;IACpD,uDAAuD;IACvD,sEAAsE;IACtE,sDAAsD;IACtD,OAAOF,SAASG,kBAAkBL,OAAOC,OAAOK,iBAAiBN,OAAOC;AAC1E,EAAE;AAEF,SAASI,kBAAkBL,KAAgB,EAAEC,GAA2B;IACtE;IAEA,MAAM,CAACM,WAAWC,aAAa,GAAGnB,yBAAyBW;IAC3D,MAAMS,eAAelB,sBAAsBS;IAC3C,MAAMU,aAAaf;IAEnB,OAAOgB,OAAOC,MAAM,CAClBnB,YACE;QACE,GAAGO,KAAK;QACRO;QACAE;QACAI,cAAc3B,iBAAiB,CAAC4B,OAAOC;gBAErCf;YADA,MAAMgB,gBAAgB5B,oBAAoB2B,MAAMR;aAChDP,sBAAAA,MAAMa,YAAY,cAAlBb,0CAAAA,yBAAAA,OAAqBc,OAAO;gBAC1B,GAAGC,IAAI;gBACPR,WAAWV,aAAaoB,yBAAyB,CAACD;YACpD;YACAR,aAAaQ;QACf;QACAE,cAAchC,iBAAiB,CAAC4B,OAAOC;gBACrCf;aAAAA,sBAAAA,MAAMkB,YAAY,cAAlBlB,0CAAAA,yBAAAA,OAAqBc,OAAOC;YAC5B,IAAI,CAACD,MAAMK,kBAAkB,IAAI;gBAC/BT,WAAWU,QAAQ,CAACL,MAAM;oBACxBM,eAAeN,KAAKO,iBAAiB;gBACvC;YACF;QACF;QACAC,iBAAiBrC,iBAAiB,CAAC4B,OAAOC;gBAExCf;YADA,MAAMwB,mBAAmBlC,6BAA6ByB,MAAMN;aAC5DT,yBAAAA,MAAMuB,eAAe,cAArBvB,6CAAAA,4BAAAA,OAAwBc,OAAO;gBAC7B,GAAGC,IAAI;gBACPN,cAAcX,aAAa2B,yBAAyB,CAACD;YACvD;QACF;IACF,GACArC,cAAcc,KAAKS,WAAWgB,OAAO,IAEvC;QAAEC,UAAU;IAAS;AAEzB;AAEA,SAASrB,iBAAiBN,KAAgB,EAAEC,GAA2B;IACrE;IAEA,IAAI2B,QAAQC,GAAG,CAACC,QAAQ,KAAK,eAAe;QAC1C,qEAAqE;QACrE,sDAAsD;QACtD,MAAMH,WAAW/B,wBAAwBmC,CAAAA,MAAOA,IAAIJ,QAAQ;QAC5D,IAAIA,aAAa,QAAQ;YACvB,MAAM,IAAIK,MAA2B,CAAC;;mEAItC,CAAC;QACH;IACF;IACA,OAAOtC,WAAWM,OAAOC;AAC3B"}
@@ -1,13 +1,17 @@
1
1
  import * as React from 'react';
2
2
  import { useFluent_unstable } from '@fluentui/react-shared-contexts';
3
3
  import { ChevronRight12Regular } from '@fluentui/react-icons';
4
+ import { durations, curves } from '@fluentui/react-motion';
4
5
  import { useTreeItemContext_unstable } from '../contexts/treeItemContext';
5
6
  export const TreeItemChevron = /*#__PURE__*/ React.memo(()=>{
6
7
  const open = useTreeItemContext_unstable((ctx)=>ctx.open);
7
8
  const { dir } = useFluent_unstable();
8
9
  const expandIconRotation = open ? 90 : dir !== 'rtl' ? 0 : 180;
9
10
  return /*#__PURE__*/ React.createElement(ChevronRight12Regular, {
10
- style: expandIconInlineStyles[expandIconRotation]
11
+ style: {
12
+ ...expandIconInlineStyles[expandIconRotation],
13
+ transition: `transform ${durations.durationNormal}ms ${curves.curveEasyEaseMax}`
14
+ }
11
15
  });
12
16
  });
13
17
  TreeItemChevron.displayName = 'TreeItemChevron';
@@ -1 +1 @@
1
- {"version":3,"sources":["TreeItemChevron.tsx"],"sourcesContent":["import * as React from 'react';\nimport { useFluent_unstable } from '@fluentui/react-shared-contexts';\nimport { ChevronRight12Regular } from '@fluentui/react-icons';\nimport { useTreeItemContext_unstable } from '../contexts/treeItemContext';\n\nexport const TreeItemChevron = React.memo(() => {\n const open = useTreeItemContext_unstable(ctx => ctx.open);\n\n const { dir } = useFluent_unstable();\n\n const expandIconRotation = open ? 90 : dir !== 'rtl' ? 0 : 180;\n return <ChevronRight12Regular style={expandIconInlineStyles[expandIconRotation]} />;\n});\nTreeItemChevron.displayName = 'TreeItemChevron';\n\nconst expandIconInlineStyles = {\n 90: { transform: `rotate(90deg)` },\n 0: { transform: `rotate(0deg)` },\n 180: { transform: `rotate(180deg)` },\n} as const;\n"],"names":["React","useFluent_unstable","ChevronRight12Regular","useTreeItemContext_unstable","TreeItemChevron","memo","open","ctx","dir","expandIconRotation","style","expandIconInlineStyles","displayName","transform"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,kBAAkB,QAAQ,kCAAkC;AACrE,SAASC,qBAAqB,QAAQ,wBAAwB;AAC9D,SAASC,2BAA2B,QAAQ,8BAA8B;AAE1E,OAAO,MAAMC,gCAAkBJ,MAAMK,IAAI,CAAC;IACxC,MAAMC,OAAOH,4BAA4BI,CAAAA,MAAOA,IAAID,IAAI;IAExD,MAAM,EAAEE,GAAG,EAAE,GAAGP;IAEhB,MAAMQ,qBAAqBH,OAAO,KAAKE,QAAQ,QAAQ,IAAI;IAC3D,qBAAO,oBAACN;QAAsBQ,OAAOC,sBAAsB,CAACF,mBAAmB;;AACjF,GAAG;AACHL,gBAAgBQ,WAAW,GAAG;AAE9B,MAAMD,yBAAyB;IAC7B,IAAI;QAAEE,WAAW,CAAC,aAAa,CAAC;IAAC;IACjC,GAAG;QAAEA,WAAW,CAAC,YAAY,CAAC;IAAC;IAC/B,KAAK;QAAEA,WAAW,CAAC,cAAc,CAAC;IAAC;AACrC"}
1
+ {"version":3,"sources":["TreeItemChevron.tsx"],"sourcesContent":["import * as React from 'react';\nimport { useFluent_unstable } from '@fluentui/react-shared-contexts';\nimport { ChevronRight12Regular } from '@fluentui/react-icons';\nimport { durations, curves } from '@fluentui/react-motion';\nimport { useTreeItemContext_unstable } from '../contexts/treeItemContext';\n\nexport const TreeItemChevron = React.memo(() => {\n const open = useTreeItemContext_unstable(ctx => ctx.open);\n\n const { dir } = useFluent_unstable();\n\n const expandIconRotation = open ? 90 : dir !== 'rtl' ? 0 : 180;\n return (\n <ChevronRight12Regular\n style={{\n ...expandIconInlineStyles[expandIconRotation],\n transition: `transform ${durations.durationNormal}ms ${curves.curveEasyEaseMax}`,\n }}\n />\n );\n});\nTreeItemChevron.displayName = 'TreeItemChevron';\n\nconst expandIconInlineStyles = {\n 90: { transform: `rotate(90deg)` },\n 0: { transform: `rotate(0deg)` },\n 180: { transform: `rotate(180deg)` },\n} as const;\n"],"names":["React","useFluent_unstable","ChevronRight12Regular","durations","curves","useTreeItemContext_unstable","TreeItemChevron","memo","open","ctx","dir","expandIconRotation","style","expandIconInlineStyles","transition","durationNormal","curveEasyEaseMax","displayName","transform"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,kBAAkB,QAAQ,kCAAkC;AACrE,SAASC,qBAAqB,QAAQ,wBAAwB;AAC9D,SAASC,SAAS,EAAEC,MAAM,QAAQ,yBAAyB;AAC3D,SAASC,2BAA2B,QAAQ,8BAA8B;AAE1E,OAAO,MAAMC,gCAAkBN,MAAMO,IAAI,CAAC;IACxC,MAAMC,OAAOH,4BAA4BI,CAAAA,MAAOA,IAAID,IAAI;IAExD,MAAM,EAAEE,GAAG,EAAE,GAAGT;IAEhB,MAAMU,qBAAqBH,OAAO,KAAKE,QAAQ,QAAQ,IAAI;IAC3D,qBACE,oBAACR;QACCU,OAAO;YACL,GAAGC,sBAAsB,CAACF,mBAAmB;YAC7CG,YAAY,CAAC,UAAU,EAAEX,UAAUY,cAAc,CAAC,GAAG,EAAEX,OAAOY,gBAAgB,CAAC,CAAC;QAClF;;AAGN,GAAG;AACHV,gBAAgBW,WAAW,GAAG;AAE9B,MAAMJ,yBAAyB;IAC7B,IAAI;QAAEK,WAAW,CAAC,aAAa,CAAC;IAAC;IACjC,GAAG;QAAEA,WAAW,CAAC,YAAY,CAAC;IAAC;IAC/B,KAAK;QAAEA,WAAW,CAAC,cAAc,CAAC;IAAC;AACrC"}