@dxos/plugin-deck 0.8.2-main.f11618f → 0.8.2-main.fbd8ed0
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-VYZ4IWI3.mjs → app-graph-builder-R7COZ4A6.mjs} +16 -15
- package/dist/lib/browser/app-graph-builder-R7COZ4A6.mjs.map +7 -0
- package/dist/lib/browser/{check-app-scheme-O7JPE4TM.mjs → check-app-scheme-7AXGR6UT.mjs} +2 -2
- package/dist/lib/browser/check-app-scheme-7AXGR6UT.mjs.map +7 -0
- package/dist/lib/browser/chunk-3O2UZVBA.mjs +121 -0
- package/dist/lib/browser/chunk-3O2UZVBA.mjs.map +7 -0
- package/dist/lib/browser/chunk-JAYQ5BTF.mjs +157 -0
- package/dist/lib/browser/chunk-JAYQ5BTF.mjs.map +7 -0
- package/dist/lib/browser/{chunk-RDFJGGGX.mjs → chunk-KIGMELV2.mjs} +186 -201
- package/dist/lib/browser/chunk-KIGMELV2.mjs.map +7 -0
- package/dist/lib/browser/{state-Z6UY2Z3M.mjs → chunk-OF5RIATN.mjs} +6 -4
- package/dist/lib/browser/chunk-OF5RIATN.mjs.map +7 -0
- package/dist/lib/browser/chunk-TRFYUEBA.mjs +145 -0
- package/dist/lib/browser/chunk-TRFYUEBA.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +4 -5
- package/dist/lib/browser/index.mjs.map +1 -1
- package/dist/lib/browser/{intent-resolver-JKWXWUV6.mjs → intent-resolver-MAKOS57L.mjs} +78 -62
- package/dist/lib/browser/intent-resolver-MAKOS57L.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/{react-root-S6ZAKNZA.mjs → react-root-DGQVIHXP.mjs} +6 -6
- package/dist/lib/browser/{react-surface-I7WZBOGM.mjs → react-surface-PXBXIOPU.mjs} +6 -6
- package/dist/lib/browser/{settings-6NU7CF2B.mjs → settings-UBWJF7J7.mjs} +4 -4
- package/dist/lib/browser/{settings-6NU7CF2B.mjs.map → settings-UBWJF7J7.mjs.map} +3 -3
- package/dist/lib/browser/state-4WFB4SDO.mjs +10 -0
- package/dist/lib/browser/state-4WFB4SDO.mjs.map +7 -0
- package/dist/lib/browser/{tools-VDVQTJMD.mjs → tools-IVPIPTVA.mjs} +7 -7
- package/dist/lib/browser/tools-IVPIPTVA.mjs.map +7 -0
- package/dist/lib/browser/types.mjs +1 -1
- package/dist/lib/browser/{url-handler-3CARFXQK.mjs → url-handler-JSYGSVSB.mjs} +4 -4
- package/dist/lib/browser/url-handler-JSYGSVSB.mjs.map +7 -0
- package/dist/types/src/capabilities/app-graph-builder.d.ts +2 -179
- package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
- package/dist/types/src/capabilities/check-app-scheme.d.ts +2 -2
- package/dist/types/src/capabilities/check-app-scheme.d.ts.map +1 -1
- package/dist/types/src/capabilities/index.d.ts +5 -180
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/intent-resolver.d.ts +2 -2
- package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
- package/dist/types/src/capabilities/state.d.ts +2 -2
- package/dist/types/src/capabilities/state.d.ts.map +1 -1
- package/dist/types/src/capabilities/tools.d.ts.map +1 -1
- package/dist/types/src/capabilities/url-handler.d.ts +2 -2
- package/dist/types/src/capabilities/url-handler.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/Banner.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/ContentEmpty.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/DeckLayout.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/Popover.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/StatusBar.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/Toast.d.ts.map +1 -1
- package/dist/types/src/components/DeckSettings/DeckSettings.d.ts.map +1 -1
- package/dist/types/src/components/Plank/Plank.d.ts +18 -5
- package/dist/types/src/components/Plank/Plank.d.ts.map +1 -1
- package/dist/types/src/components/Plank/Plank.stories.d.ts +3 -3
- package/dist/types/src/components/Plank/Plank.stories.d.ts.map +1 -1
- package/dist/types/src/components/Plank/PlankControls.d.ts +1 -0
- package/dist/types/src/components/Plank/PlankControls.d.ts.map +1 -1
- package/dist/types/src/components/Plank/PlankError.d.ts.map +1 -1
- package/dist/types/src/components/Plank/PlankHeading.d.ts.map +1 -1
- package/dist/types/src/components/Sidebar/ComplementarySidebar.d.ts.map +1 -1
- package/dist/types/src/components/Sidebar/Sidebar.d.ts.map +1 -1
- package/dist/types/src/components/Sidebar/SidebarButton.d.ts +2 -1
- package/dist/types/src/components/Sidebar/SidebarButton.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +5 -1
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useBreakpoints.d.ts.map +1 -0
- package/dist/types/src/hooks/useCompanions.d.ts.map +1 -0
- package/dist/types/src/hooks/useDeckCompanions.d.ts +13 -0
- package/dist/types/src/hooks/useDeckCompanions.d.ts.map +1 -0
- package/dist/types/src/hooks/useHoistStatusbar.d.ts.map +1 -0
- package/dist/types/src/hooks/useNodeActionExpander.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/layout.d.ts.map +1 -1
- package/dist/types/src/types.d.ts +104 -104
- package/dist/types/src/types.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +1 -4
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/src/util/layoutAppliesTopbar.d.ts.map +1 -1
- package/dist/types/src/util/overscroll.d.ts.map +1 -1
- package/dist/types/src/util/set-active.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +35 -29
- package/src/capabilities/app-graph-builder.ts +120 -92
- package/src/capabilities/check-app-scheme.ts +3 -5
- package/src/capabilities/index.ts +1 -0
- package/src/capabilities/intent-resolver.ts +94 -76
- package/src/capabilities/settings.ts +2 -2
- package/src/capabilities/state.ts +4 -2
- package/src/capabilities/tools.ts +4 -3
- package/src/capabilities/url-handler.ts +4 -4
- package/src/components/DeckLayout/ContentEmpty.tsx +3 -2
- package/src/components/DeckLayout/DeckLayout.tsx +12 -10
- package/src/components/Plank/Plank.stories.tsx +20 -8
- package/src/components/Plank/Plank.tsx +100 -67
- package/src/components/Plank/PlankControls.tsx +15 -25
- package/src/components/Plank/PlankHeading.tsx +19 -9
- package/src/components/Sidebar/ComplementarySidebar.tsx +4 -35
- package/src/components/Sidebar/Sidebar.tsx +2 -1
- package/src/components/Sidebar/SidebarButton.tsx +30 -7
- package/src/components/fragments.ts +1 -1
- package/src/hooks/index.ts +5 -1
- package/src/{util → hooks}/useCompanions.ts +3 -3
- package/src/hooks/useDeckCompanions.ts +33 -0
- package/src/hooks/useNodeActionExpander.ts +3 -8
- package/src/index.ts +1 -1
- package/src/types.ts +72 -71
- package/src/util/index.ts +1 -4
- package/dist/lib/browser/app-graph-builder-VYZ4IWI3.mjs.map +0 -7
- package/dist/lib/browser/check-app-scheme-O7JPE4TM.mjs.map +0 -7
- package/dist/lib/browser/chunk-6HJZL3WT.mjs +0 -118
- package/dist/lib/browser/chunk-6HJZL3WT.mjs.map +0 -7
- package/dist/lib/browser/chunk-FLOVGNYB.mjs +0 -81
- package/dist/lib/browser/chunk-FLOVGNYB.mjs.map +0 -7
- package/dist/lib/browser/chunk-RBJ6DLAC.mjs +0 -24
- package/dist/lib/browser/chunk-RBJ6DLAC.mjs.map +0 -7
- package/dist/lib/browser/chunk-RDFJGGGX.mjs.map +0 -7
- package/dist/lib/browser/chunk-ZMJMCN7O.mjs +0 -157
- package/dist/lib/browser/chunk-ZMJMCN7O.mjs.map +0 -7
- package/dist/lib/browser/intent-resolver-JKWXWUV6.mjs.map +0 -7
- package/dist/lib/browser/state-Z6UY2Z3M.mjs.map +0 -7
- package/dist/lib/browser/tools-VDVQTJMD.mjs.map +0 -7
- package/dist/lib/browser/url-handler-3CARFXQK.mjs.map +0 -7
- package/dist/types/src/util/useBreakpoints.d.ts.map +0 -1
- package/dist/types/src/util/useCompanions.d.ts.map +0 -1
- package/dist/types/src/util/useHoistStatusbar.d.ts.map +0 -1
- /package/dist/lib/browser/{react-root-S6ZAKNZA.mjs.map → react-root-DGQVIHXP.mjs.map} +0 -0
- /package/dist/lib/browser/{react-surface-I7WZBOGM.mjs.map → react-surface-PXBXIOPU.mjs.map} +0 -0
- /package/dist/types/src/{util → hooks}/useBreakpoints.d.ts +0 -0
- /package/dist/types/src/{util → hooks}/useCompanions.d.ts +0 -0
- /package/dist/types/src/{util → hooks}/useHoistStatusbar.d.ts +0 -0
- /package/src/{util → hooks}/useBreakpoints.ts +0 -0
- /package/src/{util → hooks}/useHoistStatusbar.ts +0 -0
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import { Schema } from 'effect';
|
|
6
|
+
|
|
5
7
|
import {
|
|
6
8
|
contributes,
|
|
7
9
|
createIntent,
|
|
@@ -10,7 +12,6 @@ import {
|
|
|
10
12
|
type PromiseIntentDispatcher,
|
|
11
13
|
} from '@dxos/app-framework';
|
|
12
14
|
import { defineTool, ToolResult } from '@dxos/artifact';
|
|
13
|
-
import { S } from '@dxos/echo-schema';
|
|
14
15
|
import { invariant } from '@dxos/invariant';
|
|
15
16
|
|
|
16
17
|
import { meta } from '../meta';
|
|
@@ -35,8 +36,8 @@ export default () =>
|
|
|
35
36
|
`,
|
|
36
37
|
caption: 'Showing item...',
|
|
37
38
|
// TODO(wittjosiah): Refactor Layout/Navigation/Deck actions so that they can be used directly.
|
|
38
|
-
schema:
|
|
39
|
-
id:
|
|
39
|
+
schema: Schema.Struct({
|
|
40
|
+
id: Schema.String.annotations({
|
|
40
41
|
description: 'The ID of the item to show.',
|
|
41
42
|
}),
|
|
42
43
|
}),
|
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { Capabilities, contributes, createIntent, LayoutAction, type
|
|
5
|
+
import { Capabilities, contributes, createIntent, LayoutAction, type PluginContext } from '@dxos/app-framework';
|
|
6
6
|
import { scheduledEffect } from '@dxos/echo-signals/core';
|
|
7
7
|
|
|
8
8
|
import { DeckCapabilities } from './capabilities';
|
|
9
9
|
import { defaultDeck } from '../types';
|
|
10
10
|
|
|
11
11
|
// TODO(wittjosiah): Cleanup the url handling. May justify introducing routing capabilities.
|
|
12
|
-
export default async (context:
|
|
13
|
-
const { dispatchPromise: dispatch } = context.
|
|
14
|
-
const state = context.
|
|
12
|
+
export default async (context: PluginContext) => {
|
|
13
|
+
const { dispatchPromise: dispatch } = context.getCapability(Capabilities.IntentDispatcher);
|
|
14
|
+
const state = context.getCapability(DeckCapabilities.MutableDeckState);
|
|
15
15
|
|
|
16
16
|
const handleNavigation = async () => {
|
|
17
17
|
const pathname = window.location.pathname;
|
|
@@ -7,8 +7,9 @@ import React from 'react';
|
|
|
7
7
|
import { Surface, useCapability } from '@dxos/app-framework';
|
|
8
8
|
|
|
9
9
|
import { DeckCapabilities } from '../../capabilities';
|
|
10
|
+
import { useBreakpoints } from '../../hooks';
|
|
10
11
|
import { getMode } from '../../types';
|
|
11
|
-
import { layoutAppliesTopbar
|
|
12
|
+
import { layoutAppliesTopbar } from '../../util';
|
|
12
13
|
import { ToggleSidebarButton } from '../Sidebar';
|
|
13
14
|
import { fixedSidebarToggleStyles } from '../fragments';
|
|
14
15
|
|
|
@@ -20,7 +21,7 @@ export const ContentEmpty = () => {
|
|
|
20
21
|
return (
|
|
21
22
|
<div
|
|
22
23
|
role='none'
|
|
23
|
-
className='grid place-items-center p-8 relative bg-
|
|
24
|
+
className='grid place-items-center p-8 relative bg-deckSurface'
|
|
24
25
|
data-testid='layoutPlugin.firstRunMessage'
|
|
25
26
|
>
|
|
26
27
|
<Surface role='keyshortcuts' />
|
|
@@ -26,9 +26,10 @@ import { StatusBar } from './StatusBar';
|
|
|
26
26
|
import { Toast } from './Toast';
|
|
27
27
|
import { Topbar } from './Topbar';
|
|
28
28
|
import { DeckCapabilities } from '../../capabilities';
|
|
29
|
+
import { useBreakpoints, useHoistStatusbar } from '../../hooks';
|
|
29
30
|
import { DECK_PLUGIN } from '../../meta';
|
|
30
31
|
import { type DeckSettingsProps, getMode } from '../../types';
|
|
31
|
-
import { calculateOverscroll, layoutAppliesTopbar
|
|
32
|
+
import { calculateOverscroll, layoutAppliesTopbar } from '../../util';
|
|
32
33
|
import { Plank } from '../Plank';
|
|
33
34
|
import { ComplementarySidebar, Sidebar, ToggleComplementarySidebarButton, ToggleSidebarButton } from '../Sidebar';
|
|
34
35
|
import { fixedComplementarySidebarToggleStyles, fixedSidebarToggleStyles } from '../fragments';
|
|
@@ -38,7 +39,7 @@ export type DeckLayoutProps = {
|
|
|
38
39
|
};
|
|
39
40
|
|
|
40
41
|
const PlankSeparator = ({ order }: { order: number }) =>
|
|
41
|
-
order > 0 ? <span role='separator' className='row-span-2 bg-
|
|
42
|
+
order > 0 ? <span role='separator' className='row-span-2 bg-deckSurface is-4' style={{ gridColumn: order }} /> : null;
|
|
42
43
|
|
|
43
44
|
export const DeckLayout = ({ onDismissToast }: DeckLayoutProps) => {
|
|
44
45
|
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
@@ -59,7 +60,7 @@ export const DeckLayout = ({ onDismissToast }: DeckLayoutProps) => {
|
|
|
59
60
|
useEffect(() => {
|
|
60
61
|
// NOTE: Not `useAttended` so that the layout component is not re-rendered when the attended list changes.
|
|
61
62
|
const attended = untracked(() => {
|
|
62
|
-
const attention = pluginManager.context.
|
|
63
|
+
const attention = pluginManager.context.getCapability(AttentionCapabilities.Attention);
|
|
63
64
|
return attention.current;
|
|
64
65
|
});
|
|
65
66
|
const firstId = solo ?? active[0];
|
|
@@ -78,7 +79,7 @@ export const DeckLayout = ({ onDismissToast }: DeckLayoutProps) => {
|
|
|
78
79
|
if (!isNotMobile && getMode(deck) === 'deck') {
|
|
79
80
|
// NOTE: Not `useAttended` so that the layout component is not re-rendered when the attended list changes.
|
|
80
81
|
const attended = untracked(() => {
|
|
81
|
-
const attention = pluginManager.context.
|
|
82
|
+
const attention = pluginManager.context.getCapability(AttentionCapabilities.Attention);
|
|
82
83
|
return attention.current;
|
|
83
84
|
});
|
|
84
85
|
|
|
@@ -91,14 +92,15 @@ export const DeckLayout = ({ onDismissToast }: DeckLayoutProps) => {
|
|
|
91
92
|
}
|
|
92
93
|
}, [isNotMobile, deck, dispatch]);
|
|
93
94
|
|
|
94
|
-
//
|
|
95
|
+
// When deck is disabled in settings, set to solo mode if the current layout mode is deck.
|
|
96
|
+
// TODO(thure): Applying this as an effect should be avoided over emitting the intent only when the setting changes.
|
|
95
97
|
useEffect(() => {
|
|
96
|
-
if (!settings.enableDeck) {
|
|
98
|
+
if (!settings.enableDeck && layoutMode === 'deck') {
|
|
97
99
|
void dispatch(
|
|
98
100
|
createIntent(LayoutAction.SetLayoutMode, { part: 'mode', subject: active[0], options: { mode: 'solo' } }),
|
|
99
101
|
);
|
|
100
102
|
}
|
|
101
|
-
}, [settings.enableDeck, dispatch, active]);
|
|
103
|
+
}, [settings.enableDeck, dispatch, active, layoutMode]);
|
|
102
104
|
|
|
103
105
|
/**
|
|
104
106
|
* Clear scroll restoration state if the window is resized
|
|
@@ -190,8 +192,8 @@ export const DeckLayout = ({ onDismissToast }: DeckLayoutProps) => {
|
|
|
190
192
|
{!isEmpty && (
|
|
191
193
|
<Main.Content
|
|
192
194
|
bounce
|
|
193
|
-
classNames={mainPosition}
|
|
194
195
|
handlesFocus
|
|
196
|
+
classNames={mainPosition}
|
|
195
197
|
style={
|
|
196
198
|
{
|
|
197
199
|
'--dx-main-sidebarWidth':
|
|
@@ -213,7 +215,7 @@ export const DeckLayout = ({ onDismissToast }: DeckLayoutProps) => {
|
|
|
213
215
|
>
|
|
214
216
|
<div
|
|
215
217
|
role='none'
|
|
216
|
-
className={!solo ? 'relative bg-
|
|
218
|
+
className={!solo ? 'relative bg-deckSurface overflow-hidden' : 'sr-only'}
|
|
217
219
|
{...(solo && { inert: '' })}
|
|
218
220
|
>
|
|
219
221
|
{!topbar && !fullscreen && <ToggleSidebarButton classNames={fixedSidebarToggleStyles} />}
|
|
@@ -247,7 +249,7 @@ export const DeckLayout = ({ onDismissToast }: DeckLayoutProps) => {
|
|
|
247
249
|
</div>
|
|
248
250
|
<div
|
|
249
251
|
role='none'
|
|
250
|
-
className={solo ? 'relative bg-
|
|
252
|
+
className={solo ? 'relative bg-deckSurface overflow-hidden' : 'sr-only'}
|
|
251
253
|
{...(!solo && { inert: '' })}
|
|
252
254
|
>
|
|
253
255
|
{!topbar && !fullscreen && <ToggleSidebarButton classNames={fixedSidebarToggleStyles} />}
|
|
@@ -5,39 +5,51 @@
|
|
|
5
5
|
import '@dxos-theme';
|
|
6
6
|
|
|
7
7
|
import { type StoryObj, type Meta } from '@storybook/react';
|
|
8
|
+
import React from 'react';
|
|
8
9
|
|
|
9
|
-
import { IntentPlugin } from '@dxos/app-framework';
|
|
10
|
+
import { IntentPlugin, SettingsPlugin } from '@dxos/app-framework';
|
|
10
11
|
import { withPluginManager } from '@dxos/app-framework/testing';
|
|
12
|
+
import { AttentionPlugin } from '@dxos/plugin-attention';
|
|
11
13
|
import { GraphPlugin } from '@dxos/plugin-graph';
|
|
14
|
+
import { Stack } from '@dxos/react-ui-stack';
|
|
12
15
|
import { withTheme, withLayout } from '@dxos/storybook-utils';
|
|
13
16
|
|
|
14
|
-
import { Plank } from './Plank';
|
|
17
|
+
import { Plank, type PlankProps } from './Plank';
|
|
18
|
+
import DeckStateFactory from '../../capabilities/state';
|
|
15
19
|
import translations from '../../translations';
|
|
16
20
|
|
|
17
|
-
|
|
18
|
-
const meta: Meta<typeof Plank> = {
|
|
21
|
+
const meta: Meta<PlankProps> = {
|
|
19
22
|
title: 'plugins/plugin-deck/Plank',
|
|
20
23
|
component: Plank,
|
|
24
|
+
render: (args) => {
|
|
25
|
+
return (
|
|
26
|
+
<Stack orientation='horizontal'>
|
|
27
|
+
<Plank {...args} />
|
|
28
|
+
</Stack>
|
|
29
|
+
);
|
|
30
|
+
},
|
|
21
31
|
decorators: [
|
|
22
32
|
withPluginManager({
|
|
23
|
-
plugins: [IntentPlugin(), GraphPlugin()],
|
|
33
|
+
plugins: [AttentionPlugin(), SettingsPlugin(), IntentPlugin(), GraphPlugin()],
|
|
34
|
+
capabilities: () => DeckStateFactory(),
|
|
24
35
|
}),
|
|
25
36
|
withTheme,
|
|
26
|
-
withLayout({ fullscreen: true
|
|
37
|
+
withLayout({ fullscreen: true }),
|
|
27
38
|
],
|
|
28
39
|
parameters: {
|
|
29
|
-
layout: 'centered',
|
|
30
40
|
translations,
|
|
31
41
|
},
|
|
32
42
|
};
|
|
33
43
|
|
|
34
44
|
export default meta;
|
|
35
45
|
|
|
36
|
-
type Story = StoryObj<
|
|
46
|
+
type Story = StoryObj<PlankProps>;
|
|
37
47
|
|
|
48
|
+
// TODO(burdon): Need to define surface provider?
|
|
38
49
|
export const Default: Story = {
|
|
39
50
|
args: {
|
|
40
51
|
id: 'plank-1',
|
|
41
52
|
part: 'solo',
|
|
53
|
+
layoutMode: 'deck',
|
|
42
54
|
},
|
|
43
55
|
};
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import React, {
|
|
6
|
-
Fragment,
|
|
7
6
|
type KeyboardEvent,
|
|
8
7
|
type PropsWithChildren,
|
|
9
8
|
memo,
|
|
@@ -31,40 +30,117 @@ import { PlankContentError, PlankError } from './PlankError';
|
|
|
31
30
|
import { PlankHeading } from './PlankHeading';
|
|
32
31
|
import { PlankLoading } from './PlankLoading';
|
|
33
32
|
import { DeckCapabilities } from '../../capabilities';
|
|
34
|
-
import { useMainSize } from '../../hooks';
|
|
33
|
+
import { useMainSize, useCompanions } from '../../hooks';
|
|
35
34
|
import { parseEntryId } from '../../layout';
|
|
36
|
-
import { DeckAction, type LayoutMode, type
|
|
37
|
-
import { useCompanions } from '../../util';
|
|
35
|
+
import { DeckAction, type LayoutMode, type ResolvedPart, type DeckSettingsProps } from '../../types';
|
|
38
36
|
|
|
39
37
|
const UNKNOWN_ID = 'unknown_id';
|
|
40
38
|
|
|
41
|
-
export type PlankProps = {
|
|
39
|
+
export type PlankProps = Pick<PlankComponentProps, 'layoutMode' | 'part' | 'path' | 'order' | 'active' | 'settings'> & {
|
|
42
40
|
id?: string;
|
|
43
41
|
companionId?: string;
|
|
44
|
-
part: Part;
|
|
45
|
-
path?: string[];
|
|
46
|
-
order?: number;
|
|
47
|
-
active?: string[];
|
|
48
|
-
layoutMode: LayoutMode;
|
|
49
|
-
settings?: DeckSettingsProps;
|
|
50
42
|
};
|
|
51
43
|
|
|
52
|
-
|
|
44
|
+
// TODO(burdon): Factor out conditional rendering.
|
|
45
|
+
// Remove this wrapper component and render the entire set of planks in the deck with conditional visibility
|
|
46
|
+
// to obviate mounting and unmounting when switching between solo and companion mode?
|
|
47
|
+
// NOTE(thure, in reply): Whether any surface should be rendered and hidden is a performance matter — remember that
|
|
48
|
+
// article surfaces contain full experiences, so being able to unmount them will yield relatively large performance
|
|
49
|
+
// benefits. I think where we anticipate users will definitely want to quickly switch between showing and hiding entire
|
|
50
|
+
// articles, over the (again probably large) performance benefit that unmounting them would confer, we can mount and
|
|
51
|
+
// hide them, but I think that scenario in its most unambiguous form is probably rare. You could extrapolate
|
|
52
|
+
// the scenario to include all “potential” planks such as companions, which we could keep mounted and hidden, but I
|
|
53
|
+
// don’t think the resulting performance would be acceptable. I think the real issue is “perceived performance” which
|
|
54
|
+
// has mitigations that are in between mounting and un-mounting since both of those have tradeoffs; we may need one or more
|
|
55
|
+
// “partially-mounted” experiences, like loading skeletons at the simple end, or screenshots of “sleeping” planks at
|
|
56
|
+
// the advanced end.
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* A Plank is the main container for surfaces within a Deck.
|
|
60
|
+
* It may be paired with a companion plank that enables the user to select one of multiple companion surfaces.
|
|
61
|
+
*/
|
|
62
|
+
export const Plank = memo(({ id = UNKNOWN_ID, companionId, ...props }: PlankProps) => {
|
|
63
|
+
const { graph } = useAppGraph();
|
|
64
|
+
const node = useNode(graph, id);
|
|
65
|
+
const companions = useCompanions(id);
|
|
66
|
+
const currentCompanion = companions.find(({ id }) => id === companionId);
|
|
67
|
+
const hasCompanion = !!(companionId && currentCompanion);
|
|
68
|
+
|
|
69
|
+
return (
|
|
70
|
+
<PlankContainer solo={props.part === 'solo'} companion={hasCompanion}>
|
|
71
|
+
<PlankComponent
|
|
72
|
+
id={id}
|
|
73
|
+
node={node}
|
|
74
|
+
companioned={hasCompanion ? 'primary' : undefined}
|
|
75
|
+
companions={hasCompanion ? [] : companions}
|
|
76
|
+
{...props}
|
|
77
|
+
{...(props.part === 'solo' ? { part: 'solo-primary' } : {})}
|
|
78
|
+
/>
|
|
79
|
+
{hasCompanion && (
|
|
80
|
+
<PlankComponent
|
|
81
|
+
id={companionId}
|
|
82
|
+
node={currentCompanion}
|
|
83
|
+
primary={node}
|
|
84
|
+
companions={companions}
|
|
85
|
+
companioned='companion'
|
|
86
|
+
{...props}
|
|
87
|
+
{...(props.part === 'solo' ? { part: 'solo-companion' } : { order: (props.order ?? 0) + 1 })}
|
|
88
|
+
/>
|
|
89
|
+
)}
|
|
90
|
+
</PlankContainer>
|
|
91
|
+
);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const PlankContainer = ({ children, solo, companion }: PropsWithChildren<{ solo: boolean; companion: boolean }>) => {
|
|
95
|
+
const sizeAttrs = useMainSize();
|
|
96
|
+
if (!solo) {
|
|
97
|
+
return children;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// TODO(burdon): Make resizable.
|
|
101
|
+
return (
|
|
102
|
+
<div
|
|
103
|
+
role='none'
|
|
104
|
+
className={mx('absolute inset-0 grid', companion && 'grid-cols-[1fr_1fr]', railGridHorizontal, mainIntrinsicSize)}
|
|
105
|
+
{...sizeAttrs}
|
|
106
|
+
>
|
|
107
|
+
{children}
|
|
108
|
+
</div>
|
|
109
|
+
);
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
type PlankComponentProps = {
|
|
113
|
+
layoutMode: LayoutMode;
|
|
53
114
|
id: string;
|
|
54
115
|
part: ResolvedPart;
|
|
55
|
-
|
|
116
|
+
path?: string[];
|
|
117
|
+
order?: number;
|
|
118
|
+
active?: string[];
|
|
119
|
+
// TODO(burdon): Change to role?
|
|
56
120
|
companioned?: 'primary' | 'companion';
|
|
121
|
+
node?: Node;
|
|
57
122
|
primary?: Node;
|
|
58
123
|
companions?: Node[];
|
|
124
|
+
settings?: DeckSettingsProps;
|
|
59
125
|
};
|
|
60
126
|
|
|
61
|
-
const
|
|
62
|
-
({
|
|
127
|
+
const PlankComponent = memo(
|
|
128
|
+
({
|
|
129
|
+
layoutMode,
|
|
130
|
+
id,
|
|
131
|
+
part,
|
|
132
|
+
path,
|
|
133
|
+
order,
|
|
134
|
+
active,
|
|
135
|
+
companioned,
|
|
136
|
+
node,
|
|
137
|
+
primary,
|
|
138
|
+
companions,
|
|
139
|
+
settings,
|
|
140
|
+
}: PlankComponentProps) => {
|
|
63
141
|
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
64
142
|
const { deck, popoverAnchorId, scrollIntoView } = useCapability(DeckCapabilities.DeckState);
|
|
65
|
-
const rootElement = useRef<HTMLDivElement | null>(null);
|
|
66
143
|
const canResize = layoutMode === 'deck';
|
|
67
|
-
const Root = part.startsWith('solo') ? 'article' : StackItem.Root;
|
|
68
144
|
|
|
69
145
|
const attendableAttrs = useAttendableAttributes(primary?.id ?? id);
|
|
70
146
|
const index = active ? active.findIndex((entryId) => entryId === id) : 0;
|
|
@@ -72,10 +148,13 @@ const PlankImpl = memo(
|
|
|
72
148
|
const canIncrementStart = active && index !== undefined && index > 0 && length !== undefined && length > 1;
|
|
73
149
|
const canIncrementEnd = active && index !== undefined && index < length - 1 && length !== undefined;
|
|
74
150
|
|
|
151
|
+
const rootElement = useRef<HTMLDivElement | null>(null);
|
|
152
|
+
|
|
75
153
|
const { variant } = parseEntryId(id);
|
|
76
154
|
const sizeKey = `${id.split('+')[0]}${variant ? `${ATTENDABLE_PATH_SEPARATOR}${variant}` : ''}`;
|
|
77
155
|
const size = deck.plankSizing[sizeKey] as number | undefined;
|
|
78
|
-
|
|
156
|
+
|
|
157
|
+
const handleSizeChange = useCallback(
|
|
79
158
|
debounce((nextSize: number) => {
|
|
80
159
|
return dispatch(createIntent(DeckAction.UpdatePlankSize, { id: sizeKey, size: nextSize }));
|
|
81
160
|
}, 200),
|
|
@@ -122,6 +201,7 @@ const PlankImpl = memo(
|
|
|
122
201
|
// TODO(wittjosiah): Change prop to accept a component.
|
|
123
202
|
const placeholder = useMemo(() => <PlankLoading />, []);
|
|
124
203
|
|
|
204
|
+
const Root = part.startsWith('solo') ? 'article' : StackItem.Root;
|
|
125
205
|
const className = mx(
|
|
126
206
|
'attention-surface relative',
|
|
127
207
|
isSolo && mainIntrinsicSize,
|
|
@@ -131,8 +211,6 @@ const PlankImpl = memo(
|
|
|
131
211
|
part === 'deck' && (companioned === 'companion' ? '!border-separator border-ie' : '!border-separator border-li'),
|
|
132
212
|
part.startsWith('solo-') && 'row-span-2 grid-rows-subgrid min-is-0',
|
|
133
213
|
part === 'solo-companion' && '!border-separator border-is',
|
|
134
|
-
layoutMode === 'solo--fullscreen' &&
|
|
135
|
-
'!transition-[margin-block-start,inline-size] -mbs-[--rail-action] has-[[data-plank-heading]:hover]:mbs-0',
|
|
136
214
|
);
|
|
137
215
|
|
|
138
216
|
return (
|
|
@@ -145,7 +223,7 @@ const PlankImpl = memo(
|
|
|
145
223
|
: {
|
|
146
224
|
item: { id },
|
|
147
225
|
size,
|
|
148
|
-
onSizeChange:
|
|
226
|
+
onSizeChange: handleSizeChange,
|
|
149
227
|
classNames: className,
|
|
150
228
|
order,
|
|
151
229
|
role: 'article',
|
|
@@ -180,54 +258,9 @@ const PlankImpl = memo(
|
|
|
180
258
|
) : (
|
|
181
259
|
<PlankError id={id} part={part} />
|
|
182
260
|
)}
|
|
261
|
+
|
|
183
262
|
{canResize && <StackItem.ResizeHandle />}
|
|
184
263
|
</Root>
|
|
185
264
|
);
|
|
186
265
|
},
|
|
187
266
|
);
|
|
188
|
-
|
|
189
|
-
const SplitFrame = ({ children }: PropsWithChildren<{}>) => {
|
|
190
|
-
const sizeAttrs = useMainSize();
|
|
191
|
-
return (
|
|
192
|
-
<div
|
|
193
|
-
role='none'
|
|
194
|
-
className={mx('grid grid-cols-[1fr_1fr] absolute inset-0', railGridHorizontal, mainIntrinsicSize)}
|
|
195
|
-
{...sizeAttrs}
|
|
196
|
-
>
|
|
197
|
-
{children}
|
|
198
|
-
</div>
|
|
199
|
-
);
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
export const Plank = ({ id = UNKNOWN_ID, ...props }: PlankProps) => {
|
|
203
|
-
const { graph } = useAppGraph();
|
|
204
|
-
const node = useNode(graph, id);
|
|
205
|
-
const companions = useCompanions(id);
|
|
206
|
-
const currentCompanion = companions.find(({ id }) => id === props.companionId);
|
|
207
|
-
|
|
208
|
-
if (props.companionId) {
|
|
209
|
-
const Root = props.part === 'solo' ? SplitFrame : Fragment;
|
|
210
|
-
return (
|
|
211
|
-
<Root>
|
|
212
|
-
<PlankImpl
|
|
213
|
-
id={id}
|
|
214
|
-
node={node}
|
|
215
|
-
companioned='primary'
|
|
216
|
-
{...props}
|
|
217
|
-
{...(props.part === 'solo' ? { part: 'solo-primary' } : {})}
|
|
218
|
-
/>
|
|
219
|
-
<PlankImpl
|
|
220
|
-
id={props.companionId}
|
|
221
|
-
node={currentCompanion}
|
|
222
|
-
companioned='companion'
|
|
223
|
-
primary={node}
|
|
224
|
-
companions={companions}
|
|
225
|
-
{...props}
|
|
226
|
-
{...(props.part === 'solo' ? { part: 'solo-companion' } : { order: props.order! + 1 })}
|
|
227
|
-
/>
|
|
228
|
-
</Root>
|
|
229
|
-
);
|
|
230
|
-
} else {
|
|
231
|
-
return <PlankImpl id={id} node={node} companions={companions} {...props} />;
|
|
232
|
-
}
|
|
233
|
-
};
|
|
@@ -6,15 +6,7 @@ import React, { forwardRef, useCallback } from 'react';
|
|
|
6
6
|
|
|
7
7
|
import { createIntent, useIntentDispatcher } from '@dxos/app-framework';
|
|
8
8
|
import { invariant } from '@dxos/invariant';
|
|
9
|
-
import {
|
|
10
|
-
Button,
|
|
11
|
-
ButtonGroup,
|
|
12
|
-
type ButtonGroupProps,
|
|
13
|
-
type ButtonProps,
|
|
14
|
-
Icon,
|
|
15
|
-
Tooltip,
|
|
16
|
-
useTranslation,
|
|
17
|
-
} from '@dxos/react-ui';
|
|
9
|
+
import { ButtonGroup, type ButtonGroupProps, type ButtonProps, IconButton, useTranslation } from '@dxos/react-ui';
|
|
18
10
|
|
|
19
11
|
import { DECK_PLUGIN } from '../../meta';
|
|
20
12
|
import { DeckAction, type LayoutMode } from '../../types';
|
|
@@ -26,6 +18,7 @@ export type PlankCapabilities = {
|
|
|
26
18
|
incrementEnd?: boolean;
|
|
27
19
|
deck?: boolean;
|
|
28
20
|
solo?: boolean;
|
|
21
|
+
fullscreen?: boolean;
|
|
29
22
|
companion?: boolean;
|
|
30
23
|
};
|
|
31
24
|
|
|
@@ -39,22 +32,10 @@ export type PlankControlsProps = Omit<ButtonGroupProps, 'onClick'> & {
|
|
|
39
32
|
};
|
|
40
33
|
|
|
41
34
|
const PlankControl = ({ icon, label, ...props }: Omit<ButtonProps, 'children'> & { label: string; icon: string }) => {
|
|
42
|
-
return
|
|
43
|
-
<Tooltip.Root>
|
|
44
|
-
<Tooltip.Trigger asChild>
|
|
45
|
-
<Button variant='ghost' {...props}>
|
|
46
|
-
<span className='sr-only'>{label}</span>
|
|
47
|
-
<Icon icon={icon} size={5} />
|
|
48
|
-
</Button>
|
|
49
|
-
</Tooltip.Trigger>
|
|
50
|
-
<Tooltip.Portal>
|
|
51
|
-
<Tooltip.Content side='bottom'>{label}</Tooltip.Content>
|
|
52
|
-
</Tooltip.Portal>
|
|
53
|
-
</Tooltip.Root>
|
|
54
|
-
);
|
|
35
|
+
return <IconButton iconOnly label={label} icon={icon} size={5} variant='ghost' tooltipSide='bottom' {...props} />;
|
|
55
36
|
};
|
|
56
37
|
|
|
57
|
-
const plankControlSpacing = 'pli-2
|
|
38
|
+
const plankControlSpacing = 'pli-2';
|
|
58
39
|
|
|
59
40
|
type PlankComplimentControlsProps = {
|
|
60
41
|
primary?: string;
|
|
@@ -97,8 +78,8 @@ export const PlankControls = forwardRef<HTMLDivElement, PlankControlsProps>(
|
|
|
97
78
|
const layoutIsAnySolo = !!layoutMode?.startsWith('solo');
|
|
98
79
|
|
|
99
80
|
return (
|
|
100
|
-
<ButtonGroup {...props} classNames={['app-no-drag', classNames]} ref={forwardedRef}>
|
|
101
|
-
{capabilities.deck
|
|
81
|
+
<ButtonGroup {...props} classNames={['app-no-drag !opacity-100', classNames]} ref={forwardedRef}>
|
|
82
|
+
{capabilities.deck ? (
|
|
102
83
|
<>
|
|
103
84
|
{capabilities.solo && (
|
|
104
85
|
<>
|
|
@@ -150,6 +131,15 @@ export const PlankControls = forwardRef<HTMLDivElement, PlankControlsProps>(
|
|
|
150
131
|
</>
|
|
151
132
|
)}
|
|
152
133
|
</>
|
|
134
|
+
) : (
|
|
135
|
+
capabilities.fullscreen && (
|
|
136
|
+
<PlankControl
|
|
137
|
+
label={t(layoutMode === 'solo--fullscreen' ? 'exit fullscreen label' : 'show fullscreen plank label')}
|
|
138
|
+
classNames={buttonClassNames}
|
|
139
|
+
icon={layoutMode === 'solo--fullscreen' ? 'ph--corners-in--regular' : 'ph--corners-out--regular'}
|
|
140
|
+
onClick={() => onClick?.('solo--fullscreen')}
|
|
141
|
+
/>
|
|
142
|
+
)
|
|
153
143
|
)}
|
|
154
144
|
|
|
155
145
|
{close && !layoutIsAnySolo && (
|
|
@@ -9,12 +9,13 @@ import { type Node } from '@dxos/plugin-graph';
|
|
|
9
9
|
import { Icon, IconButton, Popover, toLocalizedString, useTranslation } from '@dxos/react-ui';
|
|
10
10
|
import { StackItem, type StackItemSigilAction } from '@dxos/react-ui-stack';
|
|
11
11
|
import { TextTooltip } from '@dxos/react-ui-text-tooltip';
|
|
12
|
+
import { hoverableControls, hoverableFocusedWithinControls } from '@dxos/react-ui-theme';
|
|
12
13
|
|
|
13
14
|
import { PlankCompanionControls, PlankControls } from './PlankControls';
|
|
15
|
+
import { useBreakpoints } from '../../hooks';
|
|
14
16
|
import { parseEntryId } from '../../layout';
|
|
15
17
|
import { DECK_PLUGIN } from '../../meta';
|
|
16
18
|
import { PLANK_COMPANION_TYPE, DeckAction, type ResolvedPart, type LayoutMode } from '../../types';
|
|
17
|
-
import { useBreakpoints } from '../../util';
|
|
18
19
|
import { soloInlinePadding } from '../fragments';
|
|
19
20
|
|
|
20
21
|
const MAX_COMPANIONS = 5;
|
|
@@ -65,7 +66,7 @@ export const PlankHeading = memo(
|
|
|
65
66
|
useEffect(() => {
|
|
66
67
|
const frame = requestAnimationFrame(() => {
|
|
67
68
|
// Load actions for the node.
|
|
68
|
-
node && graph.
|
|
69
|
+
node && graph.expand(node.id);
|
|
69
70
|
});
|
|
70
71
|
|
|
71
72
|
return () => cancelAnimationFrame(frame);
|
|
@@ -78,6 +79,7 @@ export const PlankHeading = memo(
|
|
|
78
79
|
solo: breakpoint !== 'mobile' && (part === 'solo' || part === 'deck'),
|
|
79
80
|
incrementStart: canIncrementStart,
|
|
80
81
|
incrementEnd: canIncrementEnd,
|
|
82
|
+
fullscreen: !isCompanionNode,
|
|
81
83
|
companion: !isCompanionNode && companions && companions.length > 0,
|
|
82
84
|
}),
|
|
83
85
|
[breakpoint, part, companions, canIncrementStart, canIncrementEnd, isCompanionNode, deckEnabled],
|
|
@@ -90,13 +92,16 @@ export const PlankHeading = memo(
|
|
|
90
92
|
} else if (variant) {
|
|
91
93
|
return [];
|
|
92
94
|
} else {
|
|
93
|
-
return [actions, graph.
|
|
95
|
+
return [actions, graph.getActions(node.id)].filter((a) => a.length > 0);
|
|
94
96
|
}
|
|
95
97
|
}, [actions, node, variant, graph]);
|
|
96
98
|
|
|
97
|
-
const handleAction = useCallback(
|
|
98
|
-
|
|
99
|
-
|
|
99
|
+
const handleAction = useCallback(
|
|
100
|
+
(action: StackItemSigilAction) => {
|
|
101
|
+
typeof action.data === 'function' && action.data?.({ parent: node, caller: DECK_PLUGIN });
|
|
102
|
+
},
|
|
103
|
+
[node],
|
|
104
|
+
);
|
|
100
105
|
|
|
101
106
|
const handlePlankAction = useCallback(
|
|
102
107
|
(eventType: DeckAction.PartAdjustment) => {
|
|
@@ -145,12 +150,17 @@ export const PlankHeading = memo(
|
|
|
145
150
|
classNames={[
|
|
146
151
|
'plb-1 border-be border-separator items-stretch gap-1 sticky inline-start-12 app-drag min-is-0 contain-layout',
|
|
147
152
|
part === 'solo' ? soloInlinePadding : 'pli-1',
|
|
148
|
-
layoutMode === 'solo--fullscreen'
|
|
149
|
-
|
|
153
|
+
...(layoutMode === 'solo--fullscreen'
|
|
154
|
+
? [
|
|
155
|
+
hoverableControls,
|
|
156
|
+
hoverableFocusedWithinControls,
|
|
157
|
+
'[&>*]:transition-opacity [&>*]:opacity-[--controls-opacity] bg-transparent border-transparent transition-[background-color,border-color] hover-hover:hover:bg-headerSurface focus-within:bg-headerSurface hover-hover:hover:border-separator focus-within:border-separator',
|
|
158
|
+
]
|
|
159
|
+
: []),
|
|
150
160
|
]}
|
|
151
161
|
data-plank-heading
|
|
152
162
|
>
|
|
153
|
-
{companions && isCompanionNode ? (
|
|
163
|
+
{companions && isCompanionNode /* TODO(thure): This is a tablist, it should be implemented as such. */ ? (
|
|
154
164
|
<div role='none' className='flex-1 min-is-0 overflow-x-auto scrollbar-thin flex gap-1'>
|
|
155
165
|
{companions.map(({ id, properties: { icon, label } }) => (
|
|
156
166
|
<IconButton
|
|
@@ -12,51 +12,20 @@ import React, {
|
|
|
12
12
|
useState,
|
|
13
13
|
} from 'react';
|
|
14
14
|
|
|
15
|
-
import {
|
|
16
|
-
LayoutAction,
|
|
17
|
-
Surface,
|
|
18
|
-
createIntent,
|
|
19
|
-
useAppGraph,
|
|
20
|
-
useCapability,
|
|
21
|
-
useIntentDispatcher,
|
|
22
|
-
} from '@dxos/app-framework';
|
|
23
|
-
import { type Node } from '@dxos/plugin-graph';
|
|
15
|
+
import { LayoutAction, Surface, createIntent, useCapability, useIntentDispatcher } from '@dxos/app-framework';
|
|
24
16
|
import { Main, useTranslation, toLocalizedString, IconButton, type Label } from '@dxos/react-ui';
|
|
25
17
|
import { Tabs } from '@dxos/react-ui-tabs';
|
|
26
|
-
import { byPosition, type Position } from '@dxos/util';
|
|
27
18
|
|
|
28
19
|
import { ToggleComplementarySidebarButton } from './SidebarButton';
|
|
29
20
|
import { DeckCapabilities } from '../../capabilities';
|
|
21
|
+
import { type DeckCompanion, getCompanionId, useDeckCompanions, useBreakpoints, useHoistStatusbar } from '../../hooks';
|
|
30
22
|
import { DECK_PLUGIN } from '../../meta';
|
|
31
|
-
import {
|
|
32
|
-
import { layoutAppliesTopbar
|
|
23
|
+
import { getMode } from '../../types';
|
|
24
|
+
import { layoutAppliesTopbar } from '../../util';
|
|
33
25
|
import { PlankContentError, PlankLoading } from '../Plank';
|
|
34
26
|
|
|
35
27
|
const label = ['complementary sidebar title', { ns: DECK_PLUGIN }] satisfies Label;
|
|
36
28
|
|
|
37
|
-
const getCompanionId = (id: string) => {
|
|
38
|
-
const [_, companionId] = id.split(ATTENDABLE_PATH_SEPARATOR);
|
|
39
|
-
return companionId ?? 'never';
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
type DeckCompanion = Node<
|
|
43
|
-
any,
|
|
44
|
-
{
|
|
45
|
-
label: Label;
|
|
46
|
-
icon: string;
|
|
47
|
-
// TODO(burdon): Scroll area should be controlled by surface.
|
|
48
|
-
/** If true, the panel will not be wrapped in a scroll area. */
|
|
49
|
-
fixed?: boolean;
|
|
50
|
-
position?: Position;
|
|
51
|
-
}
|
|
52
|
-
>;
|
|
53
|
-
|
|
54
|
-
const useDeckCompanions = (): DeckCompanion[] => {
|
|
55
|
-
const { graph } = useAppGraph();
|
|
56
|
-
const companions = graph.nodes(graph.root, { type: DECK_COMPANION_TYPE }) as DeckCompanion[];
|
|
57
|
-
return companions.toSorted((a, b) => byPosition(a.properties, b.properties));
|
|
58
|
-
};
|
|
59
|
-
|
|
60
29
|
export type ComplementarySidebarProps = {
|
|
61
30
|
current?: string;
|
|
62
31
|
};
|
|
@@ -8,9 +8,10 @@ import { Surface, useCapability } from '@dxos/app-framework';
|
|
|
8
8
|
import { type Label, Main } from '@dxos/react-ui';
|
|
9
9
|
|
|
10
10
|
import { DeckCapabilities } from '../../capabilities';
|
|
11
|
+
import { useBreakpoints, useHoistStatusbar } from '../../hooks';
|
|
11
12
|
import { DECK_PLUGIN } from '../../meta';
|
|
12
13
|
import { getMode } from '../../types';
|
|
13
|
-
import { layoutAppliesTopbar
|
|
14
|
+
import { layoutAppliesTopbar } from '../../util';
|
|
14
15
|
|
|
15
16
|
const label = ['sidebar title', { ns: DECK_PLUGIN }] satisfies Label;
|
|
16
17
|
|