@dxos/plugin-navtree 0.7.5-labs.c0e040f → 0.7.5-labs.d199c0f

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 (52) hide show
  1. package/dist/lib/browser/{chunk-SKZPY4LJ.mjs → chunk-GXNOX2XZ.mjs} +222 -80
  2. package/dist/lib/browser/chunk-GXNOX2XZ.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +3 -3
  4. package/dist/lib/browser/index.mjs.map +2 -2
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/{react-surface-OZDS36WN.mjs → react-surface-SG4QBA2U.mjs} +2 -2
  7. package/dist/types/src/capabilities/app-graph-builder.d.ts +110 -110
  8. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
  9. package/dist/types/src/capabilities/index.d.ts +124 -124
  10. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  11. package/dist/types/src/components/CommandsDialog.d.ts +1 -2
  12. package/dist/types/src/components/CommandsDialog.d.ts.map +1 -1
  13. package/dist/types/src/components/CommandsTrigger.d.ts +1 -2
  14. package/dist/types/src/components/CommandsTrigger.d.ts.map +1 -1
  15. package/dist/types/src/components/HaloButton.d.ts +1 -2
  16. package/dist/types/src/components/HaloButton.d.ts.map +1 -1
  17. package/dist/types/src/components/HaloButton.stories.d.ts +1 -2
  18. package/dist/types/src/components/HaloButton.stories.d.ts.map +1 -1
  19. package/dist/types/src/components/L0Menu.d.ts +1 -2
  20. package/dist/types/src/components/L0Menu.d.ts.map +1 -1
  21. package/dist/types/src/components/L1Panels.d.ts +8 -3
  22. package/dist/types/src/components/L1Panels.d.ts.map +1 -1
  23. package/dist/types/src/components/NavTree.d.ts +1 -2
  24. package/dist/types/src/components/NavTree.d.ts.map +1 -1
  25. package/dist/types/src/components/NavTreeContainer.d.ts +1 -1
  26. package/dist/types/src/components/NavTreeContainer.d.ts.map +1 -1
  27. package/dist/types/src/components/NavTreeItemAction.d.ts +4 -4
  28. package/dist/types/src/components/NavTreeItemAction.d.ts.map +1 -1
  29. package/dist/types/src/components/NavTreeItemAction.stories.d.ts +2 -2
  30. package/dist/types/src/components/NavTreeItemColumns.d.ts +1 -1
  31. package/dist/types/src/components/NavTreeItemColumns.d.ts.map +1 -1
  32. package/dist/types/src/components/NotchStart.d.ts +1 -2
  33. package/dist/types/src/components/NotchStart.d.ts.map +1 -1
  34. package/dist/types/src/components/types.d.ts +2 -1
  35. package/dist/types/src/components/types.d.ts.map +1 -1
  36. package/dist/types/src/experimental/Tree.d.ts +8 -8
  37. package/dist/types/src/experimental/Tree.d.ts.map +1 -1
  38. package/dist/types/src/experimental/Tree.stories.d.ts +2 -3
  39. package/dist/types/src/experimental/Tree.stories.d.ts.map +1 -1
  40. package/dist/types/src/stories/StorybookNavTree.d.ts +1 -2
  41. package/dist/types/src/stories/StorybookNavTree.d.ts.map +1 -1
  42. package/dist/types/src/util.d.ts +1 -1
  43. package/package.json +31 -30
  44. package/src/NavTreePlugin.tsx +2 -2
  45. package/src/components/L0Menu.tsx +176 -62
  46. package/src/components/L1Panels.tsx +25 -6
  47. package/src/components/NavTree.tsx +3 -3
  48. package/src/components/NavTreeContainer.tsx +9 -2
  49. package/src/components/types.ts +12 -10
  50. package/src/hooks.ts +1 -1
  51. package/dist/lib/browser/chunk-SKZPY4LJ.mjs.map +0 -7
  52. /package/dist/lib/browser/{react-surface-OZDS36WN.mjs.map → react-surface-SG4QBA2U.mjs.map} +0 -0
@@ -2,6 +2,7 @@ import type { FC } from 'react';
2
2
  import type { Node } from '@dxos/app-graph';
3
3
  import type { TreeProps } from '@dxos/react-ui-list';
4
4
  import type { MaybePromise } from '@dxos/util';
5
+ import { type L1PanelProps } from './L1Panels';
5
6
  import type { FlattenedActions, NavTreeItemGraphNode } from '../types';
