@dxos/plugin-navtree 0.7.5-labs.e27f9b9 → 0.7.5-labs.f400bbc

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 (59) hide show
  1. package/dist/lib/browser/{chunk-54MPRXMH.mjs → chunk-GXNOX2XZ.mjs} +232 -79
  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-LNRTNSM6.mjs → react-surface-SG4QBA2U.mjs} +2 -2
  7. package/dist/lib/browser/{state-65TQKYX7.mjs → state-IEFQTUPG.mjs} +2 -2
  8. package/dist/lib/browser/state-IEFQTUPG.mjs.map +7 -0
  9. package/dist/types/src/capabilities/app-graph-builder.d.ts +110 -110
  10. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
  11. package/dist/types/src/capabilities/index.d.ts +124 -124
  12. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  13. package/dist/types/src/components/CommandsDialog.d.ts +1 -2
  14. package/dist/types/src/components/CommandsDialog.d.ts.map +1 -1
  15. package/dist/types/src/components/CommandsTrigger.d.ts +1 -2
  16. package/dist/types/src/components/CommandsTrigger.d.ts.map +1 -1
  17. package/dist/types/src/components/HaloButton.d.ts +1 -2
  18. package/dist/types/src/components/HaloButton.d.ts.map +1 -1
  19. package/dist/types/src/components/HaloButton.stories.d.ts +1 -2
  20. package/dist/types/src/components/HaloButton.stories.d.ts.map +1 -1
  21. package/dist/types/src/components/L0Menu.d.ts +1 -2
  22. package/dist/types/src/components/L0Menu.d.ts.map +1 -1
  23. package/dist/types/src/components/L1Panels.d.ts +8 -3
  24. package/dist/types/src/components/L1Panels.d.ts.map +1 -1
  25. package/dist/types/src/components/NavTree.d.ts +1 -2
  26. package/dist/types/src/components/NavTree.d.ts.map +1 -1
  27. package/dist/types/src/components/NavTreeContainer.d.ts +1 -1
  28. package/dist/types/src/components/NavTreeContainer.d.ts.map +1 -1
  29. package/dist/types/src/components/NavTreeItemAction.d.ts +4 -4
  30. package/dist/types/src/components/NavTreeItemAction.d.ts.map +1 -1
  31. package/dist/types/src/components/NavTreeItemAction.stories.d.ts +2 -2
  32. package/dist/types/src/components/NavTreeItemColumns.d.ts +1 -1
  33. package/dist/types/src/components/NavTreeItemColumns.d.ts.map +1 -1
  34. package/dist/types/src/components/NotchStart.d.ts +1 -2
  35. package/dist/types/src/components/NotchStart.d.ts.map +1 -1
  36. package/dist/types/src/components/types.d.ts +2 -1
  37. package/dist/types/src/components/types.d.ts.map +1 -1
  38. package/dist/types/src/experimental/Tree.d.ts +8 -8
  39. package/dist/types/src/experimental/Tree.d.ts.map +1 -1
  40. package/dist/types/src/experimental/Tree.stories.d.ts +2 -3
  41. package/dist/types/src/experimental/Tree.stories.d.ts.map +1 -1
  42. package/dist/types/src/stories/StorybookNavTree.d.ts +1 -2
  43. package/dist/types/src/stories/StorybookNavTree.d.ts.map +1 -1
  44. package/dist/types/src/util.d.ts +1 -1
  45. package/package.json +31 -31
  46. package/src/NavTreePlugin.tsx +2 -2
  47. package/src/capabilities/state.ts +1 -1
  48. package/src/components/L0Menu.tsx +177 -55
  49. package/src/components/L1Panels.tsx +25 -6
  50. package/src/components/NavTree.stories.tsx +1 -1
  51. package/src/components/NavTree.tsx +3 -3
  52. package/src/components/NavTreeContainer.tsx +9 -2
  53. package/src/components/types.ts +12 -10
  54. package/src/hooks.ts +1 -1
  55. package/src/stories/Graph.stories.tsx +1 -1
  56. package/src/util.ts +2 -2
  57. package/dist/lib/browser/chunk-54MPRXMH.mjs.map +0 -7
  58. package/dist/lib/browser/state-65TQKYX7.mjs.map +0 -7
  59. /package/dist/lib/browser/{react-surface-LNRTNSM6.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.e27f9b9",
3
+ "version": "0.7.5-labs.f400bbc",
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,29 +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.e27f9b9",
32
- "@dxos/async": "0.7.5-labs.e27f9b9",
33
- "@dxos/app-graph": "0.7.5-labs.e27f9b9",
34
- "@dxos/debug": "0.7.5-labs.e27f9b9",
35
- "@dxos/echo-schema": "0.7.5-labs.e27f9b9",
36
- "@dxos/invariant": "0.7.5-labs.e27f9b9",
37
- "@dxos/keyboard": "0.7.5-labs.e27f9b9",
38
- "@dxos/local-storage": "0.7.5-labs.e27f9b9",
39
- "@dxos/live-object": "0.7.5-labs.e27f9b9",
40
- "@dxos/log": "0.7.5-labs.e27f9b9",
41
- "@dxos/plugin-graph": "0.7.5-labs.e27f9b9",
42
- "@dxos/plugin-observability": "0.7.5-labs.e27f9b9",
43
- "@dxos/plugin-client": "0.7.5-labs.e27f9b9",
44
- "@dxos/plugin-theme": "0.7.5-labs.e27f9b9",
45
- "@dxos/protocols": "0.7.5-labs.e27f9b9",
46
- "@dxos/react-ui-list": "0.7.5-labs.e27f9b9",
47
- "@dxos/react-client": "0.7.5-labs.e27f9b9",
48
- "@dxos/react-ui-menu": "0.7.5-labs.e27f9b9",
49
- "@dxos/react-ui-mosaic": "0.7.5-labs.e27f9b9",
50
- "@dxos/react-ui-searchlist": "0.7.5-labs.e27f9b9",
51
- "@dxos/react-ui-stack": "0.7.5-labs.e27f9b9",
52
- "@dxos/util": "0.7.5-labs.e27f9b9",
53
- "@dxos/react-ui-tabs": "0.7.5-labs.e27f9b9"
32
+ "@dxos/app-framework": "0.7.5-labs.f400bbc",
33
+ "@dxos/app-graph": "0.7.5-labs.f400bbc",
34
+ "@dxos/async": "0.7.5-labs.f400bbc",
35
+ "@dxos/debug": "0.7.5-labs.f400bbc",
36
+ "@dxos/echo-schema": "0.7.5-labs.f400bbc",
37
+ "@dxos/invariant": "0.7.5-labs.f400bbc",
38
+ "@dxos/live-object": "0.7.5-labs.f400bbc",
39
+ "@dxos/keyboard": "0.7.5-labs.f400bbc",
40
+ "@dxos/local-storage": "0.7.5-labs.f400bbc",
41
+ "@dxos/plugin-client": "0.7.5-labs.f400bbc",
42
+ "@dxos/log": "0.7.5-labs.f400bbc",
43
+ "@dxos/plugin-observability": "0.7.5-labs.f400bbc",
44
+ "@dxos/protocols": "0.7.5-labs.f400bbc",
45
+ "@dxos/plugin-graph": "0.7.5-labs.f400bbc",
46
+ "@dxos/react-ui-list": "0.7.5-labs.f400bbc",
47
+ "@dxos/plugin-theme": "0.7.5-labs.f400bbc",
48
+ "@dxos/react-client": "0.7.5-labs.f400bbc",
49
+ "@dxos/react-ui-searchlist": "0.7.5-labs.f400bbc",
50
+ "@dxos/react-ui-stack": "0.7.5-labs.f400bbc",
51
+ "@dxos/util": "0.7.5-labs.f400bbc",
52
+ "@dxos/react-ui-menu": "0.7.5-labs.f400bbc",
53
+ "@dxos/react-ui-tabs": "0.7.5-labs.f400bbc"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@phosphor-icons/react": "^2.1.5",
@@ -59,18 +59,18 @@
59
59
  "react": "~18.2.0",
60
60
  "react-dom": "~18.2.0",
61
61
  "vite": "5.4.7",
62
- "@dxos/echo-signals": "0.7.5-labs.e27f9b9",
63
- "@dxos/random": "0.7.5-labs.e27f9b9",
64
- "@dxos/react-ui": "0.7.5-labs.e27f9b9",
65
- "@dxos/react-ui-theme": "0.7.5-labs.e27f9b9",
66
- "@dxos/storybook-utils": "0.7.5-labs.e27f9b9"
62
+ "@dxos/echo-signals": "0.7.5-labs.f400bbc",
63
+ "@dxos/react-ui-theme": "0.7.5-labs.f400bbc",
64
+ "@dxos/react-ui": "0.7.5-labs.f400bbc",
65
+ "@dxos/random": "0.7.5-labs.f400bbc",
66
+ "@dxos/storybook-utils": "0.7.5-labs.f400bbc"
67
67
  },
