@dxos/plugin-navtree 0.7.5-labs.e27f9b9 → 0.7.5-main.2567c87
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.
- package/dist/lib/browser/{app-graph-builder-BL7LRXCM.mjs → app-graph-builder-OF4MMBLH.mjs} +5 -7
- package/dist/lib/browser/{app-graph-builder-BL7LRXCM.mjs.map → app-graph-builder-OF4MMBLH.mjs.map} +3 -3
- package/dist/lib/browser/chunk-IMGT2LAL.mjs +658 -0
- package/dist/lib/browser/chunk-IMGT2LAL.mjs.map +7 -0
- package/dist/lib/browser/{chunk-AOAGODQB.mjs → chunk-OI7AAA6Q.mjs} +1 -1
- package/dist/lib/browser/chunk-OI7AAA6Q.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +26 -21
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/intent-resolver-74JPWYBP.mjs +42 -0
- package/dist/lib/browser/intent-resolver-74JPWYBP.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/react-surface-6QWXI53A.mjs +189 -0
- package/dist/lib/browser/react-surface-6QWXI53A.mjs.map +7 -0
- package/dist/lib/browser/{state-65TQKYX7.mjs → state-HT65TAYL.mjs} +9 -6
- package/dist/lib/browser/state-HT65TAYL.mjs.map +7 -0
- package/dist/types/src/NavTreePlugin.d.ts.map +1 -1
- package/dist/types/src/capabilities/app-graph-builder.d.ts +22 -22
- package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
- package/dist/types/src/capabilities/capabilities.d.ts +2 -3
- package/dist/types/src/capabilities/capabilities.d.ts.map +1 -1
- package/dist/types/src/capabilities/index.d.ts +32 -88
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
- package/dist/types/src/capabilities/state.d.ts +3 -3
- package/dist/types/src/capabilities/state.d.ts.map +1 -1
- package/dist/types/src/components/CommandsDialog.d.ts.map +1 -1
- package/dist/types/src/components/CommandsTrigger.d.ts.map +1 -1
- package/dist/types/src/components/NavTree.d.ts +20 -3
- package/dist/types/src/components/NavTree.d.ts.map +1 -1
- package/dist/types/src/components/NavTree.stories.d.ts +2 -2
- package/dist/types/src/components/NavTree.stories.d.ts.map +1 -1
- package/dist/types/src/components/NavTreeContainer.d.ts +3 -4
- package/dist/types/src/components/NavTreeContainer.d.ts.map +1 -1
- package/dist/types/src/components/NavTreeFooter.d.ts +6 -0
- package/dist/types/src/components/NavTreeFooter.d.ts.map +1 -0
- package/dist/types/src/components/NavTreeItemAction.d.ts +1 -1
- package/dist/types/src/components/NavTreeItemAction.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +0 -2
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/stories/Graph.stories.d.ts +2 -2
- package/dist/types/src/stories/Graph.stories.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +6 -0
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types.d.ts +1 -2
- package/dist/types/src/types.d.ts.map +1 -1
- package/dist/types/src/util.d.ts +0 -9
- package/dist/types/src/util.d.ts.map +1 -1
- package/package.json +31 -33
- package/src/NavTreePlugin.tsx +10 -8
- package/src/capabilities/app-graph-builder.ts +4 -6
- package/src/capabilities/capabilities.ts +2 -3
- package/src/capabilities/intent-resolver.ts +16 -22
- package/src/capabilities/react-surface.tsx +41 -15
- package/src/capabilities/state.ts +8 -5
- package/src/components/CommandsDialog.tsx +4 -3
- package/src/components/CommandsTrigger.tsx +5 -7
- package/src/components/NavTree.stories.tsx +5 -5
- package/src/components/NavTree.tsx +116 -26
- package/src/components/NavTreeContainer.tsx +32 -106
- package/src/components/NavTreeFooter.tsx +161 -0
- package/src/components/NavTreeItemAction.tsx +4 -12
- package/src/components/NotchStart.tsx +2 -2
- package/src/components/index.ts +0 -2
- package/src/stories/Graph.stories.tsx +4 -5
- package/src/translations.ts +6 -0
- package/src/types.ts +1 -2
- package/src/util.ts +0 -54
- package/dist/lib/browser/chunk-54MPRXMH.mjs +0 -1109
- package/dist/lib/browser/chunk-54MPRXMH.mjs.map +0 -7
- package/dist/lib/browser/chunk-AOAGODQB.mjs.map +0 -7
- package/dist/lib/browser/intent-resolver-U25VBFH3.mjs +0 -47
- package/dist/lib/browser/intent-resolver-U25VBFH3.mjs.map +0 -7
- package/dist/lib/browser/react-surface-LNRTNSM6.mjs +0 -57
- package/dist/lib/browser/react-surface-LNRTNSM6.mjs.map +0 -7
- package/dist/lib/browser/state-65TQKYX7.mjs.map +0 -7
- package/dist/types/src/components/L0Menu.d.ts +0 -9
- package/dist/types/src/components/L0Menu.d.ts.map +0 -1
- package/dist/types/src/components/L1Panels.d.ts +0 -8
- package/dist/types/src/components/L1Panels.d.ts.map +0 -1
- package/dist/types/src/components/NavTreeContext.d.ts +0 -4
- package/dist/types/src/components/NavTreeContext.d.ts.map +0 -1
- package/dist/types/src/components/NavTreeItemColumns.d.ts +0 -4
- package/dist/types/src/components/NavTreeItemColumns.d.ts.map +0 -1
- package/dist/types/src/components/types.d.ts +0 -25
- package/dist/types/src/components/types.d.ts.map +0 -1
- package/dist/types/src/hooks.d.ts +0 -3
- package/dist/types/src/hooks.d.ts.map +0 -1
- package/dist/types/src/stories/StorybookNavTree.d.ts +0 -4
- package/dist/types/src/stories/StorybookNavTree.d.ts.map +0 -1
- package/src/components/L0Menu.tsx +0 -210
- package/src/components/L1Panels.tsx +0 -100
- package/src/components/NavTreeContext.tsx +0 -13
- package/src/components/NavTreeItemColumns.tsx +0 -71
- package/src/components/types.ts +0 -33
- package/src/hooks.ts +0 -21
- package/src/stories/StorybookNavTree.tsx +0 -63
|
@@ -2,40 +2,130 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import React, {
|
|
5
|
+
import React, { Fragment, useCallback, useEffect, type FC } from 'react';
|
|
6
6
|
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { isAction, type Node } from '@dxos/app-graph';
|
|
8
|
+
import { Popover, toLocalizedString, Treegrid, useTranslation } from '@dxos/react-ui';
|
|
9
|
+
import { Tree, type TreeProps } from '@dxos/react-ui-list';
|
|
10
|
+
import { type MaybePromise } from '@dxos/util';
|
|
9
11
|
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import { type NavTreeProps } from './types';
|
|
14
|
-
import { useLoadDescendents } from '../hooks';
|
|
12
|
+
import { NavTreeItemAction } from './NavTreeItemAction';
|
|
13
|
+
import { NAVTREE_PLUGIN } from '../meta';
|
|
14
|
+
import { type FlattenedActions, type NavTreeItemGraphNode } from '../types';
|
|
15
15
|
|
|
16
16
|
export const NAV_TREE_ITEM = 'NavTreeItem';
|
|
17
17
|
|
|
18
|
-
export
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
18
|
+
export type NavTreeProps = Omit<
|
|
19
|
+
TreeProps<NavTreeItemGraphNode>,
|
|
20
|
+
'draggable' | 'gridTemplateColumns' | 'renderColumns'
|
|
21
|
+
> &
|
|
22
|
+
Pick<NavTreeColumnsProps, 'getActions' | 'loadDescendents' | 'renderItemEnd' | 'popoverAnchorId'>;
|
|
23
|
+
|
|
24
|
+
export const NavTree = ({ getActions, loadDescendents, renderItemEnd, popoverAnchorId, ...props }: NavTreeProps) => {
|
|
25
|
+
const renderColumns = useCallback<NonNullable<TreeProps<NavTreeItemGraphNode>['renderColumns']>>(
|
|
26
|
+
({ item, path, open }) => {
|
|
27
|
+
return (
|
|
28
|
+
<NavTreeColumns
|
|
29
|
+
path={path}
|
|
30
|
+
node={item}
|
|
31
|
+
getActions={getActions}
|
|
32
|
+
open={open}
|
|
33
|
+
loadDescendents={loadDescendents}
|
|
34
|
+
renderItemEnd={renderItemEnd}
|
|
35
|
+
popoverAnchorId={popoverAnchorId}
|
|
36
|
+
/>
|
|
37
|
+
);
|
|
38
|
+
},
|
|
39
|
+
[renderItemEnd, popoverAnchorId, loadDescendents],
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<Tree
|
|
44
|
+
{...props}
|
|
45
|
+
draggable
|
|
46
|
+
gridTemplateColumns='[tree-row-start] 1fr min-content min-content min-content [tree-row-end]'
|
|
47
|
+
renderColumns={renderColumns}
|
|
48
|
+
/>
|
|
27
49
|
);
|
|
28
|
-
|
|
29
|
-
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
type NavTreeColumnsProps = {
|
|
53
|
+
path: string[];
|
|
54
|
+
node: Node;
|
|
55
|
+
getActions: (node: Node) => FlattenedActions;
|
|
56
|
+
open: boolean;
|
|
57
|
+
loadDescendents?: (node: Node) => MaybePromise<void>;
|
|
58
|
+
renderItemEnd?: FC<{ node: Node; open: boolean }>;
|
|
59
|
+
popoverAnchorId?: string;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const NavTreeColumns = ({
|
|
63
|
+
path,
|
|
64
|
+
node,
|
|
65
|
+
getActions,
|
|
66
|
+
open,
|
|
67
|
+
loadDescendents,
|
|
68
|
+
renderItemEnd: ItemEnd,
|
|
69
|
+
popoverAnchorId,
|
|
70
|
+
}: NavTreeColumnsProps) => {
|
|
71
|
+
const { t } = useTranslation(NAVTREE_PLUGIN);
|
|
72
|
+
|
|
73
|
+
const level = path.length - 2;
|
|
74
|
+
|
|
75
|
+
const { actions: _actions, groupedActions } = getActions(node);
|
|
76
|
+
const [primaryAction, ...secondaryActions] = _actions.toSorted((a, b) =>
|
|
77
|
+
a.properties?.disposition === 'toolbar' ? -1 : 1,
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
const actions = (primaryAction?.properties?.disposition === 'toolbar' ? secondaryActions : _actions)
|
|
81
|
+
.flatMap((action) => (isAction(action) ? [action] : []))
|
|
82
|
+
.filter((action) => !action.properties?.hidden);
|
|
83
|
+
|
|
84
|
+
const ActionRoot = popoverAnchorId === `dxos.org/ui/${NAV_TREE_ITEM}/${node.id}` ? Popover.Anchor : Fragment;
|
|
30
85
|
|
|
31
|
-
|
|
32
|
-
|
|
86
|
+
// TODO(thure): Ideally this should not be necessary.
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
const frame = requestAnimationFrame(() => {
|
|
89
|
+
void loadDescendents?.(node);
|
|
90
|
+
if (primaryAction && !isAction(primaryAction)) {
|
|
91
|
+
void loadDescendents?.(primaryAction);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
return () => cancelAnimationFrame(frame);
|
|
95
|
+
}, [primaryAction]);
|
|
33
96
|
|
|
34
97
|
return (
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
98
|
+
<>
|
|
99
|
+
{primaryAction?.properties?.disposition === 'toolbar' ? (
|
|
100
|
+
<NavTreeItemAction
|
|
101
|
+
testId={primaryAction.properties?.testId}
|
|
102
|
+
label={toLocalizedString(primaryAction.properties?.label, t)}
|
|
103
|
+
icon={primaryAction.properties?.icon ?? 'ph--placeholder--regular'}
|
|
104
|
+
parent={node}
|
|
105
|
+
monolithic={isAction(primaryAction)}
|
|
106
|
+
menuActions={isAction(primaryAction) ? [primaryAction] : groupedActions[primaryAction.id]}
|
|
107
|
+
menuType={primaryAction.properties?.menuType}
|
|
108
|
+
caller={NAV_TREE_ITEM}
|
|
109
|
+
/>
|
|
110
|
+
) : (
|
|
111
|
+
<Treegrid.Cell />
|
|
112
|
+
)}
|
|
113
|
+
<ActionRoot>
|
|
114
|
+
{actions.length > 0 ? (
|
|
115
|
+
<NavTreeItemAction
|
|
116
|
+
testId={`navtree.treeItem.actionsLevel${level}`}
|
|
117
|
+
label={t('tree item actions label')}
|
|
118
|
+
icon='ph--dots-three-vertical--regular'
|
|
119
|
+
parent={node}
|
|
120
|
+
menuActions={actions}
|
|
121
|
+
menuType='dropdown'
|
|
122
|
+
caller={NAV_TREE_ITEM}
|
|
123
|
+
/>
|
|
124
|
+
) : (
|
|
125
|
+
<Treegrid.Cell />
|
|
126
|
+
)}
|
|
127
|
+
</ActionRoot>
|
|
128
|
+
{ItemEnd && <ItemEnd node={node} open={open} />}
|
|
129
|
+
</>
|
|
40
130
|
);
|
|
41
131
|
};
|
|
@@ -5,28 +5,19 @@
|
|
|
5
5
|
import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
6
6
|
import { extractInstruction, type Instruction } from '@atlaskit/pragmatic-drag-and-drop-hitbox/tree-item';
|
|
7
7
|
import { untracked } from '@preact/signals-core';
|
|
8
|
-
import React, { memo, useCallback, useEffect
|
|
8
|
+
import React, { memo, useCallback, useEffect } from 'react';
|
|
9
9
|
|
|
10
|
-
import {
|
|
11
|
-
createIntent,
|
|
12
|
-
LayoutAction,
|
|
13
|
-
Surface,
|
|
14
|
-
useAppGraph,
|
|
15
|
-
useCapability,
|
|
16
|
-
useIntentDispatcher,
|
|
17
|
-
useLayout,
|
|
18
|
-
} from '@dxos/app-framework';
|
|
10
|
+
import { createIntent, LayoutAction, NavigationAction, useIntentDispatcher, Surface } from '@dxos/app-framework';
|
|
19
11
|
import { isAction, isActionLike, type Node } from '@dxos/app-graph';
|
|
12
|
+
import { useGraph } from '@dxos/plugin-graph';
|
|
20
13
|
import { isEchoObject, isSpace } from '@dxos/react-client/echo';
|
|
21
|
-
import { useMediaQuery } from '@dxos/react-ui';
|
|
14
|
+
import { useMediaQuery, useSidebars } from '@dxos/react-ui';
|
|
22
15
|
import { isTreeData, type TreeData, type PropsFromTreeItem } from '@dxos/react-ui-list';
|
|
23
16
|
import { mx } from '@dxos/react-ui-theme';
|
|
24
17
|
import { arrayMove } from '@dxos/util';
|
|
25
18
|
|
|
26
|
-
import { NAV_TREE_ITEM, NavTree } from './NavTree';
|
|
27
|
-
import {
|
|
28
|
-
import { type NavTreeContextValue } from './types';
|
|
29
|
-
import { NavTreeCapabilities } from '../capabilities';
|
|
19
|
+
import { NAV_TREE_ITEM, NavTree, type NavTreeProps } from './NavTree';
|
|
20
|
+
import { NAVTREE_PLUGIN } from '../meta';
|
|
30
21
|
import { type NavTreeItemGraphNode } from '../types';
|
|
31
22
|
import {
|
|
32
23
|
expandActions,
|
|
@@ -35,7 +26,6 @@ import {
|
|
|
35
26
|
getChildren,
|
|
36
27
|
getParent,
|
|
37
28
|
resolveMigrationOperation,
|
|
38
|
-
expandChildrenAndActions,
|
|
39
29
|
} from '../util';
|
|
40
30
|
|
|
41
31
|
// TODO(thure): Is NavTree truly authoritative in this regard?
|
|
@@ -47,29 +37,24 @@ const renderItemEnd = ({ node, open }: { node: Node; open: boolean }) => (
|
|
|
47
37
|
|
|
48
38
|
export type NavTreeContainerProps = {
|
|
49
39
|
popoverAnchorId?: string;
|
|
50
|
-
|
|
51
|
-
} & Pick<NavTreeContextValue, 'tab'>;
|
|
40
|
+
} & Pick<NavTreeProps, 'isOpen' | 'isCurrent' | 'onOpenChange'>;
|
|
52
41
|
|
|
53
|
-
export const NavTreeContainer = memo(({
|
|
42
|
+
export const NavTreeContainer = memo(({ isCurrent, popoverAnchorId, ...props }: NavTreeContainerProps) => {
|
|
43
|
+
const { closeNavigationSidebar } = useSidebars(NAVTREE_PLUGIN);
|
|
54
44
|
const [isLg] = useMediaQuery('lg', { ssr: false });
|
|
55
45
|
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
56
|
-
const { graph } =
|
|
57
|
-
const layout = useLayout();
|
|
58
|
-
const { isOpen, isCurrent, setItem } = useCapability(NavTreeCapabilities.State);
|
|
46
|
+
const { graph } = useGraph();
|
|
59
47
|
|
|
60
48
|
const getActions = useCallback((node: Node) => naturalGetActions(graph, node), [graph]);
|
|
61
49
|
|
|
62
50
|
const getItems = useCallback(
|
|
63
|
-
(node?: Node
|
|
51
|
+
(node?: Node) => {
|
|
64
52
|
return graph.nodes(node ?? graph.root, {
|
|
65
53
|
filter: (node): node is Node => {
|
|
66
54
|
return untracked(() => {
|
|
67
55
|
const action = isActionLike(node);
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return node.properties.disposition === disposition;
|
|
56
|
+
const disposition = node.properties.disposition;
|
|
57
|
+
return !action || (action && disposition === 'item');
|
|
73
58
|
});
|
|
74
59
|
},
|
|
75
60
|
});
|
|
@@ -111,33 +96,6 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
111
96
|
[graph],
|
|
112
97
|
);
|
|
113
98
|
|
|
114
|
-
const onOpenChange = useCallback(
|
|
115
|
-
({ item: { id }, path, open }: { item: Node; path: string[]; open: boolean }) => {
|
|
116
|
-
// TODO(thure): This might become a localstorage leak; openItemIds that no longer exist should be removed from this map.
|
|
117
|
-
setItem(path, 'open', open);
|
|
118
|
-
|
|
119
|
-
if (graph) {
|
|
120
|
-
const node = graph.findNode(id);
|
|
121
|
-
return node && expandChildrenAndActions(graph, node as NavTreeItemGraphNode);
|
|
122
|
-
}
|
|
123
|
-
},
|
|
124
|
-
[graph],
|
|
125
|
-
);
|
|
126
|
-
|
|
127
|
-
const onTabChange = useCallback(
|
|
128
|
-
async (node: NavTreeItemGraphNode) => {
|
|
129
|
-
await dispatch(createIntent(LayoutAction.SwitchWorkspace, { part: 'workspace', subject: node.id }));
|
|
130
|
-
// Open the first item if the workspace is empty.
|
|
131
|
-
if (layout.active.length === 0) {
|
|
132
|
-
const [item] = getItems(node).filter((node) => !isActionLike(node));
|
|
133
|
-
if (item) {
|
|
134
|
-
await dispatch(createIntent(LayoutAction.Open, { part: 'main', subject: [item.id] }));
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
},
|
|
138
|
-
[dispatch, layout],
|
|
139
|
-
);
|
|
140
|
-
|
|
141
99
|
const canDrop = useCallback((source: TreeData, target: TreeData) => {
|
|
142
100
|
const sourceNode = source.item as Node;
|
|
143
101
|
const targetNode = target.item as Node;
|
|
@@ -165,19 +123,11 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
165
123
|
|
|
166
124
|
const current = isCurrent(path, node);
|
|
167
125
|
if (!current) {
|
|
168
|
-
void dispatch(
|
|
169
|
-
createIntent(LayoutAction.Open, {
|
|
170
|
-
part: 'main',
|
|
171
|
-
subject: [node.id],
|
|
172
|
-
options: { key: node.properties.key },
|
|
173
|
-
}),
|
|
174
|
-
);
|
|
126
|
+
void dispatch(createIntent(NavigationAction.Open, { activeParts: { main: [node.id] } }));
|
|
175
127
|
} else if (option) {
|
|
176
|
-
void dispatch(
|
|
177
|
-
createIntent(LayoutAction.Close, { part: 'main', subject: [node.id], options: { state: false } }),
|
|
178
|
-
);
|
|
128
|
+
void dispatch(createIntent(NavigationAction.Close, { activeParts: { main: [node.id] } }));
|
|
179
129
|
} else {
|
|
180
|
-
void dispatch(createIntent(LayoutAction.ScrollIntoView, {
|
|
130
|
+
void dispatch(createIntent(LayoutAction.ScrollIntoView, { id: node.id }));
|
|
181
131
|
}
|
|
182
132
|
|
|
183
133
|
const defaultAction = graph.actions(node).find((action) => action.properties?.disposition === 'default');
|
|
@@ -186,10 +136,10 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
186
136
|
}
|
|
187
137
|
|
|
188
138
|
if (!isLg) {
|
|
189
|
-
|
|
139
|
+
closeNavigationSidebar();
|
|
190
140
|
}
|
|
191
141
|
},
|
|
192
|
-
[graph, dispatch, isCurrent, isLg],
|
|
142
|
+
[graph, dispatch, isCurrent, isLg, closeNavigationSidebar],
|
|
193
143
|
);
|
|
194
144
|
|
|
195
145
|
// TODO(wittjosiah): Factor out hook.
|
|
@@ -251,44 +201,20 @@ export const NavTreeContainer = memo(({ tab, popoverAnchorId, topbar }: NavTreeC
|
|
|
251
201
|
});
|
|
252
202
|
}, [graph]);
|
|
253
203
|
|
|
254
|
-
|
|
255
|
-
() => ({
|
|
256
|
-
tab,
|
|
257
|
-
onTabChange,
|
|
258
|
-
getActions,
|
|
259
|
-
loadDescendents,
|
|
260
|
-
renderItemEnd,
|
|
261
|
-
popoverAnchorId,
|
|
262
|
-
topbar,
|
|
263
|
-
getItems,
|
|
264
|
-
getProps,
|
|
265
|
-
isCurrent,
|
|
266
|
-
isOpen,
|
|
267
|
-
onOpenChange,
|
|
268
|
-
canDrop,
|
|
269
|
-
onSelect: handleSelect,
|
|
270
|
-
}),
|
|
271
|
-
[
|
|
272
|
-
tab,
|
|
273
|
-
onTabChange,
|
|
274
|
-
getActions,
|
|
275
|
-
loadDescendents,
|
|
276
|
-
renderItemEnd,
|
|
277
|
-
popoverAnchorId,
|
|
278
|
-
topbar,
|
|
279
|
-
getItems,
|
|
280
|
-
getProps,
|
|
281
|
-
isCurrent,
|
|
282
|
-
isOpen,
|
|
283
|
-
onOpenChange,
|
|
284
|
-
canDrop,
|
|
285
|
-
handleSelect,
|
|
286
|
-
],
|
|
287
|
-
);
|
|
288
|
-
|
|
204
|
+
// TODO(thure): What gives this an inline `overflow: initial`?
|
|
289
205
|
return (
|
|
290
|
-
<
|
|
291
|
-
|
|
292
|
-
|
|
206
|
+
<NavTree
|
|
207
|
+
id={graph.root.id}
|
|
208
|
+
getActions={getActions}
|
|
209
|
+
getItems={getItems}
|
|
210
|
+
getProps={getProps}
|
|
211
|
+
isCurrent={isCurrent}
|
|
212
|
+
loadDescendents={loadDescendents}
|
|
213
|
+
renderItemEnd={renderItemEnd}
|
|
214
|
+
popoverAnchorId={popoverAnchorId}
|
|
215
|
+
canDrop={canDrop}
|
|
216
|
+
onSelect={handleSelect}
|
|
217
|
+
{...props}
|
|
218
|
+
/>
|
|
293
219
|
);
|
|
294
220
|
});
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { formatDistance } from 'date-fns/formatDistance';
|
|
6
|
+
import React from 'react';
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
type LayoutPart,
|
|
10
|
+
SettingsAction,
|
|
11
|
+
useIntentDispatcher,
|
|
12
|
+
createIntent,
|
|
13
|
+
usePluginManager,
|
|
14
|
+
} from '@dxos/app-framework';
|
|
15
|
+
import { useConfig } from '@dxos/react-client';
|
|
16
|
+
import {
|
|
17
|
+
Button,
|
|
18
|
+
Link,
|
|
19
|
+
Message,
|
|
20
|
+
Popover,
|
|
21
|
+
Tooltip,
|
|
22
|
+
Trans,
|
|
23
|
+
useDefaultValue,
|
|
24
|
+
useSidebars,
|
|
25
|
+
useTranslation,
|
|
26
|
+
Icon,
|
|
27
|
+
IconButton,
|
|
28
|
+
} from '@dxos/react-ui';
|
|
29
|
+
import { LayoutControls } from '@dxos/react-ui-stack';
|
|
30
|
+
import { mx } from '@dxos/react-ui-theme';
|
|
31
|
+
|
|
32
|
+
import { NAVTREE_PLUGIN } from '../meta';
|
|
33
|
+
|
|
34
|
+
const buttonStyles = '!pli-1.5 text-xs font-normal';
|
|
35
|
+
|
|
36
|
+
const repo = 'https://github.com/dxos/dxos';
|
|
37
|
+
|
|
38
|
+
const VERSION_REGEX = /([\d.]+)/;
|
|
39
|
+
|
|
40
|
+
export const NavTreeFooter = (props: { layoutPart?: LayoutPart }) => {
|
|
41
|
+
const layoutPart = useDefaultValue(props.layoutPart, () => 'sidebar');
|
|
42
|
+
const config = useConfig();
|
|
43
|
+
const { t } = useTranslation(NAVTREE_PLUGIN);
|
|
44
|
+
const { navigationSidebarOpen } = useSidebars(NAVTREE_PLUGIN);
|
|
45
|
+
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
46
|
+
const { version, timestamp, commitHash } = config.values.runtime?.app?.build ?? {};
|
|
47
|
+
const manager = usePluginManager();
|
|
48
|
+
const [_, v] = version?.match(VERSION_REGEX) ?? [];
|
|
49
|
+
|
|
50
|
+
const releaseUrl =
|
|
51
|
+
config.values.runtime?.app?.env?.DX_ENVIRONMENT === 'production'
|
|
52
|
+
? `${repo}/releases/tag/v${version}`
|
|
53
|
+
: `${repo}/commit/${commitHash}`;
|
|
54
|
+
|
|
55
|
+
const previewUrl = 'https://docs.dxos.org/composer#technology-preview';
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<div
|
|
59
|
+
role='none'
|
|
60
|
+
className={mx(
|
|
61
|
+
'flex pbe-[env(safe-area-inset-bottom)] box-content justify-end',
|
|
62
|
+
layoutPart === 'complementary' && 'md:justify-end flex-row-reverse',
|
|
63
|
+
)}
|
|
64
|
+
>
|
|
65
|
+
<Popover.Root>
|
|
66
|
+
<Popover.Trigger asChild>
|
|
67
|
+
<Button variant='ghost' classNames={buttonStyles} {...(!navigationSidebarOpen && { tabIndex: -1 })}>
|
|
68
|
+
v{v}
|
|
69
|
+
</Button>
|
|
70
|
+
</Popover.Trigger>
|
|
71
|
+
<Popover.Portal>
|
|
72
|
+
<Popover.Content
|
|
73
|
+
side='top'
|
|
74
|
+
role='message'
|
|
75
|
+
classNames='z-[12] bg-warning-500 max-is-[min(calc(100vw-16px),40ch)]'
|
|
76
|
+
>
|
|
77
|
+
<Message.Root valence='warning' className='rounded-be-none p-5'>
|
|
78
|
+
<Message.Title>
|
|
79
|
+
<Icon icon='ph--warning--duotone' size={6} classNames='inline mie-2' />
|
|
80
|
+
<span>{t('warning title')}</span>
|
|
81
|
+
</Message.Title>
|
|
82
|
+
<Message.Body>
|
|
83
|
+
{t('technology preview message')}
|
|
84
|
+
<br />
|
|
85
|
+
<Link href={previewUrl} target='_blank' rel='noreferrer' variant='neutral'>
|
|
86
|
+
{t('learn more label')}
|
|
87
|
+
<Icon icon='ph--arrow-square-out--bold' classNames='inline mis-1' />
|
|
88
|
+
</Link>
|
|
89
|
+
</Message.Body>
|
|
90
|
+
</Message.Root>
|
|
91
|
+
<div role='none' className='plb-4 pli-5 space-b-2 text-baseText'>
|
|
92
|
+
{timestamp && (
|
|
93
|
+
<p>
|
|
94
|
+
{t('released message', {
|
|
95
|
+
released: formatDistance(new Date(timestamp), new Date(), { addSuffix: true }),
|
|
96
|
+
})}
|
|
97
|
+
<br />
|
|
98
|
+
<Link href={releaseUrl} target='_blank' rel='noreferrer' variant='neutral'>
|
|
99
|
+
{t('see release label')}
|
|
100
|
+
<Icon icon='ph--arrow-square-out--bold' classNames='inline mis-1' />
|
|
101
|
+
</Link>
|
|
102
|
+
</p>
|
|
103
|
+
)}
|
|
104
|
+
<p>
|
|
105
|
+
<Trans
|
|
106
|
+
{...{
|
|
107
|
+
t,
|
|
108
|
+
i18nKey: 'powered by dxos message',
|
|
109
|
+
components: {
|
|
110
|
+
dxos: <Link href='https://dxos.org' target='_blank' rel='noreferrer' variant='neutral' />,
|
|
111
|
+
},
|
|
112
|
+
}}
|
|
113
|
+
/>
|
|
114
|
+
</p>
|
|
115
|
+
</div>
|
|
116
|
+
<Popover.Arrow />
|
|
117
|
+
</Popover.Content>
|
|
118
|
+
</Popover.Portal>
|
|
119
|
+
</Popover.Root>
|
|
120
|
+
|
|
121
|
+
<Tooltip.Root>
|
|
122
|
+
<Tooltip.Trigger asChild>
|
|
123
|
+
{/* TODO(burdon): Reconcile with action created by LayoutPlugin. */}
|
|
124
|
+
<IconButton
|
|
125
|
+
icon='ph--gear-six--regular'
|
|
126
|
+
iconOnly
|
|
127
|
+
label={t('open settings label')}
|
|
128
|
+
size={4}
|
|
129
|
+
variant='ghost'
|
|
130
|
+
classNames={buttonStyles}
|
|
131
|
+
data-testid='treeView.openSettings'
|
|
132
|
+
data-joyride='welcome/settings'
|
|
133
|
+
{...(!navigationSidebarOpen && { tabIndex: -1 })}
|
|
134
|
+
iconClassNames='rotate-90'
|
|
135
|
+
onClick={() => dispatch(createIntent(SettingsAction.Open))}
|
|
136
|
+
/>
|
|
137
|
+
</Tooltip.Trigger>
|
|
138
|
+
<Tooltip.Portal>
|
|
139
|
+
<Tooltip.Content classNames='z-[12]'>
|
|
140
|
+
{t('open settings label')}
|
|
141
|
+
<Tooltip.Arrow />
|
|
142
|
+
</Tooltip.Content>
|
|
143
|
+
</Tooltip.Portal>
|
|
144
|
+
</Tooltip.Root>
|
|
145
|
+
|
|
146
|
+
{/* NOTE(thure): Unpinning from the NavTree’s default position in Deck is temporarily disabled. */}
|
|
147
|
+
{manager.enabled.includes('dxos.org/plugin/deck') && (
|
|
148
|
+
<LayoutControls
|
|
149
|
+
variant='hide-disabled'
|
|
150
|
+
capabilities={{
|
|
151
|
+
incrementStart: false,
|
|
152
|
+
incrementEnd: false,
|
|
153
|
+
}}
|
|
154
|
+
onClick={(_type) => {
|
|
155
|
+
// TODO(Zan): If we inmplement pinning again, we should dispatch here.
|
|
156
|
+
}}
|
|
157
|
+
/>
|
|
158
|
+
)}
|
|
159
|
+
</div>
|
|
160
|
+
);
|
|
161
|
+
};
|
|
@@ -24,8 +24,11 @@ export type NavTreeItemActionMenuProps = ActionProperties & {
|
|
|
24
24
|
const fallbackIcon = 'ph--placeholder--regular';
|
|
25
25
|
|
|
26
26
|
const actionButtonProps = {
|
|
27
|
+
iconOnly: true,
|
|
27
28
|
size: 4 as const,
|
|
29
|
+
variant: 'ghost' as const,
|
|
28
30
|
density: 'fine' as const,
|
|
31
|
+
classNames: mx('shrink-0 !pli-2 pointer-fine:!pli-1', hoverableControlItem, hoverableOpenControlItem),
|
|
29
32
|
};
|
|
30
33
|
|
|
31
34
|
export const NavTreeItemActionDropdownMenu = ({
|
|
@@ -43,10 +46,7 @@ export const NavTreeItemActionDropdownMenu = ({
|
|
|
43
46
|
<DropdownMenu.Trigger asChild>
|
|
44
47
|
<IconButton
|
|
45
48
|
{...actionButtonProps}
|
|
46
|
-
classNames={mx('shrink-0 pli-2 pointer-fine:pli-1', hoverableControlItem, hoverableOpenControlItem)}
|
|
47
|
-
variant='ghost'
|
|
48
49
|
icon={icon ?? fallbackIcon}
|
|
49
|
-
iconOnly
|
|
50
50
|
label={toLocalizedString(label, t)}
|
|
51
51
|
data-testid={testId}
|
|
52
52
|
suppressNextTooltip={suppressNextTooltip}
|
|
@@ -59,22 +59,14 @@ export const NavTreeItemActionDropdownMenu = ({
|
|
|
59
59
|
|
|
60
60
|
export const NavTreeItemMonolithicAction = ({
|
|
61
61
|
parent,
|
|
62
|
-
properties: { disabled, caller, testId, icon
|
|
62
|
+
properties: { disabled, caller, testId, icon } = { label: 'never' },
|
|
63
63
|
data: invoke,
|
|
64
64
|
baseLabel,
|
|
65
65
|
}: Action & { parent: Node; onAction?: (action: Action) => void; baseLabel: string }) => {
|
|
66
66
|
return (
|
|
67
67
|
<IconButton
|
|
68
68
|
{...actionButtonProps}
|
|
69
|
-
variant={variant}
|
|
70
|
-
classNames={mx(
|
|
71
|
-
'shrink-0',
|
|
72
|
-
hoverableControlItem,
|
|
73
|
-
hoverableOpenControlItem,
|
|
74
|
-
iconOnly ? 'pli-2 pointer-fine:pli-1' : 'p-2 pointer-fine:p-2 mie-1',
|
|
75
|
-
)}
|
|
76
69
|
icon={icon ?? fallbackIcon}
|
|
77
|
-
iconOnly={iconOnly}
|
|
78
70
|
label={baseLabel}
|
|
79
71
|
disabled={disabled}
|
|
80
72
|
onClick={(event) => {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import React from 'react';
|
|
6
6
|
|
|
7
|
-
import { createIntent,
|
|
7
|
+
import { createIntent, useIntentDispatcher, useCapabilities } from '@dxos/app-framework';
|
|
8
8
|
import { ClientAction } from '@dxos/plugin-client/types';
|
|
9
9
|
import { ObservabilityCapabilities } from '@dxos/plugin-observability';
|
|
10
10
|
import { useIdentity } from '@dxos/react-client/halo';
|
|
@@ -19,7 +19,7 @@ export const NotchStart = () => {
|
|
|
19
19
|
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
20
20
|
return (
|
|
21
21
|
<HaloButton
|
|
22
|
-
size={
|
|
22
|
+
size={8}
|
|
23
23
|
identityKey={identity?.identityKey.toHex()}
|
|
24
24
|
hue={identity?.profile?.data?.hue}
|
|
25
25
|
emoji={identity?.profile?.data?.emoji}
|
package/src/components/index.ts
CHANGED
|
@@ -6,7 +6,5 @@ export * from './CommandsDialog';
|
|
|
6
6
|
export * from './CommandsTrigger';
|
|
7
7
|
export * from './NavTree';
|
|
8
8
|
export * from './NavTreeContainer';
|
|
9
|
-
export * from './NavTreeContext';
|
|
10
9
|
export * from './NavTreeDocumentTitle';
|
|
11
10
|
export * from './NotchStart';
|
|
12
|
-
export * from './types';
|
|
@@ -18,7 +18,7 @@ import { isTreeData, type PropsFromTreeItem } from '@dxos/react-ui-list';
|
|
|
18
18
|
import { Path } from '@dxos/react-ui-mosaic';
|
|
19
19
|
import { withLayout, withTheme } from '@dxos/storybook-utils';
|
|
20
20
|
|
|
21
|
-
import {
|
|
21
|
+
import { NavTree } from '../components';
|
|
22
22
|
import { getActions, getChildren } from '../util';
|
|
23
23
|
|
|
24
24
|
faker.seed(3);
|
|
@@ -53,9 +53,9 @@ const state = new Map<string, ReactiveObject<{ open: boolean; current: boolean }
|
|
|
53
53
|
|
|
54
54
|
export const Default = {};
|
|
55
55
|
|
|
56
|
-
const meta: Meta<typeof
|
|
56
|
+
const meta: Meta<typeof NavTree> = {
|
|
57
57
|
title: 'plugins/plugin-navtree/Graph',
|
|
58
|
-
component:
|
|
58
|
+
component: NavTree,
|
|
59
59
|
decorators: [withTheme, withLayout({ tooltips: true })],
|
|
60
60
|
render: (args) => {
|
|
61
61
|
useEffect(() => {
|
|
@@ -78,10 +78,9 @@ const meta: Meta<typeof StorybookNavTree> = {
|
|
|
78
78
|
});
|
|
79
79
|
}, []);
|
|
80
80
|
|
|
81
|
-
return <
|
|
81
|
+
return <NavTree {...args} />;
|
|
82
82
|
},
|
|
83
83
|
args: {
|
|
84
|
-
root: graph.root,
|
|
85
84
|
id: graph.root.id,
|
|
86
85
|
getActions: (node: Node) => getActions(graph, node),
|
|
87
86
|
getItems: (node?: Node) => graph.nodes(node ?? graph.root),
|
package/src/translations.ts
CHANGED
|
@@ -13,6 +13,12 @@ export default [
|
|
|
13
13
|
'commands dialog title': 'Commands',
|
|
14
14
|
'command list input placeholder': 'Search for commands…',
|
|
15
15
|
'node actions menu invoker label': 'More options',
|
|
16
|
+
'warning title': 'WARNING',
|
|
17
|
+
'technology preview message': 'Composer is still in technology preview.',
|
|
18
|
+
'learn more label': 'Learn more',
|
|
19
|
+
'released message': 'This version released {{released}}.',
|
|
20
|
+
'see release label': 'See release on GitHub',
|
|
21
|
+
'powered by dxos message': 'Powered by <dxos>DXOS</dxos>',
|
|
16
22
|
'tree item actions label': 'More actions',
|
|
17
23
|
'empty branch message': ' ',
|
|
18
24
|
},
|
package/src/types.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import { type Action, type ActionLike, type Node } from '@dxos/app-graph';
|
|
6
6
|
import { type Label } from '@dxos/react-ui';
|
|
7
|
-
import { type MaybePromise
|
|
7
|
+
import { type MaybePromise } from '@dxos/util';
|
|
8
8
|
|
|
9
9
|
export type NavTreeItemGraphNode = Node<
|
|
10
10
|
any,
|
|
@@ -31,7 +31,6 @@ type SharedProperties = {
|
|
|
31
31
|
label: Label;
|
|
32
32
|
icon?: string;
|
|
33
33
|
disabled?: boolean;
|
|
34
|
-
position?: Position;
|
|
35
34
|
testId?: string;
|
|
36
35
|
className?: string;
|
|
37
36
|
headingClassName?: string;
|