6
7
  export type NavTreeItemColumnsProps = {
7
8
  path: string[];
@@ -9,7 +10,7 @@ export type NavTreeItemColumnsProps = {
9
10
  open: boolean;
10
11
  };
11
12
  export type NavTreeProps = Pick<TreeProps<NavTreeItemGraphNode>, 'id' | 'root'>;
12
- export type NavTreeContextValue = Pick<TreeProps<NavTreeItemGraphNode>, 'getProps' | 'isCurrent' | 'isOpen' | 'onOpenChange' | 'canDrop' | 'onSelect'> & {
13
+ export type NavTreeContextValue = Pick<TreeProps<NavTreeItemGraphNode>, 'getProps' | 'isCurrent' | 'isOpen' | 'onOpenChange' | 'canDrop' | 'onSelect'> & Pick<L1PanelProps, 'onBack'> & {
13
14
  tab: string;
14
15
  onTabChange?: (node: NavTreeItemGraphNode) => void;
15
16
  getItems: (node?: NavTreeItemGraphNode, disposition?: string) => NavTreeItemGraphNode[];
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/components/types.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAEhC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAEvE,MAAM,MAAM,uBAAuB,GAAG;IACpC,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,IAAI,EAAE,IAAI,CAAC;IACX,IAAI,EAAE,OAAO,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,oBAAoB,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC,CAAC;AAEhF,MAAM,MAAM,mBAAmB,GAAG,IAAI,CACpC,SAAS,CAAC,oBAAoB,CAAC,EAC/B,UAAU,GAAG,WAAW,GAAG,QAAQ,GAAG,cAAc,GAAG,SAAS,GAAG,UAAU,CAC9E,GAAG;IACF,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,oBAAoB,KAAK,IAAI,CAAC;IACnD,QAAQ,EAAE,CAAC,IAAI,CAAC,EAAE,oBAAoB,EAAE,WAAW,CAAC,EAAE,MAAM,KAAK,oBAAoB,EAAE,CAAC;IACxF,UAAU,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,gBAAgB,CAAC;IAC7C,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,YAAY,CAAC,IAAI,CAAC,CAAC;IACrD,aAAa,CAAC,EAAE,EAAE,CAAC;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAClD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/components/types.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAEhC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAEvE,MAAM,MAAM,uBAAuB,GAAG;IACpC,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,IAAI,EAAE,IAAI,CAAC;IACX,IAAI,EAAE,OAAO,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,oBAAoB,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC,CAAC;AAEhF,MAAM,MAAM,mBAAmB,GAAG,IAAI,CACpC,SAAS,CAAC,oBAAoB,CAAC,EAC/B,UAAU,GAAG,WAAW,GAAG,QAAQ,GAAG,cAAc,GAAG,SAAS,GAAG,UAAU,CAC9E,GACC,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,GAAG;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,oBAAoB,KAAK,IAAI,CAAC;IACnD,QAAQ,EAAE,CAAC,IAAI,CAAC,EAAE,oBAAoB,EAAE,WAAW,CAAC,EAAE,MAAM,KAAK,oBAAoB,EAAE,CAAC;IACxF,UAAU,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,gBAAgB,CAAC;IAC7C,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,YAAY,CAAC,IAAI,CAAC,CAAC;IACrD,aAAa,CAAC,EAAE,EAAE,CAAC;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAClD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC"}
@@ -1,11 +1,11 @@
1
1
  import { type Icon, type IconProps } from '@phosphor-icons/react';
2
- import React, { type HTMLAttributes, type PropsWithChildren } from 'react';
2
+ import { type HTMLAttributes, type PropsWithChildren } from 'react';
3
3
  import { type ClassNameValue, type Size } from '@dxos/react-ui';
4
4
  export declare const IconButton: ({ Icon, classNames, size, onClick, ...props }: {
5
5
  Icon: Icon;
6
6
  classNames?: ClassNameValue;
7
7
  size?: Size;
8
- } & Pick<IconProps, "weight"> & Pick<HTMLAttributes<HTMLDivElement>, "onClick">) => React.JSX.Element;
8
+ } & Pick<IconProps, "weight"> & Pick<HTMLAttributes<HTMLDivElement>, "onClick">) => import("react/jsx-runtime").JSX.Element;
9
9
  export type TreeNodeData = {
10
10
  id: string;
11
11
  title: string;
@@ -34,23 +34,23 @@ export type TreeNodeProps = {
34
34
  onChangeSelected?: (id: string, select: boolean) => void;
35
35
  onMenuAction?: (id: string, action: string) => void;
36
36
  };
37
- export declare const Title: ({ node: { title } }: Pick<TreeNodeProps, "node">) => React.JSX.Element;
37
+ export declare const Title: ({ node: { title } }: Pick<TreeNodeProps, "node">) => import("react/jsx-runtime").JSX.Element;
38
38
  export declare const Grid: ({ className, ...props }: PropsWithChildren<{
39
39
  className?: string;
40
- }> & HTMLAttributes<HTMLDivElement>) => React.JSX.Element;
40
+ }> & HTMLAttributes<HTMLDivElement>) => import("react/jsx-runtime").JSX.Element;
41
41
  export declare const TreeNodeRow: (props: TreeNodeProps & {
42
42
  className?: string;
43
- }) => React.JSX.Element;
43
+ }) => import("react/jsx-runtime").JSX.Element;
44
44
  export declare const TreeNode: (props: TreeNodeProps & {
45
45
  ancestors?: TreeNodeData[];
46
- }) => React.JSX.Element;
46
+ }) => import("react/jsx-runtime").JSX.Element;
47
47
  export declare const TreeChildNodes: ({ className, ...props }: TreeNodeProps & {
48
48
  ancestors?: TreeNodeData[];
49
49
  className?: string;
50
- }) => React.JSX.Element;
50
+ }) => import("react/jsx-runtime").JSX.Element;
51
51
  export type TreeProps = {
52
52
  className?: string;
53
53
  showRoot?: boolean;
54
54
  } & TreeNodeProps;
55
- export declare const Tree: ({ className, showRoot, ...props }: TreeProps) => React.JSX.Element;
55
+ export declare const Tree: ({ className, showRoot, ...props }: TreeProps) => import("react/jsx-runtime").JSX.Element;
56
56
  //# sourceMappingURL=Tree.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Tree.d.ts","sourceRoot":"","sources":["../../../../src/experimental/Tree.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Tree.d.ts","sourceRoot":"","sources":["../../../../src/experimental/Tree.tsx"],"names":[],"mappings":"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"}
