@dxos/plugin-simple-layout 0.8.4-main.bc674ce → 0.8.4-main.bcb3aa67d6
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/index.mjs +44 -64
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +44 -63
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/SimpleLayoutPlugin.d.ts +1 -1
- package/dist/types/src/SimpleLayoutPlugin.d.ts.map +1 -1
- package/dist/types/src/capabilities/app-graph-builder.d.ts +6 -0
- package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -0
- package/dist/types/src/capabilities/index.d.ts +21 -6
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/operation-handler.d.ts +6 -0
- package/dist/types/src/capabilities/operation-handler.d.ts.map +1 -0
- package/dist/types/src/capabilities/{react-root/react-root.d.ts → react-root.d.ts} +1 -1
- package/dist/types/src/capabilities/react-root.d.ts.map +1 -0
- package/dist/types/src/capabilities/react-surface.d.ts +5 -0
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
- package/dist/types/src/capabilities/{spotlight-dismiss/spotlight-dismiss.d.ts → spotlight-dismiss.d.ts} +1 -1
- package/dist/types/src/capabilities/spotlight-dismiss.d.ts.map +1 -0
- package/dist/types/src/capabilities/{state/state.d.ts → state.d.ts} +2 -2
- package/dist/types/src/capabilities/state.d.ts.map +1 -0
- package/dist/types/src/capabilities/url-handler.d.ts +12 -0
- package/dist/types/src/capabilities/url-handler.d.ts.map +1 -0
- package/dist/types/src/components/ContentError.stories.d.ts +26 -21
- package/dist/types/src/components/ContentError.stories.d.ts.map +1 -1
- package/dist/types/src/components/DebugOverlay/DebugOverlay.d.ts +19 -0
- package/dist/types/src/components/DebugOverlay/DebugOverlay.d.ts.map +1 -0
- package/dist/types/src/components/DebugOverlay/index.d.ts +2 -0
- package/dist/types/src/components/DebugOverlay/index.d.ts.map +1 -0
- package/dist/types/src/components/Home/Home.d.ts.map +1 -1
- package/dist/types/src/components/Loading/Loading.d.ts +3 -0
- package/dist/types/src/components/Loading/Loading.d.ts.map +1 -0
- package/dist/types/src/components/{ContentLoading.stories.d.ts → Loading/Loading.stories.d.ts} +1 -1
- package/dist/types/src/components/Loading/Loading.stories.d.ts.map +1 -0
- package/dist/types/src/components/Loading/index.d.ts +2 -0
- package/dist/types/src/components/Loading/index.d.ts.map +1 -0
- package/dist/types/src/components/MobileLayout/MobileLayout.d.ts +35 -0
- package/dist/types/src/components/MobileLayout/MobileLayout.d.ts.map +1 -0
- package/dist/types/src/components/MobileLayout/MobileLayout.stories.d.ts +7 -0
- package/dist/types/src/components/MobileLayout/MobileLayout.stories.d.ts.map +1 -0
- package/dist/types/src/components/MobileLayout/index.d.ts +2 -0
- package/dist/types/src/components/MobileLayout/index.d.ts.map +1 -0
- package/dist/types/src/components/NavBranch/NavBranch.d.ts +11 -0
- package/dist/types/src/components/NavBranch/NavBranch.d.ts.map +1 -0
- package/dist/types/src/components/NavBranch/index.d.ts +2 -0
- package/dist/types/src/components/NavBranch/index.d.ts.map +1 -0
- package/dist/types/src/components/Popover/Popover.d.ts.map +1 -1
- package/dist/types/src/components/SimpleLayout/AppBar.d.ts +28 -0
- package/dist/types/src/components/SimpleLayout/AppBar.d.ts.map +1 -0
- package/dist/types/src/components/SimpleLayout/AppBar.stories.d.ts +54 -0
- package/dist/types/src/components/SimpleLayout/AppBar.stories.d.ts.map +1 -0
- package/dist/types/src/components/SimpleLayout/Drawer.d.ts +1 -1
- package/dist/types/src/components/SimpleLayout/Drawer.d.ts.map +1 -1
- package/dist/types/src/components/SimpleLayout/Main.d.ts.map +1 -1
- package/dist/types/src/components/SimpleLayout/NavBar.d.ts +17 -8
- package/dist/types/src/components/SimpleLayout/NavBar.d.ts.map +1 -1
- package/dist/types/src/components/SimpleLayout/NavBar.stories.d.ts +35 -25
- package/dist/types/src/components/SimpleLayout/NavBar.stories.d.ts.map +1 -1
- package/dist/types/src/components/SimpleLayout/SimpleLayout.d.ts.map +1 -1
- package/dist/types/src/components/SimpleLayout/SimpleLayout.stories.d.ts +26 -25
- package/dist/types/src/components/SimpleLayout/SimpleLayout.stories.d.ts.map +1 -1
- package/dist/types/src/components/SimpleLayout/index.d.ts +3 -0
- package/dist/types/src/components/SimpleLayout/index.d.ts.map +1 -1
- package/dist/types/src/components/hooks.d.ts +4 -2
- package/dist/types/src/components/hooks.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +4 -2
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/hooks/actions.d.ts +19 -0
- package/dist/types/src/hooks/actions.d.ts.map +1 -0
- package/dist/types/src/hooks/index.d.ts +4 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useAppBarProps.d.ts +7 -0
- package/dist/types/src/hooks/useAppBarProps.d.ts.map +1 -0
- package/dist/types/src/hooks/useCompanions.d.ts +5 -1
- package/dist/types/src/hooks/useCompanions.d.ts.map +1 -1
- package/dist/types/src/hooks/useDrawerActions.d.ts +13 -0
- package/dist/types/src/hooks/useDrawerActions.d.ts.map +1 -0
- package/dist/types/src/hooks/useNavbarActions.d.ts +14 -0
- package/dist/types/src/hooks/useNavbarActions.d.ts.map +1 -0
- package/dist/types/src/hooks/useSimpleLayoutState.d.ts +3 -3
- package/dist/types/src/hooks/useSimpleLayoutState.d.ts.map +1 -1
- package/dist/types/src/operations/close.d.ts +5 -0
- package/dist/types/src/operations/close.d.ts.map +1 -0
- package/dist/types/src/operations/index.d.ts +3 -0
- package/dist/types/src/operations/index.d.ts.map +1 -0
- package/dist/types/src/operations/open.d.ts +5 -0
- package/dist/types/src/operations/open.d.ts.map +1 -0
- package/dist/types/src/operations/revert-workspace.d.ts +5 -0
- package/dist/types/src/operations/revert-workspace.d.ts.map +1 -0
- package/dist/types/src/operations/set-layout-mode.d.ts +5 -0
- package/dist/types/src/operations/set-layout-mode.d.ts.map +1 -0
- package/dist/types/src/operations/set.d.ts +5 -0
- package/dist/types/src/operations/set.d.ts.map +1 -0
- package/dist/types/src/operations/state-access.d.ts +8 -0
- package/dist/types/src/operations/state-access.d.ts.map +1 -0
- package/dist/types/src/operations/switch-workspace.d.ts +5 -0
- package/dist/types/src/operations/switch-workspace.d.ts.map +1 -0
- package/dist/types/src/operations/update-complementary.d.ts +5 -0
- package/dist/types/src/operations/update-complementary.d.ts.map +1 -0
- package/dist/types/src/operations/update-dialog.d.ts +5 -0
- package/dist/types/src/operations/update-dialog.d.ts.map +1 -0
- package/dist/types/src/operations/update-popover.d.ts +5 -0
- package/dist/types/src/operations/update-popover.d.ts.map +1 -0
- package/dist/types/src/operations/update-sidebar.d.ts +5 -0
- package/dist/types/src/operations/update-sidebar.d.ts.map +1 -0
- package/dist/types/src/translations.d.ts +26 -19
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/capabilities.d.ts +7 -6
- package/dist/types/src/types/capabilities.d.ts.map +1 -1
- package/dist/types/src/types/events.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +46 -30
- package/src/SimpleLayoutPlugin.ts +24 -13
- package/src/capabilities/app-graph-builder.ts +21 -0
- package/src/capabilities/index.ts +13 -6
- package/src/capabilities/operation-handler.ts +14 -0
- package/src/capabilities/{react-root/react-root.tsx → react-root.tsx} +4 -4
- package/src/capabilities/react-surface.tsx +51 -0
- package/src/capabilities/{spotlight-dismiss/spotlight-dismiss.ts → spotlight-dismiss.ts} +2 -2
- package/src/capabilities/{state/state.tsx → state.tsx} +6 -5
- package/src/capabilities/url-handler.ts +161 -0
- package/src/components/ContentError.stories.tsx +8 -7
- package/src/components/DebugOverlay/DebugOverlay.tsx +96 -0
- package/src/components/DebugOverlay/index.ts +5 -0
- package/src/components/Dialog/Dialog.tsx +6 -6
- package/src/components/Home/Home.tsx +50 -43
- package/src/components/{ContentLoading.stories.tsx → Loading/Loading.stories.tsx} +5 -5
- package/src/components/{ContentLoading.tsx → Loading/Loading.tsx} +2 -2
- package/src/components/Loading/index.ts +5 -0
- package/src/components/MobileLayout/MobileLayout.stories.tsx +133 -0
- package/src/components/MobileLayout/MobileLayout.tsx +374 -0
- package/src/components/MobileLayout/index.ts +5 -0
- package/src/components/NavBranch/NavBranch.tsx +127 -0
- package/src/components/{Workspace → NavBranch}/index.ts +1 -1
- package/src/components/Popover/Popover.tsx +9 -9
- package/src/components/SimpleLayout/AppBar.stories.tsx +144 -0
- package/src/components/SimpleLayout/AppBar.tsx +93 -0
- package/src/components/SimpleLayout/Drawer.tsx +27 -82
- package/src/components/SimpleLayout/Main.tsx +40 -34
- package/src/components/SimpleLayout/NavBar.stories.tsx +131 -23
- package/src/components/SimpleLayout/NavBar.tsx +18 -51
- package/src/components/SimpleLayout/SimpleLayout.stories.tsx +45 -57
- package/src/components/SimpleLayout/SimpleLayout.tsx +40 -22
- package/src/components/SimpleLayout/index.ts +3 -0
- package/src/components/hooks.ts +9 -9
- package/src/components/index.ts +4 -2
- package/src/hooks/actions.ts +84 -0
- package/src/hooks/index.ts +4 -0
- package/src/hooks/useAppBarProps.ts +115 -0
- package/src/hooks/useCompanions.ts +8 -5
- package/src/hooks/useDrawerActions.ts +100 -0
- package/src/hooks/useNavbarActions.ts +87 -0
- package/src/hooks/useSimpleLayoutState.ts +5 -5
- package/src/meta.ts +1 -1
- package/src/operations/close.ts +34 -0
- package/src/operations/index.ts +16 -0
- package/src/operations/open.ts +63 -0
- package/src/operations/revert-workspace.ts +22 -0
- package/src/operations/set-layout-mode.ts +12 -0
- package/src/operations/set.ts +23 -0
- package/src/operations/state-access.ts +19 -0
- package/src/operations/switch-workspace.ts +26 -0
- package/src/operations/update-complementary.ts +35 -0
- package/src/operations/update-dialog.ts +28 -0
- package/src/operations/update-popover.ts +35 -0
- package/src/operations/update-sidebar.ts +12 -0
- package/src/translations.ts +21 -19
- package/src/types/capabilities.ts +12 -8
- package/src/types/events.ts +3 -2
- package/dist/lib/browser/chunk-LR3EE3VB.mjs +0 -789
- package/dist/lib/browser/chunk-LR3EE3VB.mjs.map +0 -7
- package/dist/lib/browser/chunk-P77G4YTR.mjs +0 -29
- package/dist/lib/browser/chunk-P77G4YTR.mjs.map +0 -7
- package/dist/lib/browser/operation-resolver-775UYAC2.mjs +0 -203
- package/dist/lib/browser/operation-resolver-775UYAC2.mjs.map +0 -7
- package/dist/lib/browser/react-root-KM55OMGJ.mjs +0 -21
- package/dist/lib/browser/react-root-KM55OMGJ.mjs.map +0 -7
- package/dist/lib/browser/react-surface-BABGAWGY.mjs +0 -39
- package/dist/lib/browser/react-surface-BABGAWGY.mjs.map +0 -7
- package/dist/lib/browser/spotlight-dismiss-VSNOPETH.mjs +0 -66
- package/dist/lib/browser/spotlight-dismiss-VSNOPETH.mjs.map +0 -7
- package/dist/lib/browser/state-OUFTC2KV.mjs +0 -47
- package/dist/lib/browser/state-OUFTC2KV.mjs.map +0 -7
- package/dist/lib/browser/url-handler-DOUFQIAC.mjs +0 -54
- package/dist/lib/browser/url-handler-DOUFQIAC.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-F5TEKVJG.mjs +0 -31
- package/dist/lib/node-esm/chunk-F5TEKVJG.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-HB2B3LLG.mjs +0 -790
- package/dist/lib/node-esm/chunk-HB2B3LLG.mjs.map +0 -7
- package/dist/lib/node-esm/operation-resolver-LDNYS3DI.mjs +0 -204
- package/dist/lib/node-esm/operation-resolver-LDNYS3DI.mjs.map +0 -7
- package/dist/lib/node-esm/react-root-36UYFEEB.mjs +0 -22
- package/dist/lib/node-esm/react-root-36UYFEEB.mjs.map +0 -7
- package/dist/lib/node-esm/react-surface-CGHFVWU3.mjs +0 -40
- package/dist/lib/node-esm/react-surface-CGHFVWU3.mjs.map +0 -7
- package/dist/lib/node-esm/spotlight-dismiss-L5PCWIJG.mjs +0 -68
- package/dist/lib/node-esm/spotlight-dismiss-L5PCWIJG.mjs.map +0 -7
- package/dist/lib/node-esm/state-Q2ZA26W5.mjs +0 -48
- package/dist/lib/node-esm/state-Q2ZA26W5.mjs.map +0 -7
- package/dist/lib/node-esm/url-handler-DVAZZEUO.mjs +0 -55
- package/dist/lib/node-esm/url-handler-DVAZZEUO.mjs.map +0 -7
- package/dist/types/src/capabilities/operation-resolver/index.d.ts +0 -3
- package/dist/types/src/capabilities/operation-resolver/index.d.ts.map +0 -1
- package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts +0 -5
- package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts.map +0 -1
- package/dist/types/src/capabilities/react-root/index.d.ts +0 -6
- package/dist/types/src/capabilities/react-root/index.d.ts.map +0 -1
- package/dist/types/src/capabilities/react-root/react-root.d.ts.map +0 -1
- package/dist/types/src/capabilities/react-surface/index.d.ts +0 -3
- package/dist/types/src/capabilities/react-surface/index.d.ts.map +0 -1
- package/dist/types/src/capabilities/react-surface/react-surface.d.ts +0 -5
- package/dist/types/src/capabilities/react-surface/react-surface.d.ts.map +0 -1
- package/dist/types/src/capabilities/spotlight-dismiss/index.d.ts +0 -3
- package/dist/types/src/capabilities/spotlight-dismiss/index.d.ts.map +0 -1
- package/dist/types/src/capabilities/spotlight-dismiss/spotlight-dismiss.d.ts.map +0 -1
- package/dist/types/src/capabilities/state/index.d.ts +0 -13
- package/dist/types/src/capabilities/state/index.d.ts.map +0 -1
- package/dist/types/src/capabilities/state/state.d.ts.map +0 -1
- package/dist/types/src/capabilities/url-handler/index.d.ts +0 -3
- package/dist/types/src/capabilities/url-handler/index.d.ts.map +0 -1
- package/dist/types/src/capabilities/url-handler/url-handler.d.ts +0 -10
- package/dist/types/src/capabilities/url-handler/url-handler.d.ts.map +0 -1
- package/dist/types/src/components/ContentError.d.ts +0 -5
- package/dist/types/src/components/ContentError.d.ts.map +0 -1
- package/dist/types/src/components/ContentLoading.d.ts +0 -3
- package/dist/types/src/components/ContentLoading.d.ts.map +0 -1
- package/dist/types/src/components/ContentLoading.stories.d.ts.map +0 -1
- package/dist/types/src/components/SimpleLayout/Banner.d.ts +0 -8
- package/dist/types/src/components/SimpleLayout/Banner.d.ts.map +0 -1
- package/dist/types/src/components/Workspace/Workspace.d.ts +0 -9
- package/dist/types/src/components/Workspace/Workspace.d.ts.map +0 -1
- package/dist/types/src/components/Workspace/index.d.ts +0 -2
- package/dist/types/src/components/Workspace/index.d.ts.map +0 -1
- package/src/capabilities/operation-resolver/index.ts +0 -10
- package/src/capabilities/operation-resolver/operation-resolver.ts +0 -215
- package/src/capabilities/react-root/index.ts +0 -7
- package/src/capabilities/react-surface/index.ts +0 -7
- package/src/capabilities/react-surface/react-surface.tsx +0 -40
- package/src/capabilities/spotlight-dismiss/index.ts +0 -7
- package/src/capabilities/state/index.ts +0 -9
- package/src/capabilities/url-handler/index.ts +0 -7
- package/src/capabilities/url-handler/url-handler.ts +0 -80
- package/src/components/ContentError.tsx +0 -23
- package/src/components/SimpleLayout/Banner.tsx +0 -113
- package/src/components/Workspace/Workspace.tsx +0 -115
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2025 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import * as Effect from 'effect/Effect';
|
|
6
|
-
|
|
7
|
-
import { Capability, Common } from '@dxos/app-framework';
|
|
8
|
-
import { Node } from '@dxos/plugin-graph';
|
|
9
|
-
|
|
10
|
-
import { type SimpleLayoutState, SimpleLayoutState as SimpleLayoutStateCapability } from '../../types';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* URL handler for simple layout that syncs browser URL with layout state.
|
|
14
|
-
* URL format: /{workspace} or /{workspace}/{active}
|
|
15
|
-
* Root is represented as / or /root.
|
|
16
|
-
*/
|
|
17
|
-
export default Capability.makeModule(
|
|
18
|
-
Effect.fnUntraced(function* () {
|
|
19
|
-
const { invokeSync } = yield* Capability.get(Common.Capability.OperationInvoker);
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Handle navigation events (initial load and popstate).
|
|
23
|
-
* Parses URL and updates state accordingly.
|
|
24
|
-
*/
|
|
25
|
-
const handleNavigation = () => {
|
|
26
|
-
const pathname = window.location.pathname;
|
|
27
|
-
|
|
28
|
-
// Parse URL segments: /{workspace}/{active}
|
|
29
|
-
const [_, nextWorkspace, nextActive] = pathname.split('/');
|
|
30
|
-
|
|
31
|
-
// Determine target workspace (empty or 'root' means Node.RootId).
|
|
32
|
-
const targetWorkspace = !nextWorkspace || nextWorkspace === 'root' ? Node.RootId : nextWorkspace;
|
|
33
|
-
|
|
34
|
-
// Navigate via operations (they will update state accordingly).
|
|
35
|
-
invokeSync(Common.LayoutOperation.SwitchWorkspace, { subject: targetWorkspace });
|
|
36
|
-
if (nextActive) {
|
|
37
|
-
invokeSync(Common.LayoutOperation.Open, { subject: [nextActive] });
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
// Handle initial URL and listen for browser navigation.
|
|
42
|
-
yield* Effect.sync(() => handleNavigation());
|
|
43
|
-
window.addEventListener('popstate', handleNavigation);
|
|
44
|
-
|
|
45
|
-
// Subscribe to state changes to update the URL.
|
|
46
|
-
let lastWorkspace: string | undefined;
|
|
47
|
-
let lastActive: string | undefined;
|
|
48
|
-
const unsubscribe = yield* Common.Capability.subscribeAtom(
|
|
49
|
-
SimpleLayoutStateCapability,
|
|
50
|
-
(state: SimpleLayoutState) => {
|
|
51
|
-
const { workspace, active } = state;
|
|
52
|
-
|
|
53
|
-
// Only update URL if relevant state changed.
|
|
54
|
-
if (workspace !== lastWorkspace || active !== lastActive) {
|
|
55
|
-
lastWorkspace = workspace;
|
|
56
|
-
lastActive = active;
|
|
57
|
-
|
|
58
|
-
// Build path: root is represented as /, other workspaces as /{workspace}.
|
|
59
|
-
let path: string;
|
|
60
|
-
if (workspace === Node.RootId) {
|
|
61
|
-
path = active ? `/${Node.RootId}/${active}` : '/';
|
|
62
|
-
} else {
|
|
63
|
-
path = active ? `/${workspace}/${active}` : `/${workspace}`;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (window.location.pathname !== path) {
|
|
67
|
-
history.pushState(null, '', `${path}${window.location.search}`);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
},
|
|
71
|
-
);
|
|
72
|
-
|
|
73
|
-
return Capability.contributes(Common.Capability.Null, null, () =>
|
|
74
|
-
Effect.sync(() => {
|
|
75
|
-
window.removeEventListener('popstate', handleNavigation);
|
|
76
|
-
unsubscribe();
|
|
77
|
-
}),
|
|
78
|
-
);
|
|
79
|
-
}),
|
|
80
|
-
);
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2024 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import React from 'react';
|
|
6
|
-
|
|
7
|
-
import { useTranslation } from '@dxos/react-ui';
|
|
8
|
-
import { descriptionMessage, mx } from '@dxos/ui-theme';
|
|
9
|
-
|
|
10
|
-
import { meta } from '../meta';
|
|
11
|
-
|
|
12
|
-
// TODO(burdon): Factor out.
|
|
13
|
-
export const ContentError = ({ error }: { error?: Error }) => {
|
|
14
|
-
const { t } = useTranslation(meta.id);
|
|
15
|
-
const errorString = error?.toString() ?? '';
|
|
16
|
-
return (
|
|
17
|
-
<div role='none' className='grid place-items-center overflow-y-auto attention-surface'>
|
|
18
|
-
<p role='alert' className={mx(descriptionMessage, 'p-2 break-all rounded-sm')}>
|
|
19
|
-
{error ? errorString : t('error fallback message')}
|
|
20
|
-
</p>
|
|
21
|
-
</div>
|
|
22
|
-
);
|
|
23
|
-
};
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2025 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import React, { Fragment, useCallback, useMemo } from 'react';
|
|
6
|
-
|
|
7
|
-
import { Common } from '@dxos/app-framework';
|
|
8
|
-
import { useAppGraph, useOperationInvoker } from '@dxos/app-framework/react';
|
|
9
|
-
import { Graph, Node, useActionRunner, useActions } from '@dxos/plugin-graph';
|
|
10
|
-
import { IconButton, Popover, type ThemedClassName, Toolbar, toLocalizedString, useTranslation } from '@dxos/react-ui';
|
|
11
|
-
import { DropdownMenu, MenuProvider } from '@dxos/react-ui-menu';
|
|
12
|
-
import { mx, osTranslations } from '@dxos/ui-theme';
|
|
13
|
-
|
|
14
|
-
import { useSimpleLayoutState } from '../../hooks';
|
|
15
|
-
import { meta } from '../../meta';
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Check if an item is a direct child of a workspace or collection.
|
|
19
|
-
* Returns true if any parent node has disposition 'workspace' or 'collection'.
|
|
20
|
-
*/
|
|
21
|
-
const isWorkspaceOrCollectionChild = (graph: Graph.ReadableGraph, itemId: string): boolean => {
|
|
22
|
-
const parents = Graph.getConnections(graph, itemId, 'inbound');
|
|
23
|
-
return parents.some(
|
|
24
|
-
(node) => node.properties.disposition === 'workspace' || node.properties.disposition === 'collection',
|
|
25
|
-
);
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
export type BannerProps = ThemedClassName<{
|
|
29
|
-
node?: Node.Node;
|
|
30
|
-
}>;
|
|
31
|
-
|
|
32
|
-
export const Banner = ({ node, classNames }: BannerProps) => {
|
|
33
|
-
const { t } = useTranslation(meta.id);
|
|
34
|
-
const { state } = useSimpleLayoutState();
|
|
35
|
-
const { invokePromise } = useOperationInvoker();
|
|
36
|
-
const { graph } = useAppGraph();
|
|
37
|
-
const runAction = useActionRunner();
|
|
38
|
-
|
|
39
|
-
const label = (node && toLocalizedString(node.properties.label, t)) ?? t('current app name', { ns: osTranslations });
|
|
40
|
-
|
|
41
|
-
// Get actions for the current node, filtered by disposition.
|
|
42
|
-
// NOTE: Graph expansion is handled by useLoadDescendents in Main.tsx.
|
|
43
|
-
const allActions = useActions(graph, node?.id);
|
|
44
|
-
const actions = useMemo(() => {
|
|
45
|
-
return allActions.filter((a) =>
|
|
46
|
-
['list-item', 'list-item-primary', 'heading-list-item'].includes(a.properties.disposition),
|
|
47
|
-
);
|
|
48
|
-
}, [allActions]);
|
|
49
|
-
|
|
50
|
-
// Check if current active item is a top-level workspace/collection child.
|
|
51
|
-
const isTopLevelItem = useMemo(() => {
|
|
52
|
-
if (!state.active) {
|
|
53
|
-
return false;
|
|
54
|
-
}
|
|
55
|
-
return isWorkspaceOrCollectionChild(graph, state.active);
|
|
56
|
-
}, [graph, state.active]);
|
|
57
|
-
|
|
58
|
-
const handleClick = useCallback(async () => {
|
|
59
|
-
if (state.active) {
|
|
60
|
-
// If history is empty and this is a top-level item, go to home.
|
|
61
|
-
if (state.history.length === 0 && isTopLevelItem) {
|
|
62
|
-
await invokePromise(Common.LayoutOperation.SwitchWorkspace, { subject: Node.RootId });
|
|
63
|
-
} else {
|
|
64
|
-
// Otherwise, close (which will pop from history or clear active).
|
|
65
|
-
await invokePromise(Common.LayoutOperation.Close, { subject: [state.active] });
|
|
66
|
-
}
|
|
67
|
-
} else {
|
|
68
|
-
await invokePromise(Common.LayoutOperation.SwitchWorkspace, { subject: Node.RootId });
|
|
69
|
-
}
|
|
70
|
-
}, [invokePromise, state.active, state.history.length, isTopLevelItem]);
|
|
71
|
-
|
|
72
|
-
// Wrap the menu trigger with Popover.Anchor when the popoverAnchorId matches.
|
|
73
|
-
const AnchorRoot = node && state.popoverAnchorId === `dxos.org/ui/${meta.id}/${node.id}` ? Popover.Anchor : Fragment;
|
|
74
|
-
|
|
75
|
-
if (!node) {
|
|
76
|
-
return null;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return (
|
|
80
|
-
<Toolbar.Root role='banner' classNames={mx('grid grid-cols-[var(--rail-size)_1fr_var(--rail-size)]', classNames)}>
|
|
81
|
-
{node.id !== Node.RootId ? (
|
|
82
|
-
<IconButton
|
|
83
|
-
iconOnly
|
|
84
|
-
variant='ghost'
|
|
85
|
-
icon='ph--caret-left--regular'
|
|
86
|
-
label={t('back label')}
|
|
87
|
-
onClick={handleClick}
|
|
88
|
-
/>
|
|
89
|
-
) : (
|
|
90
|
-
<div />
|
|
91
|
-
)}
|
|
92
|
-
<h1 className={'grow text-center truncate font-medium'}>{label}</h1>
|
|
93
|
-
{actions.length > 0 ? (
|
|
94
|
-
<AnchorRoot>
|
|
95
|
-
<MenuProvider onAction={runAction}>
|
|
96
|
-
<DropdownMenu.Root items={actions} caller={meta.id}>
|
|
97
|
-
<DropdownMenu.Trigger asChild>
|
|
98
|
-
<IconButton
|
|
99
|
-
iconOnly
|
|
100
|
-
variant='ghost'
|
|
101
|
-
icon='ph--dots-three-vertical--regular'
|
|
102
|
-
label={t('actions menu label')}
|
|
103
|
-
/>
|
|
104
|
-
</DropdownMenu.Trigger>
|
|
105
|
-
</DropdownMenu.Root>
|
|
106
|
-
</MenuProvider>
|
|
107
|
-
</AnchorRoot>
|
|
108
|
-
) : (
|
|
109
|
-
<span />
|
|
110
|
-
)}
|
|
111
|
-
</Toolbar.Root>
|
|
112
|
-
);
|
|
113
|
-
};
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2025 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import React, { useCallback, useEffect, useRef } from 'react';
|
|
6
|
-
|
|
7
|
-
import { Common } from '@dxos/app-framework';
|
|
8
|
-
import { useAppGraph, useOperationInvoker } from '@dxos/app-framework/react';
|
|
9
|
-
import { type Node, useConnections } from '@dxos/plugin-graph';
|
|
10
|
-
import { Avatar, Icon, Toolbar, toLocalizedString, useTranslation } from '@dxos/react-ui';
|
|
11
|
-
import { Card, Layout, Mosaic, type StackTileComponent } from '@dxos/react-ui-mosaic';
|
|
12
|
-
import { SearchList, useSearchListItem, useSearchListResults } from '@dxos/react-ui-searchlist';
|
|
13
|
-
import { mx } from '@dxos/ui-theme';
|
|
14
|
-
|
|
15
|
-
import { meta } from '../../meta';
|
|
16
|
-
import { useLoadDescendents } from '../hooks';
|
|
17
|
-
|
|
18
|
-
export type WorkspaceProps = {
|
|
19
|
-
id: string;
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
*
|
|
24
|
-
*/
|
|
25
|
-
// TODO(burdon): Rename or motivate name in comment.
|
|
26
|
-
export const Workspace = ({ id }: WorkspaceProps) => {
|
|
27
|
-
const { t } = useTranslation(meta.id);
|
|
28
|
-
const { graph } = useAppGraph();
|
|
29
|
-
|
|
30
|
-
// Expand the workspace node to load its children.
|
|
31
|
-
useLoadDescendents(id);
|
|
32
|
-
|
|
33
|
-
// Get direct children of the workspace node.
|
|
34
|
-
const children = useConnections(graph, id, 'outbound');
|
|
35
|
-
|
|
36
|
-
const { results, handleSearch } = useSearchListResults({
|
|
37
|
-
items: children,
|
|
38
|
-
extract: (child) => toLocalizedString(child.properties.label, t),
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
return (
|
|
42
|
-
<Layout.Main toolbar>
|
|
43
|
-
<SearchList.Root onSearch={handleSearch}>
|
|
44
|
-
<Toolbar.Root>
|
|
45
|
-
<SearchList.Input placeholder={t('search placeholder')} autoFocus />
|
|
46
|
-
</Toolbar.Root>
|
|
47
|
-
<SearchList.Content>
|
|
48
|
-
<Mosaic.Container asChild>
|
|
49
|
-
<Mosaic.Viewport padding>
|
|
50
|
-
<Mosaic.Stack items={results} getId={(child) => child.id} Tile={WorkspaceChildTile} />
|
|
51
|
-
</Mosaic.Viewport>
|
|
52
|
-
</Mosaic.Container>
|
|
53
|
-
</SearchList.Content>
|
|
54
|
-
</SearchList.Root>
|
|
55
|
-
</Layout.Main>
|
|
56
|
-
);
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
const WorkspaceChildTile: StackTileComponent<Node.Node> = ({ data }) => {
|
|
60
|
-
const { t } = useTranslation(meta.id);
|
|
61
|
-
const { invokeSync } = useOperationInvoker();
|
|
62
|
-
const ref = useRef<HTMLDivElement>(null);
|
|
63
|
-
const { selectedValue, registerItem, unregisterItem } = useSearchListItem();
|
|
64
|
-
const isSelected = selectedValue === data.id;
|
|
65
|
-
|
|
66
|
-
const name = toLocalizedString(data.properties.label, t);
|
|
67
|
-
|
|
68
|
-
const handleSelect = useCallback(
|
|
69
|
-
() => invokeSync(Common.LayoutOperation.Open, { subject: [data.id] }),
|
|
70
|
-
[invokeSync, data.id],
|
|
71
|
-
);
|
|
72
|
-
|
|
73
|
-
// Register this item with the search context.
|
|
74
|
-
useEffect(() => {
|
|
75
|
-
if (ref.current) {
|
|
76
|
-
registerItem(data.id, ref.current, handleSelect);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return () => unregisterItem(data.id);
|
|
80
|
-
}, [data.id, handleSelect, registerItem, unregisterItem]);
|
|
81
|
-
|
|
82
|
-
// Scroll into view when selected.
|
|
83
|
-
useEffect(() => {
|
|
84
|
-
if (isSelected && ref.current) {
|
|
85
|
-
ref.current.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
|
|
86
|
-
}
|
|
87
|
-
}, [isSelected]);
|
|
88
|
-
|
|
89
|
-
return (
|
|
90
|
-
<Card.Root
|
|
91
|
-
ref={ref}
|
|
92
|
-
role='button'
|
|
93
|
-
fullWidth
|
|
94
|
-
tabIndex={-1} // TODO(burdon): Use Mosaic.Focus.
|
|
95
|
-
data-selected={isSelected}
|
|
96
|
-
classNames={mx('dx-focus-ring', isSelected && 'bg-hoverOverlay')}
|
|
97
|
-
onClick={handleSelect}
|
|
98
|
-
>
|
|
99
|
-
<Card.Toolbar density='coarse'>
|
|
100
|
-
<Avatar.Root>
|
|
101
|
-
<Avatar.Content
|
|
102
|
-
hue={data.properties.hue}
|
|
103
|
-
icon={data.properties.icon}
|
|
104
|
-
hueVariant='transparent'
|
|
105
|
-
variant='square'
|
|
106
|
-
size={12}
|
|
107
|
-
fallback={name}
|
|
108
|
-
/>
|
|
109
|
-
<Avatar.Label>{name}</Avatar.Label>
|
|
110
|
-
<Icon icon='ph--caret-right--regular' />
|
|
111
|
-
</Avatar.Root>
|
|
112
|
-
</Card.Toolbar>
|
|
113
|
-
</Card.Root>
|
|
114
|
-
);
|
|
115
|
-
};
|