@dxos/plugin-navtree 0.6.13 → 0.6.14-main.1366248

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 +611 -398
  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 +99 -41
  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.1366248",
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-framework": "0.6.14-main.1366248",
39
+ "@dxos/app-graph": "0.6.14-main.1366248",
40
+ "@dxos/async": "0.6.14-main.1366248",
41
+ "@dxos/echo-schema": "0.6.14-main.1366248",
42
+ "@dxos/debug": "0.6.14-main.1366248",
43
+ "@dxos/local-storage": "0.6.14-main.1366248",
44
+ "@dxos/log": "0.6.14-main.1366248",
45
+ "@dxos/keyboard": "0.6.14-main.1366248",
46
+ "@dxos/plugin-client": "0.6.14-main.1366248",
47
+ "@dxos/plugin-graph": "0.6.14-main.1366248",
48
+ "@dxos/invariant": "0.6.14-main.1366248",
49
+ "@dxos/plugin-observability": "0.6.14-main.1366248",
50
+ "@dxos/plugin-theme": "0.6.14-main.1366248",
51
+ "@dxos/protocols": "0.6.14-main.1366248",
52
+ "@dxos/react-client": "0.6.14-main.1366248",
53
+ "@dxos/react-ui-list": "0.6.14-main.1366248",
54
+ "@dxos/react-ui-deck": "0.6.14-main.1366248",
55
+ "@dxos/react-ui-mosaic": "0.6.14-main.1366248",
56
+ "@dxos/react-ui-searchlist": "0.6.14-main.1366248",
57
+ "@dxos/util": "0.6.14-main.1366248"
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/random": "0.6.14-main.1366248",
67
+ "@dxos/react-ui": "0.6.14-main.1366248",
68
+ "@dxos/storybook-utils": "0.6.14-main.1366248",
69
+ "@dxos/react-ui-theme": "0.6.14-main.1366248",
70
+ "@dxos/echo-signals": "0.6.14-main.1366248"
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.1366248",
77
+ "@dxos/react-ui-theme": "0.6.14-main.1366248"
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 {
@@ -19,12 +18,14 @@ import {
19
18
  type GraphProvides,
20
19
  parseGraphPlugin,
21
20
  NavigationAction,
21
+ parseNavigationPlugin,
22
22
  } from '@dxos/app-framework';
23
- import { createExtension, type Graph, isAction, isGraphNode, type Node } from '@dxos/app-graph';
23
+ import { createExtension, type Graph, isAction, isGraphNode, type Node, type NodeFilter } from '@dxos/app-graph';
24
+ import { invariant } from '@dxos/invariant';
24
25
  import { Keyboard } from '@dxos/keyboard';
25
26
  import { LocalStorageStore } from '@dxos/local-storage';
26
27
  import { Path } from '@dxos/react-ui-mosaic';
27
- import { type OpenItemIds } from '@dxos/react-ui-navtree';
28
+ import { mx } from '@dxos/react-ui-theme';
28
29
  import { getHostPlatform } from '@dxos/util';
29
30
 
30
31
  import {
@@ -38,7 +39,14 @@ import {
38
39
  import { CommandsTrigger } from './components/CommandsTrigger';
39
40
  import meta, { KEY_BINDING, NAVTREE_PLUGIN } from './meta';
40
41
  import translations from './translations';
41
- import { expandOpenGraphNodes, getActions, getChildren, type NavTreeItem, type NavTreeItemGraphNode } from './util';
42
+ import { type NavTreeItem } from './types';
43
+ import {
44
+ expandOpenGraphNodes,
45
+ getActions,
46
+ getChildren,
47
+ treeItemsFromRootNode,
48
+ type NavTreeItemGraphNode,
49
+ } from './util';
42
50
 
43
51
  export type NavTreePluginProvides = SurfaceProvides &
44
52
  MetadataRecordsProvides &
@@ -46,41 +54,99 @@ export type NavTreePluginProvides = SurfaceProvides &
46
54
  TranslationsProvides &
47
55
  IntentResolverProvides;
48
56
 
49
- type NavTreeState = { root?: NavTreeItemGraphNode; openItemIds: OpenItemIds };
57
+ type NavTreeState = {
58
+ root?: NavTreeItemGraphNode;
59
+ flatTree: NavTreeItem[];
60
+ open: string[];
61
+ };
50
62
 
51
63
  export const NavTreePlugin = (): PluginDefinition<NavTreePluginProvides> => {
64
+ let graphPlugin: Plugin<GraphProvides> | undefined;
65
+ let graph: Graph | undefined;
66
+ const itemCache = new Map<string, NavTreeItem>();
67
+
52
68
  const state = new LocalStorageStore<NavTreeState>('dxos.org/settings/navtree', {
69
+ root: undefined,
70
+ get flatTree() {
71
+ if (!this.root || !graph) {
72
+ return [];
73
+ }
74
+
75
+ return treeItemsFromRootNode(graph, this.root, this.open, getItem);
76
+ },
53
77
  // TODO(thure): Do this dynamically.
54
- openItemIds: { root: true, 'dxos.org/plugin/space-spaces': true, 'dxos.org/plugin/files': true },
78
+ open: ['root', 'root~dxos.org/plugin/space-spaces', 'root~dxos.org/plugin/files'],
55
79
  });
56
80
 
57
- let graphPlugin: Plugin<GraphProvides> | undefined;
58
- let graph: Graph | undefined;
81
+ const getItem = (node: NavTreeItemGraphNode, parent: readonly string[], filter?: NodeFilter) => {
82
+ invariant(graph);
83
+ const path = [...parent, node.id];
84
+ const { actions, groupedActions } = getActions(graph, node);
85
+ const children = getChildren(graph, node, filter, path);
86
+ const parentOf =
87
+ children.length > 0 ? children.map(({ id }) => id) : node.properties.role === 'branch' ? [] : undefined;
88
+ const item = {
89
+ id: node.id,
90
+ label: node.properties.label ?? node.id,
91
+ icon: node.properties.icon,
92
+ disabled: node.properties.disabled,
93
+ testId: node.properties.testId,
94
+ className: mx(node.properties.modified && 'italic', node.properties.className),
95
+ headingClassName: node.properties.headingClassName,
96
+ path,
97
+ parentOf,
98
+ node,
99
+ actions,
100
+ groupedActions,
101
+ } satisfies NavTreeItem;
59
102
 
60
- const handleOpenItemIdsChange = (nextOpenItemIds: OpenItemIds) => {
103
+ const cachedItem = itemCache.get(node.id);
104
+ // TODO(wittjosiah): This is not a good enough check.
105
+ // Consider better ways to doing reactive transformations which retain referential equality.
106
+ if (cachedItem && JSON.stringify(item) === JSON.stringify(cachedItem)) {
107
+ return cachedItem;
108
+ } else {
109
+ itemCache.set(node.id, item);
110
+ return item;
111
+ }
112
+ };
113
+
114
+ const handleOpenChange = (item: NavTreeItem, open: boolean) => {
115
+ const path = Path.create(...item.path);
61
116
  // TODO(thure): This might become a localstorage leak; openItemIds that no longer exist should be removed from this map.
62
- state.values.openItemIds = nextOpenItemIds;
117
+ if (open) {
118
+ state.values.open.push(path);
119
+ } else {
120
+ const index = state.values.open.indexOf(path);
121
+ if (index > -1) {
122
+ state.values.open.splice(index, 1);
123
+ }
124
+ }
125
+
63
126
  if (graph) {
64
- void expandOpenGraphNodes(graph, nextOpenItemIds);
127
+ void expandOpenGraphNodes(graph, state.values.open);
65
128
  }
66
129
  };
67
130
 
68
131
  return {
69
132
  meta,
70
133
  ready: async (plugins) => {
134
+ state.prop({ key: 'open', type: LocalStorageStore.json<string[]>() });
135
+
71
136
  graphPlugin = resolvePlugin(plugins, parseGraphPlugin);
72
137
  graph = graphPlugin?.provides.graph;
73
138
  if (!graph) {
74
139
  return;
75
140
  }
76
141
 
77
- state.values.root = graph.root as NavTreeItemGraphNode;
78
- getChildren(graph, state.values.root);
79
- getActions(graph, state.values.root);
80
-
81
- state.prop({ key: 'openItemIds', storageKey: 'openItemIds', type: LocalStorageStore.json<OpenItemIds>() });
142
+ const dispatch = resolvePlugin(plugins, parseIntentPlugin)?.provides.intent.dispatch;
143
+ const soloPart = resolvePlugin(plugins, parseNavigationPlugin)?.provides.location.active.solo?.[0];
144
+ if (dispatch && soloPart) {
145
+ void dispatch({ plugin: NAVTREE_PLUGIN, action: NavigationAction.EXPOSE, data: { id: soloPart.id } });
146
+ }
82
147
 
83
- void expandOpenGraphNodes(graph, state.values.openItemIds);
148
+ state.values.root = graph.root as NavTreeItemGraphNode;
149
+ void expandOpenGraphNodes(graph, state.values.open);
84
150
 
85
151
  // TODO(wittjosiah): Factor out.
86
152
  // TODO(wittjosiah): Handle removal of actions.
@@ -148,19 +214,15 @@ export const NavTreePlugin = (): PluginDefinition<NavTreePluginProvides> => {
148
214
 
149
215
  switch (role) {
150
216
  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;
217
+ return (
218
+ <NavTreeContainer
219
+ items={state.values.flatTree}
220
+ current={data.activeIds as string[]}
221
+ open={state.values.open}
222
+ onOpenChange={handleOpenChange}
223
+ popoverAnchorId={data.popoverAnchorId as string}
224
+ />
225
+ );
164
226
 
165
227
  case 'document-title': {
166
228
  return <NavTreeDocumentTitle node={isGraphNode(data.activeNode) ? data.activeNode : undefined} />;
@@ -201,17 +263,14 @@ export const NavTreePlugin = (): PluginDefinition<NavTreePluginProvides> => {
201
263
  if (graph && intent.data?.id) {
202
264
  const path = graph.getPath({ target: intent.data.id });
203
265
  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));
206
- if (itemId.length > 0) {
207
- acc[itemId] = true;
266
+ const additionalOpenItems = [...Array(path.length)].reduce((acc: string[], _, index) => {
267
+ const itemId = Path.create(...path.slice(0, index));
268
+ if (itemId.length > 0 && !state.values.open.includes(itemId)) {
269
+ acc.push(itemId);
208
270
  }
209
271
  return acc;
210
- }, {});
211
- state.values.openItemIds = {
212
- ...additionalOpenItems,
213
- ...state.values.openItemIds,
214
- };
272
+ }, []);
273
+ state.values.open.push(...additionalOpenItems);
215
274
  }
216
275
  }
217
276
  break;
@@ -243,8 +302,7 @@ export const NavTreePlugin = (): PluginDefinition<NavTreePluginProvides> => {
243
302
  },
244
303
  properties: {
245
304
  label: ['open commands label', { ns: NAVTREE_PLUGIN }],
246
- icon: (props: IconProps) => <MagnifyingGlass {...props} />,
247
- iconSymbol: 'ph--magnifying-glass--regular',
305
+ icon: 'ph--magnifying-glass--regular',
248
306
  keyBinding: {
249
307
  macos: 'meta+k',
250
308
  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 = {};