@@ -1,8 +1,7 @@
1
1
  import '@dxos-theme';
2
2
  import { type Meta } from '@storybook/react';
3
- import { type JSX } from 'react';
4
- export declare const Default: () => JSX.Element;
5
- export declare const Visitor: () => JSX.Element;
3
+ export declare const Default: () => import("react/jsx-runtime").JSX.Element;
4
+ export declare const Visitor: () => import("react/jsx-runtime").JSX.Element;
6
5
  declare const meta: Meta;
7
6
  export default meta;
8
7
  //# sourceMappingURL=Tree.stories.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Tree.stories.d.ts","sourceRoot":"","sources":["../../../../src/experimental/Tree.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,aAAa,CAAC;AAGrB,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAc,EAAE,KAAK,GAAG,EAA+C,MAAM,OAAO,CAAC;AAmGrF,eAAO,MAAM,OAAO,mBAEnB,CAAC;AAEF,eAAO,MAAM,OAAO,mBAenB,CAAC;AAmGF,QAAA,MAAM,IAAI,EAAE,IAIX,CAAC;AAEF,eAAe,IAAI,CAAC"}
1
+ {"version":3,"file":"Tree.stories.d.ts","sourceRoot":"","sources":["../../../../src/experimental/Tree.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,aAAa,CAAC;AAGrB,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAoG7C,eAAO,MAAM,OAAO,+CAEnB,CAAC;AAEF,eAAO,MAAM,OAAO,+CAenB,CAAC;AAmGF,QAAA,MAAM,IAAI,EAAE,IAIX,CAAC;AAEF,eAAe,IAAI,CAAC"}
@@ -1,4 +1,3 @@
1
- import React from 'react';
2
1
  import { type NavTreeContextValue, type NavTreeProps } from '../components';
3
- export declare const StorybookNavTree: ({ getActions, loadDescendents, renderItemEnd, popoverAnchorId, getItems, getProps, isCurrent, canDrop, onSelect, isOpen, onOpenChange, ...props }: NavTreeProps & NavTreeContextValue) => React.JSX.Element;
2
+ export declare const StorybookNavTree: ({ getActions, loadDescendents, renderItemEnd, popoverAnchorId, getItems, getProps, isCurrent, canDrop, onSelect, isOpen, onOpenChange, ...props }: NavTreeProps & NavTreeContextValue) => import("react/jsx-runtime").JSX.Element;
4
3
  //# sourceMappingURL=StorybookNavTree.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"StorybookNavTree.d.ts","sourceRoot":"","sources":["../../../../src/stories/StorybookNavTree.tsx"],"names":[],"mappings":"AAIA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAEjD,OAAO,EAA2B,KAAK,mBAAmB,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAGrG,eAAO,MAAM,gBAAgB,sJAa1B,YAAY,GAAG,mBAAmB,sBAwCpC,CAAC"}
1
+ {"version":3,"file":"StorybookNavTree.d.ts","sourceRoot":"","sources":["../../../../src/stories/StorybookNavTree.tsx"],"names":[],"mappings":"AAMA,OAAO,EAA2B,KAAK,mBAAmB,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAGrG,eAAO,MAAM,gBAAgB,sJAa1B,YAAY,GAAG,mBAAmB,4CAwCpC,CAAC"}
@@ -9,7 +9,7 @@ export declare const getActions: (graph: Graph, node: Node) => FlattenedActions;
9
9
  export declare const expandChildrenAndActions: (graph: Graph, node: Node) => Promise<[void, [void, void]]>;
10
10
  export declare const expandChildren: (graph: Graph, node: Node) => Promise<void>;
11
11
  export declare const expandActions: (graph: Graph, node: Node) => Promise<[void, void]>;
12
- export declare const l0ItemType: (item: Node<any>) => "collection" | "action" | "link" | "tab";
12
+ export declare const l0ItemType: (item: Node<any>) => "link" | "tab" | "collection" | "action";
13
13
  /**
14
14
  * Returns the first two renderable characters from a string that are separated by non-word characters.
15
15
  * Handles Unicode characters correctly.
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@dxos/plugin-navtree",
3
- "version": "0.7.5-labs.c0e040f",
3
+ "version": "0.7.5-labs.d199c0f",
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
9
  "sideEffects": true,
10
+ "type": "module",
10
11
  "exports": {
11
12
  ".": {
12
13
  "types": "./dist/types/src/index.d.ts",
@@ -28,28 +29,28 @@
28
29
  "@radix-ui/react-dismissable-layer": "1.1.5",
29
30
  "@radix-ui/react-use-controllable-state": "1.1.0",
30
31
  "date-fns": "^3.3.1",
31
- "@dxos/app-framework": "0.7.5-labs.c0e040f",
32
- "@dxos/async": "0.7.5-labs.c0e040f",
33
- "@dxos/app-graph": "0.7.5-labs.c0e040f",
34
- "@dxos/debug": "0.7.5-labs.c0e040f",
35
- "@dxos/invariant": "0.7.5-labs.c0e040f",
36
- "@dxos/keyboard": "0.7.5-labs.c0e040f",
37
- "@dxos/live-object": "0.7.5-labs.c0e040f",
38
- "@dxos/local-storage": "0.7.5-labs.c0e040f",
39
- "@dxos/log": "0.7.5-labs.c0e040f",
40
- "@dxos/plugin-client": "0.7.5-labs.c0e040f",
41
- "@dxos/echo-schema": "0.7.5-labs.c0e040f",
42
- "@dxos/plugin-observability": "0.7.5-labs.c0e040f",
43
- "@dxos/plugin-graph": "0.7.5-labs.c0e040f",
44
- "@dxos/plugin-theme": "0.7.5-labs.c0e040f",
45
- "@dxos/protocols": "0.7.5-labs.c0e040f",
46
- "@dxos/react-client": "0.7.5-labs.c0e040f",
47
- "@dxos/react-ui-list": "0.7.5-labs.c0e040f",
48
- "@dxos/react-ui-menu": "0.7.5-labs.c0e040f",
49
- "@dxos/react-ui-searchlist": "0.7.5-labs.c0e040f",
50
- "@dxos/react-ui-stack": "0.7.5-labs.c0e040f",
51
- "@dxos/util": "0.7.5-labs.c0e040f",
52
- "@dxos/react-ui-tabs": "0.7.5-labs.c0e040f"
32
+ "@dxos/app-framework": "0.7.5-labs.d199c0f",
33
+ "@dxos/app-graph": "0.7.5-labs.d199c0f",
34
+ "@dxos/echo-schema": "0.7.5-labs.d199c0f",
35
+ "@dxos/async": "0.7.5-labs.d199c0f",
36
+ "@dxos/debug": "0.7.5-labs.d199c0f",
37
+ "@dxos/invariant": "0.7.5-labs.d199c0f",
38
+ "@dxos/keyboard": "0.7.5-labs.d199c0f",
39
+ "@dxos/live-object": "0.7.5-labs.d199c0f",
40
+ "@dxos/local-storage": "0.7.5-labs.d199c0f",
41
+ "@dxos/log": "0.7.5-labs.d199c0f",
42
+ "@dxos/plugin-client": "0.7.5-labs.d199c0f",
43
+ "@dxos/plugin-graph": "0.7.5-labs.d199c0f",
44
+ "@dxos/plugin-observability": "0.7.5-labs.d199c0f",
45
+ "@dxos/protocols": "0.7.5-labs.d199c0f",
46
+ "@dxos/react-client": "0.7.5-labs.d199c0f",
47
+ "@dxos/react-ui-list": "0.7.5-labs.d199c0f",
48
+ "@dxos/plugin-theme": "0.7.5-labs.d199c0f",
49
+ "@dxos/react-ui-menu": "0.7.5-labs.d199c0f",
50
+ "@dxos/react-ui-searchlist": "0.7.5-labs.d199c0f",
51
+ "@dxos/react-ui-stack": "0.7.5-labs.d199c0f",
52
+ "@dxos/react-ui-tabs": "0.7.5-labs.d199c0f",
53
+ "@dxos/util": "0.7.5-labs.d199c0f"
53
54
  },
54
55
  "devDependencies": {
55
56
  "@phosphor-icons/react": "^2.1.5",
@@ -58,18 +59,18 @@
58
59
  "react": "~18.2.0",
59
60
  "react-dom": "~18.2.0",
60
61
  "vite": "5.4.7",
61
- "@dxos/echo-signals": "0.7.5-labs.c0e040f",
62
- "@dxos/random": "0.7.5-labs.c0e040f",
63
- "@dxos/react-ui": "0.7.5-labs.c0e040f",
64
- "@dxos/react-ui-theme": "0.7.5-labs.c0e040f",
65
- "@dxos/storybook-utils": "0.7.5-labs.c0e040f"
62
+ "@dxos/echo-signals": "0.7.5-labs.d199c0f",
63
+ "@dxos/random": "0.7.5-labs.d199c0f",
64
+ "@dxos/react-ui": "0.7.5-labs.d199c0f",
65
+ "@dxos/storybook-utils": "0.7.5-labs.d199c0f",
66
+ "@dxos/react-ui-theme": "0.7.5-labs.d199c0f"
66
67
  },
67
68
  "peerDependencies": {
68
69
  "@phosphor-icons/react": "^2.1.5",
69
70
  "react": "~18.2.0",
70
71
  "react-dom": "~18.2.0",
71
- "@dxos/react-ui": "0.7.5-labs.c0e040f",
72
- "@dxos/react-ui-theme": "0.7.5-labs.c0e040f"
72
+ "@dxos/react-ui-theme": "0.7.5-labs.d199c0f",
73
+ "@dxos/react-ui": "0.7.5-labs.d199c0f"
73
74
  },
74
75
  "publishConfig": {
75
76
  "access": "public"
@@ -74,12 +74,12 @@ export const NavTreePlugin = () =>
74
74
  }),
75
75
  defineModule({
76
76
  id: `${meta.id}/module/react-surface`,
77
- activatesOn: Events.SetupSurfaces,
77
+ activatesOn: Events.SetupReactSurface,
78
78
  activate: ReactSurface,
79
79
  }),
80
80
  defineModule({
81
81
  id: `${meta.id}/module/intent-resolver`,
82
- activatesOn: Events.SetupIntents,
82
+ activatesOn: Events.SetupIntentResolver,
83
83
  activate: IntentResolver,
84
84
  }),
85
85
  defineModule({
@@ -2,13 +2,35 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import React, { type MouseEvent, useCallback, useMemo } from 'react';
5
+ import { combine } from '@atlaskit/pragmatic-drag-and-drop/combine';
6
+ import { draggable, dropTargetForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
7
+ import { preserveOffsetOnSource } from '@atlaskit/pragmatic-drag-and-drop/element/preserve-offset-on-source';
8
+ import { scrollJustEnoughIntoView } from '@atlaskit/pragmatic-drag-and-drop/element/scroll-just-enough-into-view';
9
+ import {
10
+ attachClosestEdge,
11
+ type Edge,
12
+ extractClosestEdge,
13
+ } from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge';
14
+ import React, { type MouseEvent, useCallback, useLayoutEffect, useMemo, useRef, useState } from 'react';
6
15
 
7
16
  import { createIntent, LayoutAction, useIntentDispatcher } from '@dxos/app-framework';
8
17
  import { type Node } from '@dxos/app-graph';
9
- import { Icon, toLocalizedString, Tooltip, useMediaQuery, useSidebars, useTranslation } from '@dxos/react-ui';
18
+ import { invariant } from '@dxos/invariant';
19
+ import {
20
+ Popover,
21
+ ScrollArea,
22
+ toLocalizedString,
23
+ Tooltip,
24
+ useMediaQuery,
25
+ useSidebars,
26
+ useTranslation,
27
+ ListItem,
28
+ Icon,
29
+ } from '@dxos/react-ui';
30
+ import type { StackItemRearrangeHandler } from '@dxos/react-ui-stack';
10
31
  import { Tabs } from '@dxos/react-ui-tabs';
11
32
  import { mx } from '@dxos/react-ui-theme';
33
+ import { arrayMove } from '@dxos/util';
12
34
 
13
35
  import { useNavTreeContext } from './NavTreeContext';
14
36
  import { NotchStart } from './NotchStart';
@@ -16,11 +38,14 @@ import { useLoadDescendents } from '../hooks';
16
38
  import { NAVTREE_PLUGIN } from '../meta';
17
39
  import { getFirstTwoRenderableChars, l0ItemType } from '../util';
18
40
 
41
+ type L0ItemData = { id: L0ItemProps['item']['id']; type: 'l0Item' };
42
+
19
43
  type L0ItemProps = {
20
44
  item: Node<any>;
21
45
  parent?: Node<any>;
22
46
  path: string[];
23
47
  pinned?: boolean;
48
+ onRearrange?: StackItemRearrangeHandler<L0ItemData>;
24
49
  };
25
50
 
26
51
  const useL0ItemClick = ({ item, parent, path }: L0ItemProps, type: string) => {
@@ -70,11 +95,13 @@ const l0Breakpoints: Record<string, string> = {
70
95
  lg: 'hidden lg:grid',
71
96
  };
72
97
 
73
- const L0Item = ({ item, parent, path, pinned }: L0ItemProps) => {
98
+ const L0Item = ({ item, parent, path, pinned, onRearrange }: L0ItemProps) => {
74
99
  const { t } = useTranslation(NAVTREE_PLUGIN);
100
+ const itemElement = useRef<HTMLElement | null>(null);
101
+ const [closestEdge, setEdge] = useState<Edge | null>(null);
75
102
  const type = l0ItemType(item);
76
103
  const itemPath = useMemo(() => [...path, item.id], [item.id, path]);
77
- const { getProps } = useNavTreeContext();
104
+ const { getProps, popoverAnchorId } = useNavTreeContext();
78
105
  const { id, testId } = getProps?.(item, path) ?? {};
79
106
  const Root = type === 'collection' ? 'h2' : type === 'tab' ? Tabs.TabPrimitive : 'button';
80
107
  const handleClick = useL0ItemClick({ item, path: itemPath, parent }, type);
@@ -87,56 +114,117 @@ const L0Item = ({ item, parent, path, pinned }: L0ItemProps) => {
87
114
  const localizedString = toLocalizedString(item.properties.label, t);
88
115
  const hue = item.properties.hue ?? null;
89
116
  const avatarValue = useMemo(
90
- () => (type === 'tab' ? getFirstTwoRenderableChars(localizedString).join('') : []),
117
+ () => (type === 'tab' ? getFirstTwoRenderableChars(localizedString).join('').toUpperCase() : []),
91
118
  [type, item.properties.label, t],
92
119
  );
120
+ const hueFgStyle = hue && { style: { color: `var(--dx-${hue}SurfaceText)` } };
93
121
 
94
- return (
95
- <Tooltip.Root delayDuration={0}>
96
- <Tooltip.Trigger asChild>
97
- <Root
98
- {...(rootProps as any)}
99
- data-type={type}
100
- className={mx(
101
- 'group/l0i dx-focus-ring-group grid overflow-hidden relative data[type!="collection"]:cursor-pointer app-no-drag',
102
- l0Breakpoints[item.properties.l0Breakpoint],
103
- )}
104
- >
105
- {type !== 'collection' && (
106
- <div
107
- role='none'
108
- className={mx(
109
- 'absolute -z-[1] dx-focus-ring-group-indicator transition-colors',
110
- type === 'tab' || pinned ? 'rounded' : 'rounded-full',
111
- pinned
112
- ? 'bg-transparent group-hover/l0i:bg-groupSurface inset-inline-3 inset-block-0.5'
113
- : 'bg-groupSurface inset-inline-3 inset-block-2',
114
- )}
115
- {...(hue && { style: { background: `var(--dx-${hue}Surface)` } })}
116
- />
117
- )}
118
- <div
119
- role='none'
120
- className='hidden group-aria-selected/l0i:block absolute inline-start-0 inset-block-4 is-1 bg-accentSurface rounded-ie'
121
- />
122
- {type === 'tab' && item.properties.disposition !== 'pin-end' ? (
123
- <span
124
- role='img'
125
- className='place-self-center text-3xl font-light'
126
- {...(hue && { style: { color: `var(--dx-${hue}SurfaceText)` } })}
127
- >
122
+ useLayoutEffect(() => {
123
+ // NOTE(thure): This is copied from StackItem, perhaps this should be DRYed out.
124
+ if (!itemElement.current || !onRearrange) {
125
+ return;
126
+ }
127
+ return combine(
128
+ draggable({
129
+ element: itemElement.current,
130
+ getInitialData: () => ({ id: item.id, type: 'l0Item' }) satisfies L0ItemData,
131
+ onGenerateDragPreview: ({ nativeSetDragImage, source, location }) => {
132
+ document.body.setAttribute('data-drag-preview', 'true');
133
+ const element = source.element.querySelector('[data-frame]') as HTMLElement;
134
+ scrollJustEnoughIntoView({ element });
135
+ const { x, y } = preserveOffsetOnSource({ element, input: location.current.input })({
136
+ container: (element.offsetParent ?? document.body) as HTMLElement,
137
+ });
138
+ nativeSetDragImage?.(element, x, y);
139
+ },
140
+ onDragStart: () => {
141
+ document.body.removeAttribute('data-drag-preview');
142
+ itemElement.current!.closest('[data-drag-autoscroll]')?.setAttribute('data-drag-autoscroll', 'active');
143
+ },
144
+ onDrop: () => {
145
+ itemElement.current!.closest('[data-drag-autoscroll]')?.setAttribute('data-drag-autoscroll', 'idle');
146
+ },
147
+ }),
148
+ dropTargetForElements({
149
+ element: itemElement.current,
150
+ getData: ({ input, element }) => {
151
+ return attachClosestEdge(
152
+ { id: item.id, type: 'l0Item' },
153
+ { input, element, allowedEdges: ['top', 'bottom'] },
154
+ );
155
+ },
156
+ onDragEnter: ({ self, source }) => {
157
+ if (source.data.type === self.data.type) {
158
+ setEdge(extractClosestEdge(self.data));
159
+ }
160
+ },
161
+ onDrag: ({ self, source }) => {
162
+ if (source.data.type === self.data.type) {
163
+ setEdge(extractClosestEdge(self.data));
164
+ }
165
+ },
166
+ onDragLeave: () => setEdge(null),
167
+ onDrop: ({ self, source }) => {
168
+ setEdge(null);
169
+ if (source.data.type === self.data.type) {
170
+ onRearrange(source.data as L0ItemData, self.data as L0ItemData, extractClosestEdge(self.data));
171
+ }
172
+ },
173
+ }),
174
+ );
175
+ }, [item, onRearrange]);
176
+
177
+ const l0ItemTrigger = (
178
+ <Root
179
+ {...(rootProps as any)}
180
+ data-type={type}
181
+ className={mx(
182
+ 'group/l0i dx-focus-ring-group grid relative data[type!="collection"]:cursor-pointer app-no-drag',
183
+ l0Breakpoints[item.properties.l0Breakpoint],
184
+ )}
185
+ ref={itemElement}
186
+ >
187
+ <div
188
+ role='none'
189
+ data-frame={true}
190
+ className={mx(
191
+ 'absolute grid dx-focus-ring-group-indicator transition-colors',
192
+ type === 'tab' || pinned ? 'rounded' : 'rounded-full',
193
+ pinned
194
+ ? 'bg-transparent group-hover/l0i:bg-groupSurface inset-inline-3 inset-block-0.5'
195
+ : 'bg-groupSurface inset-inline-3 inset-block-2',
196
+ )}
197
+ {...(hue && { style: { background: `var(--dx-${hue}Surface)` } })}
198
+ >
199
+ {(item.properties.icon && (
200
+ <Icon icon={item.properties.icon} size={pinned ? 5 : 7} classNames='place-self-center' {...hueFgStyle} />
201
+ )) ||
202
+ (type === 'tab' && item.properties.disposition !== 'pin-end' ? (
203
+ <span role='img' className='place-self-center text-3xl font-light' {...hueFgStyle}>
128
204
  {avatarValue}
129
205
  </span>
130
206
  ) : (
131
207
  item.properties.icon && (
132
- <Icon icon={item.properties.icon} size={pinned ? 5 : 7} classNames='place-self-center' />
208
+ <Icon icon='ph--planet--regular' size={pinned ? 5 : 7} classNames='place-self-center' {...hueFgStyle} />
133
209
  )
134
- )}
135
- <span id={`${item.id}__label`} className='sr-only'>
136
- {localizedString}
137
- </span>
138
- </Root>
139
- </Tooltip.Trigger>
210
+ ))}
211
+ </div>
212
+ <div
213
+ role='none'
214
+ className='hidden group-aria-selected/l0i:block absolute inline-start-0 inset-block-4 is-1 bg-accentSurface rounded-ie'
215
+ />
216
+ <span id={`${item.id}__label`} className='sr-only'>
217
+ {localizedString}
218
+ </span>
219
+ {onRearrange && closestEdge && <ListItem.DropIndicator edge={closestEdge} />}
220
+ </Root>
221
+ );
222
+
223
+ return popoverAnchorId === id ? (
224
+ <Popover.Anchor asChild>{l0ItemTrigger}</Popover.Anchor>
225
+ ) : (
226
+ <Tooltip.Root delayDuration={0}>
227
+ <Tooltip.Trigger asChild>{l0ItemTrigger}</Tooltip.Trigger>
140
228
  <Tooltip.Portal>
141
229
  <Tooltip.Content side='right'>
142
230
  {localizedString}
@@ -153,6 +241,21 @@ const L0Collection = ({ item, path, parent }: L0ItemProps) => {
153
241
  const collectionItems = navTreeContext.getItems(item);
154
242
  const groupPath = useMemo(() => [...path, item.id], [item.id, path]);
155
243
  const { id, testId } = navTreeContext.getProps?.(item, path) ?? {};
244
+ const handleRearrange = useCallback<StackItemRearrangeHandler<L0ItemData>>(
245
+ (source, target, closestEdge) => {
246
+ invariant(item.properties.onRearrangeChildren);
247
+ const sourceIndex = collectionItems.findIndex((i) => i.id === source.id);
248
+ const targetIndex = collectionItems.findIndex((i) => i.id === target.id);
249
+ const insertIndex =
250
+ source.id === target.id
251
+ ? sourceIndex
252
+ : targetIndex +
253
+ (sourceIndex < targetIndex ? (closestEdge === 'top' ? -1 : 0) : closestEdge === 'bottom' ? 1 : 0);
254
+ const nextOrder = arrayMove([...collectionItems], sourceIndex, insertIndex);
255
+ return item.properties.onRearrangeChildren(nextOrder);
256
+ },
257
+ [collectionItems, item.properties.onRearrangeChildren],
258
+ );
156
259
  return (
157
260
  <div
158
261
  role='group'
@@ -161,10 +264,14 @@ const L0Collection = ({ item, path, parent }: L0ItemProps) => {
161
264
  data-itemid={id}
162
265
  data-testid={testId}
163
266
  >
164
- {/* TODO(burdon): Option. */}
165
- {/* <L0Item item={item} parent={parent} path={groupPath} /> */}
166
267
  {collectionItems.map((collectionItem) => (
167
- <L0Item key={collectionItem.id} item={collectionItem} parent={item} path={groupPath} />
268
+ <L0Item
269
+ key={collectionItem.id}
270
+ item={collectionItem}
271
+ parent={item}
272
+ path={groupPath}
273
+ {...(item.properties.onRearrangeChildren && { onRearrange: handleRearrange })}
274
+ />
168
275
  ))}
