@dxos/plugin-navtree 0.6.13 → 0.6.14-main.69511f5

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 (63) hide show
  1. package/dist/lib/browser/{chunk-U7MTKDFQ.mjs → chunk-PSVCPL4T.mjs} +1 -1
  2. package/dist/lib/browser/chunk-PSVCPL4T.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +595 -392
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/meta.mjs +1 -1
  7. package/dist/types/src/NavTreePlugin.d.ts.map +1 -1
  8. package/dist/types/src/components/CommandsDialog.d.ts.map +1 -1
  9. package/dist/types/src/components/HaloButton.stories.d.ts +5 -9
  10. package/dist/types/src/components/HaloButton.stories.d.ts.map +1 -1
  11. package/dist/types/src/components/NavBarStart.d.ts.map +1 -1
  12. package/dist/types/src/components/NavTree.d.ts +20 -0
  13. package/dist/types/src/components/NavTree.d.ts.map +1 -0
  14. package/dist/types/src/components/NavTree.stories.d.ts +7 -0
  15. package/dist/types/src/components/NavTree.stories.d.ts.map +1 -0
  16. package/dist/types/src/components/NavTreeContainer.d.ts +8 -8
  17. package/dist/types/src/components/NavTreeContainer.d.ts.map +1 -1
  18. package/dist/types/src/components/NavTreeItemAction.d.ts +23 -0
  19. package/dist/types/src/components/NavTreeItemAction.d.ts.map +1 -0
  20. package/dist/types/src/components/NavTreeItemAction.stories.d.ts +45 -0
  21. package/dist/types/src/components/NavTreeItemAction.stories.d.ts.map +1 -0
  22. package/dist/types/src/components/index.d.ts +1 -0
  23. package/dist/types/src/components/index.d.ts.map +1 -1
  24. package/dist/types/src/experimental/Tree.stories.d.ts +3 -7
  25. package/dist/types/src/experimental/Tree.stories.d.ts.map +1 -1
  26. package/dist/types/src/meta.d.ts.map +1 -1
  27. package/dist/types/src/stories/Graph.stories.d.ts +4 -12
  28. package/dist/types/src/stories/Graph.stories.d.ts.map +1 -1
  29. package/dist/types/src/testing/generator.d.ts +86 -0
  30. package/dist/types/src/testing/generator.d.ts.map +1 -0
  31. package/dist/types/src/testing/index.d.ts +3 -0
  32. package/dist/types/src/testing/index.d.ts.map +1 -0
  33. package/dist/types/src/testing/visitor.d.ts +18 -0
  34. package/dist/types/src/testing/visitor.d.ts.map +1 -0
  35. package/dist/types/src/translations.d.ts +5 -10
  36. package/dist/types/src/translations.d.ts.map +1 -1
  37. package/dist/types/src/types.d.ts +41 -0
  38. package/dist/types/src/types.d.ts.map +1 -0
  39. package/dist/types/src/util.d.ts +8 -9
  40. package/dist/types/src/util.d.ts.map +1 -1
  41. package/package.json +39 -34
  42. package/src/NavTreePlugin.tsx +89 -36
  43. package/src/components/CommandsDialog.tsx +2 -4
  44. package/src/components/HaloButton.stories.tsx +8 -6
  45. package/src/components/NavBarStart.tsx +2 -4
  46. package/src/components/NavTree.stories.tsx +104 -0
  47. package/src/components/NavTree.tsx +127 -0
  48. package/src/components/NavTreeContainer.tsx +132 -302
  49. package/src/components/NavTreeFooter.tsx +1 -1
  50. package/src/components/NavTreeItemAction.stories.tsx +57 -0
  51. package/src/components/NavTreeItemAction.tsx +367 -0
  52. package/src/components/index.ts +1 -0
  53. package/src/experimental/Tree.stories.tsx +11 -8
  54. package/src/experimental/Tree.tsx +2 -2
  55. package/src/meta.ts +3 -1
  56. package/src/stories/Graph.stories.tsx +111 -102
  57. package/src/testing/generator.ts +199 -0
  58. package/src/testing/index.ts +6 -0
  59. package/src/testing/visitor.ts +152 -0
  60. package/src/translations.ts +3 -3
  61. package/src/types.ts +50 -0
  62. package/src/util.ts +52 -63
  63. package/dist/lib/browser/chunk-U7MTKDFQ.mjs.map +0 -7
@@ -1,7 +1,7 @@
1
1
  import { type Action, type Node, type NodeFilter, type Graph } from '@dxos/app-graph';
2
- import { type NavTreeItemNode, type NavTreeItemNodeProperties, type OpenItemIds } from '@dxos/react-ui-navtree';
3
2
  import { type MaybePromise } from '@dxos/util';