68
68
  "peerDependencies": {
69
69
  "@phosphor-icons/react": "^2.1.5",
70
70
  "react": "~18.2.0",
71
71
  "react-dom": "~18.2.0",
72
- "@dxos/react-ui": "0.7.5-labs.e27f9b9",
73
- "@dxos/react-ui-theme": "0.7.5-labs.e27f9b9"
72
+ "@dxos/react-ui": "0.7.5-labs.f400bbc",
73
+ "@dxos/react-ui-theme": "0.7.5-labs.f400bbc"
74
74
  },
75
75
  "publishConfig": {
76
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({
@@ -6,7 +6,7 @@ import { effect } from '@preact/signals-core';
6
6
 
7
7
  import { Capabilities, contributes, type PluginsContext } from '@dxos/app-framework';
8
8
  import { type ReactiveObject, create } from '@dxos/live-object';
9
- import { Path } from '@dxos/react-ui-mosaic';
9
+ import { Path } from '@dxos/react-ui-list';
10
10
 
11
11
  import { NavTreeCapabilities } from './capabilities';
12
12
  import { NAVTREE_PLUGIN } from '../meta';
@@ -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);
@@ -85,50 +112,119 @@ const L0Item = ({ item, parent, path, pinned }: L0ItemProps) => {
85
112
  ? { onClick: handleClick, 'data-testid': testId, 'data-itemid': id }
86
113
  : { onClick: handleClick };
87
114
  const localizedString = toLocalizedString(item.properties.label, t);
115
+ const hue = item.properties.hue ?? null;
88
116
  const avatarValue = useMemo(
89
- () => (type === 'tab' ? getFirstTwoRenderableChars(localizedString).join('') : []),
117
+ () => (type === 'tab' ? getFirstTwoRenderableChars(localizedString).join('').toUpperCase() : []),
90
118
  [type, item.properties.label, t],
91
119
  );
120
+ const hueFgStyle = hue && { style: { color: `var(--dx-${hue}SurfaceText)` } };
92
121
 
93
- return (
94
- <Tooltip.Root delayDuration={0}>
95
- <Tooltip.Trigger asChild>
96
- <Root
97
- {...(rootProps as any)}
98
- data-type={type}
99
- className={mx(
100
- 'group/l0i dx-focus-ring-group grid overflow-hidden relative data[type!="collection"]:cursor-pointer app-no-drag',
101
- l0Breakpoints[item.properties.l0Breakpoint],
102
- )}
103
- >
104
- {type !== 'collection' && (
105
- <div
106
- role='none'
107
- className={mx(
108
- 'absolute -z-[1] group-hover/l0i:bg-input dx-focus-ring-group-indicator transition-colors',
109
- type === 'tab' || pinned ? 'rounded' : 'rounded-full',
110
- pinned ? 'bg-transparent inset-inline-3 inset-block-0' : 'bg-input inset-inline-3 inset-block-2',
111
- )}
112
- />
113
- )}
114
- <div
115
- role='none'
116
- className='hidden group-aria-selected/l0i:block absolute inline-start-0 inset-block-4 is-1 bg-accentSurface rounded-ie'
117
- />
118
- {type === 'tab' && item.properties.disposition !== 'pin-end' ? (
119
- <span role='img' className='place-self-center text-3xl font-light'>
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}>
120
204
  {avatarValue}
121
205
  </span>
122
206
  ) : (
123
207
  item.properties.icon && (
124
- <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} />
125
209
  )
126
- )}
127
- <span id={`${item.id}__label`} className='sr-only'>
128
- {localizedString}
129
- </span>
130
- </Root>
131
- </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>
132
228
  <Tooltip.Portal>
133
229
  <Tooltip.Content side='right'>
134
230
  {localizedString}
@@ -145,6 +241,21 @@ const L0Collection = ({ item, path, parent }: L0ItemProps) => {
145
241
  const collectionItems = navTreeContext.getItems(item);
146
242
  const groupPath = useMemo(() => [...path, item.id], [item.id, path]);
147
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
+ );
148
259
  return (
149
260
  <div
150
261
  role='group'
@@ -153,10 +264,14 @@ const L0Collection = ({ item, path, parent }: L0ItemProps) => {
153
264
  data-itemid={id}
154
265
  data-testid={testId}
155
266
  >
156
- {/* TODO(burdon): Option. */}
157
- {/* <L0Item item={item} parent={parent} path={groupPath} /> */}
158
267
  {collectionItems.map((collectionItem) => (
159
- <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
+ />
160
275
  ))}
161
276
  </div>
162
277
  );
@@ -174,19 +289,26 @@ export const L0Menu = ({
174
289
  path: string[];
175
290
  }) => {
176
291
  return (
177
- <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'>
178
- <div
179
- role='none'
180
- 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)]'
181
- >
182
- {topLevelItems.map((item) => {
183
- if (l0ItemType(item) === 'collection') {
184
- return <L0Collection key={item.id} item={item} parent={parent} path={path} />;
185
- } else {
186
- return <L0Item key={item.id} item={item} parent={parent} path={path} />;
187
- }
188
- })}
189
- </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>
190
312
  <div role='none' className='grid grid-cols-1 auto-rows-[--rail-action] pbs-2'>
191
313
  {pinnedItems
192
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
  }
@@ -13,7 +13,7 @@ import { isActionLike, type NodeArg } from '@dxos/app-graph';
13
13
  import { create, type ReactiveObject } from '@dxos/live-object';
14
14
  import { faker } from '@dxos/random';
15
15
  import { isTreeData, type TreeData } from '@dxos/react-ui-list';
16
- import { Path } from '@dxos/react-ui-mosaic';
16
+ import { Path } from '@dxos/react-ui-list';
17
17
  import { withLayout, withTheme } from '@dxos/storybook-utils';
18
18
 
19
19
  import { StorybookNavTree } from '../stories/StorybookNavTree';