@dxos/plugin-navtree 0.7.4-staging.f7e8224 → 0.7.5-feature-compute.4d9d99a
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-OF4MMBLH.mjs +42 -0
- package/dist/lib/browser/app-graph-builder-OF4MMBLH.mjs.map +7 -0
- package/dist/lib/browser/chunk-IMGT2LAL.mjs +658 -0
- package/dist/lib/browser/chunk-IMGT2LAL.mjs.map +7 -0
- package/dist/lib/browser/{chunk-PSVCPL4T.mjs → chunk-KOXMEAOS.mjs} +5 -3
- package/dist/lib/browser/chunk-KOXMEAOS.mjs.map +7 -0
- package/dist/lib/browser/chunk-OI7AAA6Q.mjs +15 -0
- package/dist/lib/browser/chunk-OI7AAA6Q.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +106 -1212
- 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/keyboard-MUBRTPI5.mjs +46 -0
- package/dist/lib/browser/keyboard-MUBRTPI5.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-HT65TAYL.mjs +111 -0
- package/dist/lib/browser/state-HT65TAYL.mjs.map +7 -0
- package/dist/types/src/NavTreePlugin.d.ts +1 -3
- package/dist/types/src/NavTreePlugin.d.ts.map +1 -1
- package/dist/types/src/capabilities/app-graph-builder.d.ts +181 -0
- package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -0
- package/dist/types/src/capabilities/capabilities.d.ts +17 -0
- package/dist/types/src/capabilities/capabilities.d.ts.map +1 -0
- package/dist/types/src/capabilities/index.d.ts +195 -0
- package/dist/types/src/capabilities/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/intent-resolver.d.ts +4 -0
- package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -0
- package/dist/types/src/capabilities/keyboard.d.ts +4 -0
- package/dist/types/src/capabilities/keyboard.d.ts.map +1 -0
- package/dist/types/src/capabilities/react-surface.d.ts +4 -0
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
- package/dist/types/src/capabilities/state.d.ts +17 -0
- package/dist/types/src/capabilities/state.d.ts.map +1 -0
- package/dist/types/src/components/CommandsTrigger.d.ts.map +1 -1
- package/dist/types/src/components/NavTree.d.ts +2 -2
- package/dist/types/src/components/NavTree.d.ts.map +1 -1
- package/dist/types/src/components/NavTreeContainer.d.ts.map +1 -1
- package/dist/types/src/components/NavTreeFooter.d.ts.map +1 -1
- package/dist/types/src/components/NavTreeItemAction.d.ts +4 -8
- package/dist/types/src/components/NavTreeItemAction.d.ts.map +1 -1
- package/dist/types/src/components/NavTreeItemAction.stories.d.ts +0 -5
- package/dist/types/src/components/NavTreeItemAction.stories.d.ts.map +1 -1
- package/dist/types/src/components/NotchStart.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +1 -0
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/events.d.ts +4 -0
- package/dist/types/src/events.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +3 -2
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/meta.d.ts +2 -2
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +0 -1
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types.d.ts +1 -1
- package/dist/types/src/types.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -0
- package/package.json +31 -38
- package/src/NavTreePlugin.tsx +70 -287
- package/src/capabilities/app-graph-builder.ts +40 -0
- package/src/capabilities/capabilities.ts +18 -0
- package/src/capabilities/index.ts +13 -0
- package/src/capabilities/intent-resolver.ts +30 -0
- package/src/capabilities/keyboard.ts +54 -0
- package/src/capabilities/react-surface.tsx +82 -0
- package/src/capabilities/state.ts +100 -0
- package/src/components/CommandsDialog.tsx +3 -3
- package/src/components/CommandsTrigger.tsx +11 -8
- package/src/components/NavTree.tsx +6 -11
- package/src/components/NavTreeContainer.tsx +22 -56
- package/src/components/NavTreeFooter.tsx +21 -18
- package/src/components/NavTreeItemAction.stories.tsx +0 -2
- package/src/components/NavTreeItemAction.tsx +51 -317
- package/src/components/NotchStart.tsx +8 -7
- package/src/components/index.ts +1 -0
- package/src/events.ts +11 -0
- package/src/index.ts +3 -4
- package/src/meta.ts +3 -1
- package/src/translations.ts +0 -1
- package/src/types.ts +1 -1
- package/dist/lib/browser/chunk-PSVCPL4T.mjs.map +0 -7
- package/dist/lib/browser/meta.mjs +0 -11
- package/dist/lib/browser/meta.mjs.map +0 -7
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { effect } from '@preact/signals-core';
|
|
6
|
+
|
|
7
|
+
import { Capabilities, contributes, type PluginsContext } from '@dxos/app-framework';
|
|
8
|
+
import { type ReactiveObject, create } from '@dxos/live-object';
|
|
9
|
+
import { Path } from '@dxos/react-ui-mosaic';
|
|
10
|
+
|
|
11
|
+
import { NavTreeCapabilities } from './capabilities';
|
|
12
|
+
import { NAVTREE_PLUGIN } from '../meta';
|
|
13
|
+
|
|
14
|
+
const KEY = `${NAVTREE_PLUGIN}/state`;
|
|
15
|
+
|
|
16
|
+
const getInitialState = () => {
|
|
17
|
+
const stringified = localStorage.getItem(KEY);
|
|
18
|
+
if (!stringified) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
const cached: [string, { open: boolean; current: boolean }][] = JSON.parse(stringified);
|
|
24
|
+
return cached.map(
|
|
25
|
+
([key, value]): [
|
|
26
|
+
string,
|
|
27
|
+
ReactiveObject<{
|
|
28
|
+
open: boolean;
|
|
29
|
+
current: boolean;
|
|
30
|
+
}>,
|
|
31
|
+
] => [key, create({ open: value.open, current: false })],
|
|
32
|
+
);
|
|
33
|
+
} catch {}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export default (context: PluginsContext) => {
|
|
37
|
+
// TODO(wittjosiah): This currently needs to be not a ReactiveObject at the root.
|
|
38
|
+
// If it is a ReactiveObject then React errors when initializing new paths because of state change during render.
|
|
39
|
+
// Ideally this could be a ReactiveObject but be able to access and update the root level without breaking render.
|
|
40
|
+
// Wrapping accesses and updates in `untracked` didn't seem to work in all cases.
|
|
41
|
+
const state = new Map<string, ReactiveObject<{ open: boolean; current: boolean }>>(
|
|
42
|
+
getInitialState() ?? [
|
|
43
|
+
// TODO(thure): Initialize these dynamically.
|
|
44
|
+
['root', create({ open: true, current: false })],
|
|
45
|
+
['root~dxos.org/plugin/space-spaces', create({ open: true, current: false })],
|
|
46
|
+
['root~dxos.org/plugin/files', create({ open: true, current: false })],
|
|
47
|
+
],
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const getItem = (_path: string[]) => {
|
|
51
|
+
const path = Path.create(..._path);
|
|
52
|
+
const value = state.get(path) ?? create({ open: false, current: false });
|
|
53
|
+
if (!state.has(path)) {
|
|
54
|
+
state.set(path, value);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return value;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const setItem = (path: string[], key: 'open' | 'current', next: boolean) => {
|
|
61
|
+
const value = getItem(path);
|
|
62
|
+
value[key] = next;
|
|
63
|
+
|
|
64
|
+
localStorage.setItem(KEY, JSON.stringify(Array.from(state.entries())));
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const isOpen = (path: string[]) => getItem(path).open;
|
|
68
|
+
const isCurrent = (path: string[]) => getItem(path).current;
|
|
69
|
+
|
|
70
|
+
const location = context.requestCapability(Capabilities.Location);
|
|
71
|
+
const layout = context.requestCapability(Capabilities.Layout);
|
|
72
|
+
|
|
73
|
+
let previous: string[] = [];
|
|
74
|
+
const unsubscribe = effect(() => {
|
|
75
|
+
const part = layout.layoutMode === 'solo' ? 'solo' : 'main';
|
|
76
|
+
const current = location.active[part]?.map(({ id }) => id) ?? [];
|
|
77
|
+
const removed = previous.filter((id) => !current.includes(id));
|
|
78
|
+
previous = current;
|
|
79
|
+
|
|
80
|
+
// TODO(wittjosiah): This is setTimeout because there's a race between the keys be initialized.
|
|
81
|
+
// This could be avoided if the location was a path as well and not just an id.
|
|
82
|
+
setTimeout(() => {
|
|
83
|
+
removed.forEach((id) => {
|
|
84
|
+
const keys = Array.from(state.keys()).filter((key) => Path.last(key) === id);
|
|
85
|
+
keys.forEach((key) => {
|
|
86
|
+
setItem(Path.parts(key), 'current', false);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
current.forEach((id) => {
|
|
91
|
+
const keys = Array.from(new Set([...state.keys(), id])).filter((key) => Path.last(key) === id);
|
|
92
|
+
keys.forEach((key) => {
|
|
93
|
+
setItem(Path.parts(key), 'current', true);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
return contributes(NavTreeCapabilities.State, { state, getItem, setItem, isOpen, isCurrent }, () => unsubscribe());
|
|
100
|
+
};
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import React, { useMemo, useState } from 'react';
|
|
6
6
|
|
|
7
|
-
import { useIntentDispatcher, LayoutAction } from '@dxos/app-framework';
|
|
7
|
+
import { useIntentDispatcher, LayoutAction, createIntent } from '@dxos/app-framework';
|
|
8
8
|
import { type ActionLike, isActionGroup, isAction } from '@dxos/app-graph';
|
|
9
9
|
import { Keyboard, keySymbols } from '@dxos/keyboard';
|
|
10
10
|
import { useGraph } from '@dxos/plugin-graph';
|
|
@@ -19,7 +19,7 @@ import { KEY_BINDING, NAVTREE_PLUGIN } from '../meta';
|
|
|
19
19
|
export const CommandsDialogContent = ({ selected: initial }: { selected?: string }) => {
|
|
20
20
|
const { t } = useTranslation(NAVTREE_PLUGIN);
|
|
21
21
|
const [selected, setSelected] = useState<string | undefined>(initial);
|
|
22
|
-
const dispatch = useIntentDispatcher();
|
|
22
|
+
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
23
23
|
const { graph } = useGraph();
|
|
24
24
|
|
|
25
25
|
// Traverse graph.
|
|
@@ -83,7 +83,7 @@ export const CommandsDialogContent = ({ selected: initial }: { selected?: string
|
|
|
83
83
|
return;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
void dispatch(
|
|
86
|
+
void dispatch(createIntent(LayoutAction.SetLayout, { element: 'dialog', state: false }));
|
|
87
87
|
setTimeout(() => {
|
|
88
88
|
const node = graph.nodes(group ?? action, { relation: 'inbound' })[0];
|
|
89
89
|
void (node && isAction(action) && action.data({ node, caller: KEY_BINDING }));
|
|
@@ -5,24 +5,27 @@
|
|
|
5
5
|
import { MagnifyingGlass } from '@phosphor-icons/react';
|
|
6
6
|
import React from 'react';
|
|
7
7
|
|
|
8
|
-
import { LayoutAction,
|
|
8
|
+
import { createIntent, LayoutAction, useIntentDispatcher } from '@dxos/app-framework';
|
|
9
9
|
import { Button, useTranslation } from '@dxos/react-ui';
|
|
10
10
|
import { getSize } from '@dxos/react-ui-theme';
|
|
11
11
|
|
|
12
|
-
import { NAVTREE_PLUGIN } from '../meta';
|
|
12
|
+
import { COMMANDS_DIALOG, NAVTREE_PLUGIN } from '../meta';
|
|
13
13
|
|
|
14
14
|
// TODO(thure): Refactor to be handled by a more appropriate plugin.
|
|
15
15
|
export const CommandsTrigger = () => {
|
|
16
|
-
const { dispatch } =
|
|
16
|
+
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
17
17
|
const { t } = useTranslation(NAVTREE_PLUGIN);
|
|
18
18
|
return (
|
|
19
19
|
<Button
|
|
20
|
-
classNames='
|
|
20
|
+
classNames='m-1 !pli-1 lg:!pli-2'
|
|
21
21
|
onClick={() =>
|
|
22
|
-
dispatch(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
dispatch(
|
|
23
|
+
createIntent(LayoutAction.SetLayout, {
|
|
24
|
+
element: 'dialog',
|
|
25
|
+
component: COMMANDS_DIALOG,
|
|
26
|
+
dialogBlockAlign: 'start',
|
|
27
|
+
}),
|
|
28
|
+
)
|
|
26
29
|
}
|
|
27
30
|
>
|
|
28
31
|
<span className='text-description font-normal grow text-start'>{t('command list input placeholder')}</span>
|
|
@@ -23,14 +23,13 @@ export type NavTreeProps = Omit<
|
|
|
23
23
|
|
|
24
24
|
export const NavTree = ({ getActions, loadDescendents, renderItemEnd, popoverAnchorId, ...props }: NavTreeProps) => {
|
|
25
25
|
const renderColumns = useCallback<NonNullable<TreeProps<NavTreeItemGraphNode>['renderColumns']>>(
|
|
26
|
-
({ item, path,
|
|
26
|
+
({ item, path, open }) => {
|
|
27
27
|
return (
|
|
28
28
|
<NavTreeColumns
|
|
29
29
|
path={path}
|
|
30
30
|
node={item}
|
|
31
31
|
getActions={getActions}
|
|
32
|
-
|
|
33
|
-
setMenuOpen={setMenuOpen}
|
|
32
|
+
open={open}
|
|
34
33
|
loadDescendents={loadDescendents}
|
|
35
34
|
renderItemEnd={renderItemEnd}
|
|
36
35
|
popoverAnchorId={popoverAnchorId}
|
|
@@ -54,10 +53,9 @@ type NavTreeColumnsProps = {
|
|
|
54
53
|
path: string[];
|
|
55
54
|
node: Node;
|
|
56
55
|
getActions: (node: Node) => FlattenedActions;
|
|
57
|
-
|
|
58
|
-
setMenuOpen: (open: boolean) => void;
|
|
56
|
+
open: boolean;
|
|
59
57
|
loadDescendents?: (node: Node) => MaybePromise<void>;
|
|
60
|
-
renderItemEnd?: FC<{ node: Node }>;
|
|
58
|
+
renderItemEnd?: FC<{ node: Node; open: boolean }>;
|
|
61
59
|
popoverAnchorId?: string;
|
|
62
60
|
};
|
|
63
61
|
|
|
@@ -65,8 +63,7 @@ const NavTreeColumns = ({
|
|
|
65
63
|
path,
|
|
66
64
|
node,
|
|
67
65
|
getActions,
|
|
68
|
-
|
|
69
|
-
setMenuOpen,
|
|
66
|
+
open,
|
|
70
67
|
loadDescendents,
|
|
71
68
|
renderItemEnd: ItemEnd,
|
|
72
69
|
popoverAnchorId,
|
|
@@ -123,14 +120,12 @@ const NavTreeColumns = ({
|
|
|
123
120
|
menuActions={actions}
|
|
124
121
|
menuType='dropdown'
|
|
125
122
|
caller={NAV_TREE_ITEM}
|
|
126
|
-
menuOpen={menuOpen}
|
|
127
|
-
onChangeMenuOpen={setMenuOpen}
|
|
128
123
|
/>
|
|
129
124
|
) : (
|
|
130
125
|
<Treegrid.Cell />
|
|
131
126
|
)}
|
|
132
127
|
</ActionRoot>
|
|
133
|
-
{ItemEnd && <ItemEnd node={node} />}
|
|
128
|
+
{ItemEnd && <ItemEnd node={node} open={open} />}
|
|
134
129
|
</>
|
|
135
130
|
);
|
|
136
131
|
};
|
|
@@ -7,17 +7,16 @@ import { extractInstruction, type Instruction } from '@atlaskit/pragmatic-drag-a
|
|
|
7
7
|
import { untracked } from '@preact/signals-core';
|
|
8
8
|
import React, { memo, useCallback, useEffect } from 'react';
|
|
9
9
|
|
|
10
|
-
import { LayoutAction, NavigationAction,
|
|
10
|
+
import { createIntent, LayoutAction, NavigationAction, useIntentDispatcher, Surface } from '@dxos/app-framework';
|
|
11
11
|
import { isAction, isActionLike, type Node } from '@dxos/app-graph';
|
|
12
12
|
import { useGraph } from '@dxos/plugin-graph';
|
|
13
13
|
import { isEchoObject, isSpace } from '@dxos/react-client/echo';
|
|
14
|
-
import {
|
|
14
|
+
import { useMediaQuery, useSidebars } from '@dxos/react-ui';
|
|
15
15
|
import { isTreeData, type TreeData, type PropsFromTreeItem } from '@dxos/react-ui-list';
|
|
16
16
|
import { mx } from '@dxos/react-ui-theme';
|
|
17
17
|
import { arrayMove } from '@dxos/util';
|
|
18
18
|
|
|
19
19
|
import { NAV_TREE_ITEM, NavTree, type NavTreeProps } from './NavTree';
|
|
20
|
-
import { NavTreeFooter } from './NavTreeFooter';
|
|
21
20
|
import { NAVTREE_PLUGIN } from '../meta';
|
|
22
21
|
import { type NavTreeItemGraphNode } from '../types';
|
|
23
22
|
import {
|
|
@@ -32,8 +31,8 @@ import {
|
|
|
32
31
|
// TODO(thure): Is NavTree truly authoritative in this regard?
|
|
33
32
|
export const NODE_TYPE = 'dxos/app-graph/node';
|
|
34
33
|
|
|
35
|
-
const renderItemEnd = ({ node }: { node: Node }) => (
|
|
36
|
-
<Surface role='navtree-item-end' data={{
|
|
34
|
+
const renderItemEnd = ({ node, open }: { node: Node; open: boolean }) => (
|
|
35
|
+
<Surface role='navtree-item-end' data={{ id: node.id, subject: node.data, open }} limit={1} />
|
|
37
36
|
);
|
|
38
37
|
|
|
39
38
|
export type NavTreeContainerProps = {
|
|
@@ -43,7 +42,7 @@ export type NavTreeContainerProps = {
|
|
|
43
42
|
export const NavTreeContainer = memo(({ isCurrent, popoverAnchorId, ...props }: NavTreeContainerProps) => {
|
|
44
43
|
const { closeNavigationSidebar } = useSidebars(NAVTREE_PLUGIN);
|
|
45
44
|
const [isLg] = useMediaQuery('lg', { ssr: false });
|
|
46
|
-
const dispatch = useIntentDispatcher();
|
|
45
|
+
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
47
46
|
const { graph } = useGraph();
|
|
48
47
|
|
|
49
48
|
const getActions = useCallback((node: Node) => naturalGetActions(graph, node), [graph]);
|
|
@@ -124,28 +123,11 @@ export const NavTreeContainer = memo(({ isCurrent, popoverAnchorId, ...props }:
|
|
|
124
123
|
|
|
125
124
|
const current = isCurrent(path, node);
|
|
126
125
|
if (!current) {
|
|
127
|
-
void dispatch({
|
|
128
|
-
action: NavigationAction.OPEN,
|
|
129
|
-
data: {
|
|
130
|
-
activeParts: {
|
|
131
|
-
main: [node.id],
|
|
132
|
-
},
|
|
133
|
-
},
|
|
134
|
-
});
|
|
126
|
+
void dispatch(createIntent(NavigationAction.Open, { activeParts: { main: [node.id] } }));
|
|
135
127
|
} else if (option) {
|
|
136
|
-
void dispatch({
|
|
137
|
-
action: NavigationAction.CLOSE,
|
|
138
|
-
data: {
|
|
139
|
-
activeParts: {
|
|
140
|
-
main: [node.id],
|
|
141
|
-
},
|
|
142
|
-
},
|
|
143
|
-
});
|
|
128
|
+
void dispatch(createIntent(NavigationAction.Close, { activeParts: { main: [node.id] } }));
|
|
144
129
|
} else {
|
|
145
|
-
void dispatch({
|
|
146
|
-
action: LayoutAction.SCROLL_INTO_VIEW,
|
|
147
|
-
data: { id: node.id },
|
|
148
|
-
});
|
|
130
|
+
void dispatch(createIntent(LayoutAction.ScrollIntoView, { id: node.id }));
|
|
149
131
|
}
|
|
150
132
|
|
|
151
133
|
const defaultAction = graph.actions(node).find((action) => action.properties?.disposition === 'default');
|
|
@@ -219,36 +201,20 @@ export const NavTreeContainer = memo(({ isCurrent, popoverAnchorId, ...props }:
|
|
|
219
201
|
});
|
|
220
202
|
}, [graph]);
|
|
221
203
|
|
|
204
|
+
// TODO(thure): What gives this an inline `overflow: initial`?
|
|
222
205
|
return (
|
|
223
|
-
<
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
id={graph.root.id}
|
|
237
|
-
getActions={getActions}
|
|
238
|
-
getItems={getItems}
|
|
239
|
-
getProps={getProps}
|
|
240
|
-
isCurrent={isCurrent}
|
|
241
|
-
loadDescendents={loadDescendents}
|
|
242
|
-
renderItemEnd={renderItemEnd}
|
|
243
|
-
popoverAnchorId={popoverAnchorId}
|
|
244
|
-
canDrop={canDrop}
|
|
245
|
-
onSelect={handleSelect}
|
|
246
|
-
{...props}
|
|
247
|
-
/>
|
|
248
|
-
</div>
|
|
249
|
-
|
|
250
|
-
<NavTreeFooter />
|
|
251
|
-
</div>
|
|
252
|
-
</ElevationProvider>
|
|
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
|
+
/>
|
|
253
219
|
);
|
|
254
220
|
});
|
|
@@ -2,16 +2,15 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { ArrowSquareOut, GearSix, Warning } from '@phosphor-icons/react';
|
|
6
5
|
import { formatDistance } from 'date-fns/formatDistance';
|
|
7
6
|
import React from 'react';
|
|
8
7
|
|
|
9
8
|
import {
|
|
10
9
|
type LayoutPart,
|
|
11
10
|
SettingsAction,
|
|
12
|
-
parseNavigationPlugin,
|
|
13
|
-
useResolvePlugin,
|
|
14
11
|
useIntentDispatcher,
|
|
12
|
+
createIntent,
|
|
13
|
+
usePluginManager,
|
|
15
14
|
} from '@dxos/app-framework';
|
|
16
15
|
import { useConfig } from '@dxos/react-client';
|
|
17
16
|
import {
|
|
@@ -24,13 +23,15 @@ import {
|
|
|
24
23
|
useDefaultValue,
|
|
25
24
|
useSidebars,
|
|
26
25
|
useTranslation,
|
|
26
|
+
Icon,
|
|
27
|
+
IconButton,
|
|
27
28
|
} from '@dxos/react-ui';
|
|
28
29
|
import { LayoutControls } from '@dxos/react-ui-stack';
|
|
29
|
-
import {
|
|
30
|
+
import { mx } from '@dxos/react-ui-theme';
|
|
30
31
|
|
|
31
32
|
import { NAVTREE_PLUGIN } from '../meta';
|
|
32
33
|
|
|
33
|
-
const buttonStyles = 'pli-1.5 text-xs font-normal';
|
|
34
|
+
const buttonStyles = '!pli-1.5 text-xs font-normal';
|
|
34
35
|
|
|
35
36
|
const repo = 'https://github.com/dxos/dxos';
|
|
36
37
|
|
|
@@ -41,9 +42,9 @@ export const NavTreeFooter = (props: { layoutPart?: LayoutPart }) => {
|
|
|
41
42
|
const config = useConfig();
|
|
42
43
|
const { t } = useTranslation(NAVTREE_PLUGIN);
|
|
43
44
|
const { navigationSidebarOpen } = useSidebars(NAVTREE_PLUGIN);
|
|
44
|
-
const dispatch = useIntentDispatcher();
|
|
45
|
+
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
45
46
|
const { version, timestamp, commitHash } = config.values.runtime?.app?.build ?? {};
|
|
46
|
-
const
|
|
47
|
+
const manager = usePluginManager();
|
|
47
48
|
const [_, v] = version?.match(VERSION_REGEX) ?? [];
|
|
48
49
|
|
|
49
50
|
const releaseUrl =
|
|
@@ -57,7 +58,7 @@ export const NavTreeFooter = (props: { layoutPart?: LayoutPart }) => {
|
|
|
57
58
|
<div
|
|
58
59
|
role='none'
|
|
59
60
|
className={mx(
|
|
60
|
-
'flex
|
|
61
|
+
'flex pbe-[env(safe-area-inset-bottom)] box-content justify-end',
|
|
61
62
|
layoutPart === 'complementary' && 'md:justify-end flex-row-reverse',
|
|
62
63
|
)}
|
|
63
64
|
>
|
|
@@ -75,7 +76,7 @@ export const NavTreeFooter = (props: { layoutPart?: LayoutPart }) => {
|
|
|
75
76
|
>
|
|
76
77
|
<Message.Root valence='warning' className='rounded-be-none p-5'>
|
|
77
78
|
<Message.Title>
|
|
78
|
-
<
|
|
79
|
+
<Icon icon='ph--warning--duotone' size={6} classNames='inline mie-2' />
|
|
79
80
|
<span>{t('warning title')}</span>
|
|
80
81
|
</Message.Title>
|
|
81
82
|
<Message.Body>
|
|
@@ -83,7 +84,7 @@ export const NavTreeFooter = (props: { layoutPart?: LayoutPart }) => {
|
|
|
83
84
|
<br />
|
|
84
85
|
<Link href={previewUrl} target='_blank' rel='noreferrer' variant='neutral'>
|
|
85
86
|
{t('learn more label')}
|
|
86
|
-
<
|
|
87
|
+
<Icon icon='ph--arrow-square-out--bold' classNames='inline mis-1' />
|
|
87
88
|
</Link>
|
|
88
89
|
</Message.Body>
|
|
89
90
|
</Message.Root>
|
|
@@ -96,7 +97,7 @@ export const NavTreeFooter = (props: { layoutPart?: LayoutPart }) => {
|
|
|
96
97
|
<br />
|
|
97
98
|
<Link href={releaseUrl} target='_blank' rel='noreferrer' variant='neutral'>
|
|
98
99
|
{t('see release label')}
|
|
99
|
-
<
|
|
100
|
+
<Icon icon='ph--arrow-square-out--bold' classNames='inline mis-1' />
|
|
100
101
|
</Link>
|
|
101
102
|
</p>
|
|
102
103
|
)}
|
|
@@ -120,17 +121,19 @@ export const NavTreeFooter = (props: { layoutPart?: LayoutPart }) => {
|
|
|
120
121
|
<Tooltip.Root>
|
|
121
122
|
<Tooltip.Trigger asChild>
|
|
122
123
|
{/* TODO(burdon): Reconcile with action created by LayoutPlugin. */}
|
|
123
|
-
<
|
|
124
|
+
<IconButton
|
|
125
|
+
icon='ph--gear-six--regular'
|
|
126
|
+
iconOnly
|
|
127
|
+
label={t('open settings label')}
|
|
128
|
+
size={4}
|
|
124
129
|
variant='ghost'
|
|
125
130
|
classNames={buttonStyles}
|
|
126
131
|
data-testid='treeView.openSettings'
|
|
127
132
|
data-joyride='welcome/settings'
|
|
128
133
|
{...(!navigationSidebarOpen && { tabIndex: -1 })}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
<GearSix className={mx(getSize(5), 'rotate-90')} />
|
|
133
|
-
</Button>
|
|
134
|
+
iconClassNames='rotate-90'
|
|
135
|
+
onClick={() => dispatch(createIntent(SettingsAction.Open))}
|
|
136
|
+
/>
|
|
134
137
|
</Tooltip.Trigger>
|
|
135
138
|
<Tooltip.Portal>
|
|
136
139
|
<Tooltip.Content classNames='z-[12]'>
|
|
@@ -141,7 +144,7 @@ export const NavTreeFooter = (props: { layoutPart?: LayoutPart }) => {
|
|
|
141
144
|
</Tooltip.Root>
|
|
142
145
|
|
|
143
146
|
{/* NOTE(thure): Unpinning from the NavTree’s default position in Deck is temporarily disabled. */}
|
|
144
|
-
{
|
|
147
|
+
{manager.enabled.includes('dxos.org/plugin/deck') && (
|
|
145
148
|
<LayoutControls
|
|
146
149
|
variant='hide-disabled'
|
|
147
150
|
capabilities={{
|