4
- export type NavTreeItemGraphNode = Node<any, NavTreeItemNodeProperties & Partial<{
3
+ import { type NodeProperties, type NavTreeItem } from './types';
4
+ export type NavTreeItemGraphNode = Node<any, Partial<NodeProperties & {
5
5
  persistenceClass: string;
6
6
  persistenceKey: string;
7
7
  acceptPersistenceClass: Set<string>;
@@ -11,22 +11,21 @@ export type NavTreeItemGraphNode = Node<any, NavTreeItemNodeProperties & Partial
11
11
  onTransferStart: (activeNode: NavTreeItemGraphNode, index?: number) => MaybePromise<void>;
12
12
  onTransferEnd: (activeNode: NavTreeItemGraphNode, destinationParent: NavTreeItemGraphNode) => MaybePromise<void>;
13
13
  }>>;
14
- export type NavTreeItem = NavTreeItemNode<NavTreeItemGraphNode>;
15
14
  export declare const getParent: (graph: Graph, node: NavTreeItemGraphNode, path: string[]) => NavTreeItemGraphNode | undefined;
16
15
  export declare const getPersistenceParent: (graph: Graph, node: NavTreeItemGraphNode, path: string[], persistenceClass: string) => NavTreeItemGraphNode | null;
17
16
  export declare const resolveMigrationOperation: (graph: Graph, activeNode: NavTreeItemGraphNode, destinationPath: string[], destinationRelatedNode?: NavTreeItemGraphNode) => "transfer" | "copy" | "reject";
18
17
  export declare const sortActions: (actions: Action[]) => Action[];
19
- export declare const getTreeItemNode: (treeItems: NavTreeItemNode[], path?: string[]) => NavTreeItemNode | undefined;
20
- export declare const getChildren: (graph: Graph, node: NavTreeItemGraphNode, filter?: NodeFilter, path?: string[]) => NavTreeItemGraphNode[];
21
- type FlattenedActions = Required<Pick<NavTreeItemNode, 'actions' | 'groupedActions'>>;
22
- export declare const getActions: (graph: Graph, node: NavTreeItemGraphNode) => FlattenedActions;
18
+ export declare const getTreeItemNode: (treeItems: NavTreeItem[], path?: string[]) => NavTreeItem | undefined;
19
+ export declare const getChildren: (graph: Graph, node: NavTreeItemGraphNode, filter?: NodeFilter, path?: readonly string[]) => NavTreeItemGraphNode[];
20
+ type FlattenedActions = Required<Pick<NavTreeItem, 'actions' | 'groupedActions'>>;
21
+ export declare const getActions: (graph: Graph, node: Node) => FlattenedActions;
23
22
  export declare const expandChildrenAndActions: (graph: Graph, node: Node) => Promise<[void, [void, void]]>;
24
23
  export declare const expandChildren: (graph: Graph, node: Node) => Promise<void>;
25
24
  export declare const expandActions: (graph: Graph, node: Node) => Promise<[void, void]>;
26
25
  /**
27
26
  * Get a reactive tree node from a graph node.
28
27
  */
29
- export declare const treeItemsFromRootNode: (graph: Graph, rootNode: NavTreeItemGraphNode, openItemIds: OpenItemIds, path?: string[], filter?: NodeFilter) => NavTreeItem[];
30
- export declare const expandOpenGraphNodes: (graph: Graph, openItemIds: OpenItemIds) => Promise<[void, [void, void]][]>;
28
+ export declare const treeItemsFromRootNode: (graph: Graph, rootNode: NavTreeItemGraphNode, open: string[], getItem: (node: NavTreeItemGraphNode, parent: readonly string[]) => NavTreeItem, path?: readonly string[], filter?: NodeFilter) => NavTreeItem[];
29
+ export declare const expandOpenGraphNodes: (graph: Graph, open: string[]) => Promise<[void, [void, void]][]>;
31
30
  export {};
32
31
  //# sourceMappingURL=util.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../../src/util.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,KAAK,MAAM,EACX,KAAK,IAAI,EACT,KAAK,UAAU,EACf,KAAK,KAAK,EAIX,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,yBAAyB,EAC9B,KAAK,WAAW,EACjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,KAAK,YAAY,EAAe,MAAM,YAAY,CAAC;AAE5D,MAAM,MAAM,oBAAoB,GAAG,IAAI,CACrC,GAAG,EACH,yBAAyB,GACvB,OAAO,CAAC;IACN,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,sBAAsB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACpC,oBAAoB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAClC,mBAAmB,EAAE,CAAC,SAAS,EAAE,oBAAoB,EAAE,KAAK,YAAY,CAAC,IAAI,CAAC,CAAC;IAC/E,MAAM,EAAE,CAAC,UAAU,EAAE,oBAAoB,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,YAAY,CAAC,IAAI,CAAC,CAAC;IACjF,eAAe,EAAE,CAAC,UAAU,EAAE,oBAAoB,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,YAAY,CAAC,IAAI,CAAC,CAAC;IAC1F,aAAa,EAAE,CAAC,UAAU,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,oBAAoB,KAAK,YAAY,CAAC,IAAI,CAAC,CAAC;CAClH,CAAC,CACL,CAAC;AACF,MAAM,MAAM,WAAW,GAAG,eAAe,CAAC,oBAAoB,CAAC,CAAC;AAEhE,eAAO,MAAM,SAAS,UACb,KAAK,QACN,oBAAoB,QACpB,MAAM,EAAE,KACb,oBAAoB,GAAG,SAGzB,CAAC;AAEF,eAAO,MAAM,oBAAoB,UACxB,KAAK,QACN,oBAAoB,QACpB,MAAM,EAAE,oBACI,MAAM,KACvB,oBAAoB,GAAG,IAOzB,CAAC;AAEF,eAAO,MAAM,yBAAyB,UAC7B,KAAK,cACA,oBAAoB,mBACf,MAAM,EAAE,2BACA,oBAAoB,KAC5C,UAAU,GAAG,MAAM,GAAG,QAsBxB,CAAC;AAGF,eAAO,MAAM,WAAW,YAAa,MAAM,EAAE,KAAG,MAAM,EAWlD,CAAC;AAEL,eAAO,MAAM,eAAe,cAAe,eAAe,EAAE,SAAS,MAAM,EAAE,KAAG,eAAe,GAAG,SAQjG,CAAC;AAEF,eAAO,MAAM,WAAW,UACf,KAAK,QACN,oBAAoB,WACjB,UAAU,SACb,MAAM,EAAE,KACb,oBAAoB,EAStB,CAAC;AAEF,KAAK,gBAAgB,GAAG,QAAQ,CAAC,IAAI,CAAC,eAAe,EAAE,SAAS,GAAG,gBAAgB,CAAC,CAAC,CAAC;AAEtF,eAAO,MAAM,UAAU,UAAW,KAAK,QAAQ,oBAAoB,KAAG,gBAYrE,CAAC;AAEF,eAAO,MAAM,wBAAwB,UAAW,KAAK,QAAQ,IAAI,kCAEhE,CAAC;AAEF,eAAO,MAAM,cAAc,UAAW,KAAK,QAAQ,IAAI,kBAEtD,CAAC;AAEF,eAAO,MAAM,aAAa,UAAW,KAAK,QAAQ,IAAI,0BAErD,CAAC;AAmDF;;GAEG;AACH,eAAO,MAAM,qBAAqB,UACzB,KAAK,YACF,oBAAoB,eACjB,WAAW,SAClB,MAAM,EAAE,WACL,UAAU,KAClB,WAAW,EAEb,CAAC;AAEF,eAAO,MAAM,oBAAoB,UAAW,KAAK,eAAe,WAAW,oCAS1E,CAAC"}
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../../src/util.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,KAAK,MAAM,EACX,KAAK,IAAI,EACT,KAAK,UAAU,EACf,KAAK,KAAK,EAIX,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,KAAK,YAAY,EAAe,MAAM,YAAY,CAAC;AAE5D,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAEhE,MAAM,MAAM,oBAAoB,GAAG,IAAI,CACrC,GAAG,EACH,OAAO,CACL,cAAc,GAAG;IACf,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,sBAAsB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACpC,oBAAoB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAClC,mBAAmB,EAAE,CAAC,SAAS,EAAE,oBAAoB,EAAE,KAAK,YAAY,CAAC,IAAI,CAAC,CAAC;IAC/E,MAAM,EAAE,CAAC,UAAU,EAAE,oBAAoB,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,YAAY,CAAC,IAAI,CAAC,CAAC;IACjF,eAAe,EAAE,CAAC,UAAU,EAAE,oBAAoB,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,YAAY,CAAC,IAAI,CAAC,CAAC;IAC1F,aAAa,EAAE,CAAC,UAAU,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,oBAAoB,KAAK,YAAY,CAAC,IAAI,CAAC,CAAC;CAClH,CACF,CACF,CAAC;AAEF,eAAO,MAAM,SAAS,UACb,KAAK,QACN,oBAAoB,QACpB,MAAM,EAAE,KACb,oBAAoB,GAAG,SAGzB,CAAC;AAEF,eAAO,MAAM,oBAAoB,UACxB,KAAK,QACN,oBAAoB,QACpB,MAAM,EAAE,oBACI,MAAM,KACvB,oBAAoB,GAAG,IAOzB,CAAC;AAEF,eAAO,MAAM,yBAAyB,UAC7B,KAAK,cACA,oBAAoB,mBACf,MAAM,EAAE,2BACA,oBAAoB,KAC5C,UAAU,GAAG,MAAM,GAAG,QAsBxB,CAAC;AAGF,eAAO,MAAM,WAAW,YAAa,MAAM,EAAE,KAAG,MAAM,EAWlD,CAAC;AAEL,eAAO,MAAM,eAAe,cAAe,WAAW,EAAE,SAAS,MAAM,EAAE,KAAG,WAAW,GAAG,SAQzF,CAAC;AAEF,eAAO,MAAM,WAAW,UACf,KAAK,QACN,oBAAoB,WACjB,UAAU,SACb,SAAS,MAAM,EAAE,KACtB,oBAAoB,EAStB,CAAC;AAEF,KAAK,gBAAgB,GAAG,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,gBAAgB,CAAC,CAAC,CAAC;AAElF,eAAO,MAAM,UAAU,UAAW,KAAK,QAAQ,IAAI,KAAG,gBAgBrD,CAAC;AAEF,eAAO,MAAM,wBAAwB,UAAW,KAAK,QAAQ,IAAI,kCAEhE,CAAC;AAEF,eAAO,MAAM,cAAc,UAAW,KAAK,QAAQ,IAAI,kBAEtD,CAAC;AAEF,eAAO,MAAM,aAAa,UAAW,KAAK,QAAQ,IAAI,0BAErD,CAAC;AAwCF;;GAEG;AACH,eAAO,MAAM,qBAAqB,UACzB,KAAK,YACF,oBAAoB,QACxB,MAAM,EAAE,WACL,CAAC,IAAI,EAAE,oBAAoB,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,KAAK,WAAW,SACxE,SAAS,MAAM,EAAE,WACf,UAAU,KAClB,WAAW,EAEb,CAAC;AAEF,eAAO,MAAM,oBAAoB,UAAW,KAAK,QAAQ,MAAM,EAAE,oCAShE,CAAC"}
package/package.json CHANGED
@@ -1,19 +1,20 @@
1
1
  {
2
2
  "name": "@dxos/plugin-navtree",
3
- "version": "0.6.13",
3
+ "version": "0.6.14-main.69511f5",
4
4
  "description": "DXOS Surface plugin for a tree view visualization of the graph.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
7
7
  "license": "MIT",
8
8
  "author": "DXOS.org",
9
+ "sideEffects": true,
9
10
  "exports": {
10
11
  ".": {
11
- "browser": "./dist/lib/browser/index.mjs",
12
- "types": "./dist/types/src/index.d.ts"
12
+ "types": "./dist/types/src/index.d.ts",
13
+ "browser": "./dist/lib/browser/index.mjs"
13
14
  },
14
15
  "./meta": {
15
- "browser": "./dist/lib/browser/meta.mjs",
16
- "types": "./dist/types/src/meta.d.ts"
16
+ "types": "./dist/types/src/meta.d.ts",
17
+ "browser": "./dist/lib/browser/meta.mjs"
17
18
  }
18
19
  },
19
20
  "types": "dist/types/src/index.d.ts",
@@ -29,27 +30,31 @@
29
30
  "src"
30
31
  ],
31
32
  "dependencies": {
33
+ "@atlaskit/pragmatic-drag-and-drop": "^1.4.0",
34
+ "@atlaskit/pragmatic-drag-and-drop-hitbox": "^1.0.3",
32
35
  "@preact/signals-core": "^1.6.0",
36
+ "@radix-ui/react-use-controllable-state": "^1.0.0",
33
37
  "date-fns": "^3.3.1",
34
- "@dxos/app-graph": "0.6.13",
35
- "@dxos/app-framework": "0.6.13",
36
- "@dxos/debug": "0.6.13",
37
- "@dxos/async": "0.6.13",
38
- "@dxos/echo-schema": "0.6.13",
39
- "@dxos/keyboard": "0.6.13",
40
- "@dxos/local-storage": "0.6.13",
41
- "@dxos/log": "0.6.13",
42
- "@dxos/plugin-client": "0.6.13",
43
- "@dxos/plugin-graph": "0.6.13",
44
- "@dxos/plugin-observability": "0.6.13",
45
- "@dxos/plugin-theme": "0.6.13",
46
- "@dxos/protocols": "0.6.13",
47
- "@dxos/react-ui-deck": "0.6.13",
48
- "@dxos/react-ui-mosaic": "0.6.13",
49
- "@dxos/react-client": "0.6.13",
50
- "@dxos/react-ui-navtree": "0.6.13",
51
- "@dxos/util": "0.6.13",
52
- "@dxos/react-ui-searchlist": "0.6.13"
38
+ "@dxos/app-graph": "0.6.14-main.69511f5",
39
+ "@dxos/app-framework": "0.6.14-main.69511f5",
40
+ "@dxos/async": "0.6.14-main.69511f5",
41
+ "@dxos/echo-schema": "0.6.14-main.69511f5",
42
+ "@dxos/invariant": "0.6.14-main.69511f5",
43
+ "@dxos/keyboard": "0.6.14-main.69511f5",
44
+ "@dxos/debug": "0.6.14-main.69511f5",
45
+ "@dxos/log": "0.6.14-main.69511f5",
46
+ "@dxos/local-storage": "0.6.14-main.69511f5",
47
+ "@dxos/plugin-graph": "0.6.14-main.69511f5",
48
+ "@dxos/plugin-client": "0.6.14-main.69511f5",
49
+ "@dxos/plugin-observability": "0.6.14-main.69511f5",
50
+ "@dxos/plugin-theme": "0.6.14-main.69511f5",
51
+ "@dxos/protocols": "0.6.14-main.69511f5",
52
+ "@dxos/react-client": "0.6.14-main.69511f5",
53
+ "@dxos/react-ui-deck": "0.6.14-main.69511f5",
54
+ "@dxos/react-ui-list": "0.6.14-main.69511f5",
55
+ "@dxos/react-ui-mosaic": "0.6.14-main.69511f5",
56
+ "@dxos/react-ui-searchlist": "0.6.14-main.69511f5",
57
+ "@dxos/util": "0.6.14-main.69511f5"
53
58
  },
54
59
  "devDependencies": {
55
60
  "@phosphor-icons/react": "^2.1.5",
@@ -57,19 +62,19 @@
57
62
  "@types/react-dom": "~18.2.0",
58
63
  "react": "~18.2.0",
59
64
  "react-dom": "~18.2.0",
60
- "vite": "^5.3.4",
61
- "@dxos/echo-signals": "0.6.13",
62
- "@dxos/react-ui": "0.6.13",
63
- "@dxos/react-ui-theme": "0.6.13",
64
- "@dxos/random": "0.6.13",
65
- "@dxos/storybook-utils": "0.6.13"
65
+ "vite": "5.4.7",
66
+ "@dxos/echo-signals": "0.6.14-main.69511f5",
67
+ "@dxos/random": "0.6.14-main.69511f5",
68
+ "@dxos/react-ui": "0.6.14-main.69511f5",
69
+ "@dxos/react-ui-theme": "0.6.14-main.69511f5",
70
+ "@dxos/storybook-utils": "0.6.14-main.69511f5"
66
71
  },
67
72
  "peerDependencies": {
68
73
  "@phosphor-icons/react": "^2.1.5",
69
- "react": "^18.0.0",
70
- "react-dom": "^18.0.0",
71
- "@dxos/react-ui": "0.6.13",
72
- "@dxos/react-ui-theme": "0.6.13"
74
+ "react": "~18.2.0",
75
+ "react-dom": "~18.2.0",
76
+ "@dxos/react-ui": "0.6.14-main.69511f5",
77
+ "@dxos/react-ui-theme": "0.6.14-main.69511f5"
73
78
  },
74
79
  "publishConfig": {
75
80
  "access": "public"
@@ -2,7 +2,6 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { MagnifyingGlass, type IconProps } from '@phosphor-icons/react';
6
5
  import React from 'react';
7
6
 
8
7
  import {
@@ -20,11 +19,11 @@ import {
20
19
  parseGraphPlugin,
21
20
  NavigationAction,
22
21
  } from '@dxos/app-framework';
23
- import { createExtension, type Graph, isAction, isGraphNode, type Node } from '@dxos/app-graph';
22
+ import { createExtension, type Graph, isAction, isGraphNode, type Node, type NodeFilter } from '@dxos/app-graph';
23
+ import { invariant } from '@dxos/invariant';
24
24
  import { Keyboard } from '@dxos/keyboard';
25
25
  import { LocalStorageStore } from '@dxos/local-storage';
26
26
  import { Path } from '@dxos/react-ui-mosaic';
27
- import { type OpenItemIds } from '@dxos/react-ui-navtree';
28
27
  import { getHostPlatform } from '@dxos/util';
29
28
 
30
29
  import {
@@ -38,7 +37,14 @@ import {
38
37
  import { CommandsTrigger } from './components/CommandsTrigger';
39
38
  import meta, { KEY_BINDING, NAVTREE_PLUGIN } from './meta';
40
39
  import translations from './translations';
41
- import { expandOpenGraphNodes, getActions, getChildren, type NavTreeItem, type NavTreeItemGraphNode } from './util';
40
+ import { type NavTreeItem } from './types';
41
+ import {
42
+ expandOpenGraphNodes,
43
+ getActions,
44
+ getChildren,
45
+ treeItemsFromRootNode,
46
+ type NavTreeItemGraphNode,
47
+ } from './util';
42
48
 
43
49
  export type NavTreePluginProvides = SurfaceProvides &
44
50
  MetadataRecordsProvides &
@@ -46,22 +52,77 @@ export type NavTreePluginProvides = SurfaceProvides &
46
52
  TranslationsProvides &
47
53
  IntentResolverProvides;
48
54
 
49
- type NavTreeState = { root?: NavTreeItemGraphNode; openItemIds: OpenItemIds };
55
+ type NavTreeState = {
56
+ root?: NavTreeItemGraphNode;
57
+ flatTree: NavTreeItem[];
58
+ open: string[];
59
+ };
50
60
 
51
61
  export const NavTreePlugin = (): PluginDefinition<NavTreePluginProvides> => {
62
+ let graphPlugin: Plugin<GraphProvides> | undefined;
63
+ let graph: Graph | undefined;
64
+ const itemCache = new Map<string, NavTreeItem>();
65
+
52
66
  const state = new LocalStorageStore<NavTreeState>('dxos.org/settings/navtree', {
67
+ root: undefined,
68
+ get flatTree() {
69
+ if (!this.root || !graph) {
70
+ return [];
71
+ }
72
+
73
+ return treeItemsFromRootNode(graph, this.root, this.open, getItem);
74
+ },
53
75
  // TODO(thure): Do this dynamically.
54
- openItemIds: { root: true, 'dxos.org/plugin/space-spaces': true, 'dxos.org/plugin/files': true },
76
+ open: ['root', 'root~dxos.org/plugin/space-spaces', 'root~dxos.org/plugin/files'],
55
77
  });
56
78
 
57
- let graphPlugin: Plugin<GraphProvides> | undefined;
58
- let graph: Graph | undefined;
79
+ const getItem = (node: NavTreeItemGraphNode, parent: readonly string[], filter?: NodeFilter) => {
80
+ invariant(graph);
81
+ const path = [...parent, node.id];
82
+ const { actions, groupedActions } = getActions(graph, node);
83
+ const children = getChildren(graph, node, filter, path);
84
+ const parentOf =
85
+ children.length > 0 ? children.map(({ id }) => id) : node.properties.role === 'branch' ? [] : undefined;
86
+ const item = {
87
+ id: node.id,
88
+ label: node.properties.label ?? node.id,
89
+ icon: node.properties.icon,
90
+ disabled: node.properties.disabled,
91
+ testId: node.properties.testId,
92
+ className: node.properties.className,
93
+ headingClassName: node.properties.headingClassName,
94
+ path,
95
+ parentOf,
96
+ node,
97
+ actions,
98
+ groupedActions,
99
+ } satisfies NavTreeItem;
59
100
 
60
- const handleOpenItemIdsChange = (nextOpenItemIds: OpenItemIds) => {
101
+ const cachedItem = itemCache.get(node.id);
102
+ // TODO(wittjosiah): This is not a good enough check.
103
+ // Consider better ways to doing reactive transformations which retain referential equality.
104
+ if (cachedItem && JSON.stringify(item) === JSON.stringify(cachedItem)) {
105
+ return cachedItem;
106
+ } else {
107
+ itemCache.set(node.id, item);
108
+ return item;
109
+ }
110
+ };
111
+
112
+ const handleOpenChange = (item: NavTreeItem, open: boolean) => {
113
+ const path = Path.create(...item.path);
61
114
  // TODO(thure): This might become a localstorage leak; openItemIds that no longer exist should be removed from this map.
62
- state.values.openItemIds = nextOpenItemIds;
115
+ if (open) {
116
+ state.values.open.push(path);
117
+ } else {
118
+ const index = state.values.open.indexOf(path);
119
+ if (index > -1) {
120
+ state.values.open.splice(index, 1);
121
+ }
122
+ }
123
+
63
124
  if (graph) {
64
- void expandOpenGraphNodes(graph, nextOpenItemIds);
125
+ void expandOpenGraphNodes(graph, state.values.open);
65
126
  }
66
127
  };
67
128
 
@@ -78,9 +139,9 @@ export const NavTreePlugin = (): PluginDefinition<NavTreePluginProvides> => {
78
139
  getChildren(graph, state.values.root);
79
140
  getActions(graph, state.values.root);
80
141
 
81
- state.prop({ key: 'openItemIds', storageKey: 'openItemIds', type: LocalStorageStore.json<OpenItemIds>() });
142
+ state.prop({ key: 'open', type: LocalStorageStore.json<string[]>() });
82
143
 
83
- void expandOpenGraphNodes(graph, state.values.openItemIds);
144
+ void expandOpenGraphNodes(graph, state.values.open);
84
145
 
85
146
  // TODO(wittjosiah): Factor out.
86
147
  // TODO(wittjosiah): Handle removal of actions.
@@ -148,19 +209,15 @@ export const NavTreePlugin = (): PluginDefinition<NavTreePluginProvides> => {
148
209
 
149
210
  switch (role) {
150
211
  case 'navigation':
151
- if (state.values.root && state.values.openItemIds) {
152
- return (
153
- <NavTreeContainer
154
- root={state.values.root}
155
- activeIds={data.activeIds as Set<string>}
156
- openItemIds={state.values.openItemIds}
157
- onOpenItemIdsChange={handleOpenItemIdsChange}
158
- attended={data.attended as Set<string>}
159
- popoverAnchorId={data.popoverAnchorId as string}
160
- />
161
- );
162
- }
163
- break;
212
+ return (
213
+ <NavTreeContainer
214
+ items={state.values.flatTree}
215
+ current={data.activeIds as string[]}
216
+ open={state.values.open}
217
+ onOpenChange={handleOpenChange}
218
+ popoverAnchorId={data.popoverAnchorId as string}
219
+ />
220
+ );
164
221
 
165
222
  case 'document-title': {
166
223
  return <NavTreeDocumentTitle node={isGraphNode(data.activeNode) ? data.activeNode : undefined} />;
@@ -201,17 +258,14 @@ export const NavTreePlugin = (): PluginDefinition<NavTreePluginProvides> => {
201
258
  if (graph && intent.data?.id) {
202
259
  const path = graph.getPath({ target: intent.data.id });
203
260
  if (Array.isArray(path)) {
204
- const additionalOpenItems = [...Array(path.length - 1)].reduce((acc: OpenItemIds, _, index) => {
205
- const itemId = Path.create(...path.slice(1, index + 1));
261
+ const additionalOpenItems = [...Array(path.length)].reduce((acc: string[], _, index) => {
262
+ const itemId = Path.create(...path.slice(0, index));
206
263
  if (itemId.length > 0) {
207
- acc[itemId] = true;
264
+ acc.push(itemId);
208
265
  }
209
266
  return acc;
210
- }, {});
211
- state.values.openItemIds = {
212
- ...additionalOpenItems,
213
- ...state.values.openItemIds,
214
- };
267
+ }, []);
268
+ state.values.open.push(...additionalOpenItems);
215
269
  }
216
270
  }
217
271
  break;
@@ -243,8 +297,7 @@ export const NavTreePlugin = (): PluginDefinition<NavTreePluginProvides> => {
243
297
  },
244
298
  properties: {
245
299
  label: ['open commands label', { ns: NAVTREE_PLUGIN }],
246
- icon: (props: IconProps) => <MagnifyingGlass {...props} />,
247
- iconSymbol: 'ph--magnifying-glass--regular',
300
+ icon: 'ph--magnifying-glass--regular',
248
301
  keyBinding: {
249
302
  macos: 'meta+k',
250
303
  windows: 'ctrl+k',
@@ -2,14 +2,13 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { DotOutline } from '@phosphor-icons/react';
6
5
  import React, { useMemo, useState } from 'react';
7
6
 
8
7
  import { useIntentDispatcher, LayoutAction } from '@dxos/app-framework';
9
8
  import { type ActionLike, isActionGroup, isAction } from '@dxos/app-graph';
10
9
  import { Keyboard, keySymbols } from '@dxos/keyboard';
11
10
  import { useGraph } from '@dxos/plugin-graph';
12
- import { Button, Dialog, useTranslation, toLocalizedString } from '@dxos/react-ui';
11
+ import { Button, Dialog, Icon, useTranslation, toLocalizedString } from '@dxos/react-ui';
13
12
  import { SearchList } from '@dxos/react-ui-searchlist';
14
13
  import { descriptionText, mx } from '@dxos/react-ui-theme';
15
14
  import { getHostPlatform } from '@dxos/util';
@@ -70,7 +69,6 @@ export const CommandsDialogContent = ({ selected: initial }: { selected?: string
70
69
  typeof action.properties.keyBinding === 'string'
71
70
  ? action.properties.keyBinding
72
71
  : action.properties.keyBinding?.[getHostPlatform()];
73
- const Icon = action.properties.icon ?? DotOutline;
74
72
  return (
75
73
  <SearchList.Item
76
74
  value={label}
@@ -95,7 +93,7 @@ export const CommandsDialogContent = ({ selected: initial }: { selected?: string
95
93
  disabled={action.properties.disabled}
96
94
  {...(action.properties?.testId && { 'data-testid': action.properties.testId })}
97
95
  >
98
- <Icon size={4} className={mx(!action.properties.icon && 'invisible')} />
96
+ <Icon icon={action.properties.icon} size={4} />
99
97
  <span className='grow truncate'>{label}</span>
100
98
  {shortcut && <span className={mx('shrink-0', descriptionText)}>{keySymbols(shortcut).join('')}</span>}
101
99
  </SearchList.Item>
@@ -4,16 +4,18 @@
4
4
 
5
5
  import '@dxos-theme';
6
6
 
7
+ import { type Meta } from '@storybook/react';
7
8
  import React from 'react';
8
9
 
9
10
  import { HaloButton } from './HaloButton';
10
11
 
11
- export default {
12
- title: 'plugin-navtree/HaloButton',
13
- component: HaloButton,
14
- actions: { argTypesRegex: '^on.*' },
12
+ export const Default = (props: any) => {
13
+ return <HaloButton {...props} />;
15
14
  };
16
15
 
17
- export const Normal = (props: any) => {
18
- return <HaloButton {...props} />;
16
+ const meta: Meta<typeof HaloButton> = {
17
+ title: 'plugins/plugin-navtree/HaloButton',
18
+ component: HaloButton,
19
19
  };
20
+
21
+ export default meta;
@@ -2,7 +2,6 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { DotsThreeVertical } from '@phosphor-icons/react';
6
5
  import React, { Fragment } from 'react';
7
6
 
8
7
  import { getGraph, type Node } from '@dxos/app-graph';
@@ -22,7 +21,6 @@ export const NavBarStart = ({ activeNode, popoverAnchorId }: { activeNode: Node;
22
21
  ? Popover.Anchor
23
22
  : Fragment;
24
23
 
25
- const Icon = activeNode.properties?.icon ?? DotsThreeVertical;
26
24
  const graph = getGraph(activeNode);
27
25
  const actions = graph.actions(activeNode);
28
26
  const label = toLocalizedString(activeNode.properties?.label, t);
@@ -33,10 +31,10 @@ export const NavBarStart = ({ activeNode, popoverAnchorId }: { activeNode: Node;
33
31
  <>
34
32
  <ActionRoot>
35
33
  <PlankHeading.ActionsMenu
36
- Icon={Icon}
34
+ icon={activeNode.properties?.icon ?? 'ph--dots-three-vertical--regular'}
37
35
  attendableId={activeNode.id}
38
36
  triggerLabel={menuTriggerLabel}
39
- actions={actions}
37
+ actions={[actions]}
40
38
  onAction={(action) =>
41
39
  typeof action.data === 'function' && action.data({ node: action as Node, caller: TREE_ITEM_MAIN_HEADING })
42
40
  }
@@ -0,0 +1,104 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import '@dxos-theme';
6
+
7
+ import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
8
+ import { extractInstruction, type Instruction } from '@atlaskit/pragmatic-drag-and-drop-hitbox/tree-item';
9
+ import { type Meta } from '@storybook/react';
10
+ import React, { useEffect } from 'react';
11
+
12
+ import { type NodeArg } from '@dxos/app-graph';
13
+ import { create } from '@dxos/echo-schema';
14
+ import { faker } from '@dxos/random';
15
+ import { isItem } from '@dxos/react-ui-list';
16
+ import { Path } from '@dxos/react-ui-mosaic';
17
+ import { withLayout, withTheme } from '@dxos/storybook-utils';
18
+
19
+ import { NavTree, type NavTreeProps } from './NavTree';
20
+ import { createTree, flattenTree, updateState } from '../testing';
21
+ import { type NavTreeItem } from '../types';
22
+
23
+ faker.seed(1234);
24
+
25
+ type State = {
26
+ tree: NodeArg<any>;
27
+ flatTree: NavTreeItem[];
28
+ open: string[];
29
+ current: string[];
30
+ };
31
+
32
+ const state = create<State>({
33
+ tree: createTree(),
34
+ get flatTree() {
35
+ return flattenTree(this.tree, this.open);
36
+ },
37
+ open: [],
38
+ current: [],
39
+ });
40
+
41
+ const Story = (args: Partial<NavTreeProps>) => {
42
+ // NOTE: If passed directly to args, this won't be reactive.
43
+ const items = state.flatTree;
44
+
45
+ useEffect(() => {
46
+ return monitorForElements({
47
+ canMonitor: ({ source }) => isItem(source.data),
48
+ onDrop: ({ location, source }) => {
49
+ // Didn't drop on anything.
50
+ if (!location.current.dropTargets.length) {
51
+ return;
52
+ }
53
+
54
+ const target = location.current.dropTargets[0];
55
+
56
+ const instruction: Instruction | null = extractInstruction(target.data);
57
+ if (instruction !== null) {
58
+ updateState({
59
+ state: state.tree,
60
+ instruction,
61
+ source: source.data as NavTreeItem,
62
+ target: target.data as NavTreeItem,
63
+ });
64
+ }
65
+ },
66
+ });
67
+ }, []);
68
+
69
+ return <NavTree items={items} open={state.open} current={state.current} {...args} />;
70
+ };
71
+
72
+ const meta: Meta<typeof NavTree> = {
73
+ title: 'plugins/plugin-navtree/NavTree',
74
+ component: NavTree,
75
+ render: Story,
76
+ decorators: [withTheme, withLayout({ tooltips: true })],
77
+ args: {
78
+ onOpenChange: (item: NavTreeItem, open: boolean) => {
79
+ const path = Path.create(...item.path);
80
+ if (open) {
81
+ state.open.push(path);
82
+ } else {
83
+ const index = state.open.indexOf(path);
84
+ if (index > -1) {
85
+ state.open.splice(index, 1);
86
+ }
87
+ }
88
+ },
89
+ onSelect: (item: NavTreeItem, current: boolean) => {
90
+ if (current) {
91
+ state.current.push(item.id);
92
+ } else {
93
+ const index = state.current.indexOf(item.id);
94
+ if (index > -1) {
95
+ state.current.splice(index, 1);
96
+ }
97
+ }
98
+ },
99
+ },
100
+ };
101
+
102
+ export default meta;
103
+
104
+ export const Default = {};