169
276
  </div>
170
277
  );
@@ -182,19 +289,26 @@ export const L0Menu = ({
182
289
  path: string[];
183
290
  }) => {
184
291
  return (
185
- <Tabs.Tablist classNames='group/l0 absolute z-[1] inset-block-0 inline-start-0 rounded-is-lg grid grid-cols-[var(--l0-size)] grid-rows-[1fr_min-content_var(--l0-size)] contain-layout !is-[--l0-size] bg-baseSurface border-ie border-separator app-drag'>
186
- <div
187
- role='none'
188
- className='grid auto-rows-[calc(var(--l0-size)-.5rem)] min-bs-0 !overflow-y-auto plb-1 [body[data-platform="darwin"]_&]:pbs-[calc(30px+0.25rem)]'
189
- >
190
- {topLevelItems.map((item) => {
191
- if (l0ItemType(item) === 'collection') {
192
- return <L0Collection key={item.id} item={item} parent={parent} path={path} />;
193
- } else {
194
- return <L0Item key={item.id} item={item} parent={parent} path={path} />;
195
- }
196
- })}
197
- </div>
292
+ <Tabs.Tablist classNames='group/l0 absolute z-[1] inset-block-0 inline-start-0 rounded-is-lg grid grid-cols-[var(--l0-size)] grid-rows-[1fr_min-content_var(--l0-size)] contain-layout !is-[--l0-size] bg-baseSurface border-ie border-separator app-drag pbe-[env(safe-area-inset-bottom)]'>
293
+ <ScrollArea.Root>
294
+ <ScrollArea.Viewport>
295
+ <div
296
+ role='none'
297
+ className='grid auto-rows-[calc(var(--l0-size)-.5rem)] plb-1 [body[data-platform="darwin"]_&]:pbs-[calc(30px+0.25rem)] [body[data-platform="ios"]_&]:pbs-[max(env(safe-area-inset-top),0.25rem)]'
298
+ >
299
+ {topLevelItems.map((item) => {
300
+ if (l0ItemType(item) === 'collection') {
301
+ return <L0Collection key={item.id} item={item} parent={parent} path={path} />;
302
+ } else {
303
+ return <L0Item key={item.id} item={item} parent={parent} path={path} />;
304
+ }
305
+ })}
306
+ </div>
307
+ <ScrollArea.Scrollbar orientation='vertical'>
308
+ <ScrollArea.Thumb />
309
+ </ScrollArea.Scrollbar>
310
+ </ScrollArea.Viewport>
311
+ </ScrollArea.Root>
198
312
  <div role='none' className='grid grid-cols-1 auto-rows-[--rail-action] pbs-2'>
199
313
  {pinnedItems
200
314
  .filter((item) => l0ItemType(item) !== 'collection')
@@ -6,9 +6,10 @@ import React, { useMemo } from 'react';
6
6
 
7
7
  import { useLayout } from '@dxos/app-framework';
8
8
  import { type Node } from '@dxos/app-graph';
9
- import { toLocalizedString, useTranslation } from '@dxos/react-ui';
9
+ import { IconButton, toLocalizedString, useTranslation } from '@dxos/react-ui';
10
10
  import { Tree } from '@dxos/react-ui-list';
11
11
  import { Tabs } from '@dxos/react-ui-tabs';
12
+ import { hoverableControlItem, hoverableOpenControlItem, mx } from '@dxos/react-ui-theme';
12
13
 
13
14
  import { useNavTreeContext } from './NavTreeContext';
14
15
  import { NavTreeItemColumns } from './NavTreeItemColumns';
@@ -16,9 +17,9 @@ import { useLoadDescendents } from '../hooks';
16
17
  import { NAVTREE_PLUGIN } from '../meta';
17
18
  import { l0ItemType } from '../util';
18
19
 
19
- type L1PanelProps = { item: Node<any>; path: string[]; currentItemId: string };
20
+ export type L1PanelProps = { item: Node<any>; path: string[]; currentItemId: string; onBack?: () => void };
20
21
 
21
- const L1Panel = ({ item, path, currentItemId }: L1PanelProps) => {
22
+ const L1Panel = ({ item, path, currentItemId, onBack }: L1PanelProps) => {
22
23
  const layout = useLayout();
23
24
  const navTreeContext = useNavTreeContext();
24
25
  const { t } = useTranslation(NAVTREE_PLUGIN);
@@ -27,7 +28,7 @@ const L1Panel = ({ item, path, currentItemId }: L1PanelProps) => {
27
28
  key={item.id}
28
29
  value={item.id}
29
30
  classNames={[
30
- 'absolute inset-block-0 inline-end-0 is-[calc(100%-var(--l0-size))] lg:is-[--l1-size] grid-cols-1 grid-rows-[var(--rail-size)_1fr]',
31
+ 'absolute inset-block-0 inline-end-0 is-[calc(100%-var(--l0-size))] lg:is-[--l1-size] grid-cols-1 grid-rows-[var(--rail-size)_1fr] pbs-[env(safe-area-inset-top)]',
31
32
  item.id === currentItemId && 'grid',
32
33
  ]}
33
34
  tabIndex={-1}
@@ -36,6 +37,23 @@ const L1Panel = ({ item, path, currentItemId }: L1PanelProps) => {
36
37
  {item.id === currentItemId && (
37
38
  <>
38
39
  <h2 className='flex items-center border-be border-separator pis-4 app-drag'>
40
+ {item.properties.disposition === 'pin-end' && (
41
+ <IconButton
42
+ label={t('back label')}
43
+ iconOnly
44
+ icon='ph--caret-left--regular'
45
+ size={5}
46
+ density='fine'
47
+ variant='ghost'
48
+ classNames={mx(
49
+ 'shrink-0 mie-2 !p-0',
50
+ 'pointer-fine:pli-1',
51
+ hoverableControlItem,
52
+ hoverableOpenControlItem,
53
+ )}
54
+ onClick={onBack}
55
+ />
56
+ )}
39
57
  <span className='flex-1 truncate cursor-default'>{toLocalizedString(item.properties.label, t)}</span>
40
58
  <NavTreeItemColumns path={path} item={item} open />
41
59
  </h2>
@@ -77,7 +95,8 @@ export const L1Panels = ({
77
95
  topLevelItems,
78
96
  path,
79
97
  currentItemId,
80
- }: {
98
+ onBack,
99
+ }: Pick<L1PanelProps, 'onBack'> & {
81
100
  topLevelItems: Node<any>[];
82
101
  path: string[];
83
102
  currentItemId: string;
@@ -90,7 +109,7 @@ export const L1Panels = ({
90
109
  case 'collection':
91
110
  return <L1PanelCollection key={item.id} item={item} path={path} currentItemId={currentItemId} />;
92
111
  case 'tab':
93
- return <L1Panel key={item.id} item={item} path={path} currentItemId={currentItemId} />;
112
+ return <L1Panel key={item.id} item={item} path={path} currentItemId={currentItemId} onBack={onBack} />;
94
113
  default:
95
114
  return null;
96
115
  }
@@ -16,8 +16,8 @@ import { useLoadDescendents } from '../hooks';
16
16
  export const NAV_TREE_ITEM = 'NavTreeItem';
17
17
 
18
18
  export const NavTree = ({ id, root }: NavTreeProps) => {
19
- const { getItems, tab } = useNavTreeContext();
20
- const topLevelActions = getItems(root, 'item');
19
+ const { tab, getItems, onBack } = useNavTreeContext();
20
+ const topLevelActions = getItems(root, 'item').toSorted((a, b) => byPosition(a.properties, b.properties));
21
21
  const topLevelCollections = getItems(root, 'collection');
22
22
  const topLevelWorkspaces = getItems(root, 'workspace');
23
23
  const topLevelNavigation = getItems(root, 'navigation');
@@ -35,7 +35,7 @@ export const NavTree = ({ id, root }: NavTreeProps) => {
35
35
  // NOTE(thure): 74px (rather than rem) is intentional in order to match the size of macOS windowing controls
36
36
  <Tabs.Root value={tab} orientation='vertical' verticalVariant='stateless' classNames='relative'>
37
37
  <L0Menu topLevelItems={l0Items} pinnedItems={pinnedItems} path={path} parent={root} />
38
- <L1Panels topLevelItems={topLevelItems} path={path} currentItemId={tab} />
38
+ <L1Panels topLevelItems={topLevelItems} path={path} currentItemId={tab} onBack={onBack} />
39
39
  </Tabs.Root>
40
40
  );
41
41
  };