@dxos/plugin-deck 0.8.1-staging.391c573 → 0.8.1-staging.9eaf14f
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-IYHAGFA3.mjs → app-graph-builder-VYZ4IWI3.mjs} +3 -3
- package/dist/lib/browser/{check-app-scheme-S3EYUPMF.mjs → check-app-scheme-SEYECDHI.mjs} +2 -2
- package/dist/lib/browser/{chunk-YCKJNTKG.mjs → chunk-6ZSOFCPP.mjs} +26 -6
- package/dist/lib/browser/chunk-6ZSOFCPP.mjs.map +7 -0
- package/dist/lib/browser/chunk-B4LOJUWW.mjs +24 -0
- package/dist/lib/browser/{chunk-Z23S33X6.mjs → chunk-FJBMNSUC.mjs} +638 -483
- package/dist/lib/browser/chunk-FJBMNSUC.mjs.map +7 -0
- package/dist/lib/browser/chunk-FLOVGNYB.mjs +81 -0
- package/dist/lib/browser/chunk-FLOVGNYB.mjs.map +7 -0
- package/dist/lib/browser/{chunk-N7TEPFVR.mjs → chunk-NSATFAEE.mjs} +3 -3
- package/dist/lib/browser/{chunk-N7TEPFVR.mjs.map → chunk-NSATFAEE.mjs.map} +2 -2
- package/dist/lib/browser/{chunk-FYKBOM3C.mjs → chunk-RJNCG4ND.mjs} +66 -40
- package/dist/lib/browser/chunk-RJNCG4ND.mjs.map +7 -0
- package/dist/lib/browser/{chunk-22AQ5IVX.mjs → chunk-XMCG42ID.mjs} +2 -3
- package/dist/lib/browser/chunk-XMCG42ID.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +14 -9
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/{intent-resolver-P5BVUQKU.mjs → intent-resolver-UDYKO2QW.mjs} +78 -88
- package/dist/lib/browser/intent-resolver-UDYKO2QW.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/{react-root-EP4UF3KA.mjs → react-root-XLXN2VEW.mjs} +8 -10
- package/dist/lib/browser/react-root-XLXN2VEW.mjs.map +7 -0
- package/dist/lib/browser/{react-surface-5B3RLJCD.mjs → react-surface-WNGMZL7I.mjs} +11 -10
- package/dist/lib/browser/react-surface-WNGMZL7I.mjs.map +7 -0
- package/dist/lib/browser/{settings-X3P2HKQJ.mjs → settings-HMDGSBGO.mjs} +5 -4
- package/dist/lib/browser/settings-HMDGSBGO.mjs.map +7 -0
- package/dist/lib/browser/{state-2MOTLKVR.mjs → state-7TN26M42.mjs} +7 -11
- package/dist/lib/browser/state-7TN26M42.mjs.map +7 -0
- package/dist/lib/browser/tools-SC6QEN7R.mjs +78 -0
- package/dist/lib/browser/tools-SC6QEN7R.mjs.map +7 -0
- package/dist/lib/browser/types.mjs +12 -6
- package/dist/lib/browser/{url-handler-MVHTKUYA.mjs → url-handler-ODG4B6NX.mjs} +7 -9
- package/dist/lib/browser/url-handler-ODG4B6NX.mjs.map +7 -0
- package/dist/types/src/DeckPlugin.d.ts.map +1 -1
- package/dist/types/src/capabilities/capabilities.d.ts +36 -14
- package/dist/types/src/capabilities/capabilities.d.ts.map +1 -1
- package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
- package/dist/types/src/capabilities/react-root.d.ts.map +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
- package/dist/types/src/capabilities/settings.d.ts.map +1 -1
- package/dist/types/src/capabilities/state.d.ts +18 -6
- package/dist/types/src/capabilities/state.d.ts.map +1 -1
- package/dist/types/src/capabilities/tools.d.ts +1 -0
- package/dist/types/src/capabilities/tools.d.ts.map +1 -1
- package/dist/types/src/capabilities/url-handler.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/ActiveNode.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/Banner.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/DeckLayout.d.ts +1 -4
- package/dist/types/src/components/DeckLayout/DeckLayout.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/Toast.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/index.d.ts +1 -0
- package/dist/types/src/components/DeckLayout/index.d.ts.map +1 -1
- package/dist/types/src/components/DeckSettings/DeckSettings.d.ts +6 -0
- package/dist/types/src/components/DeckSettings/DeckSettings.d.ts.map +1 -0
- package/dist/types/src/components/DeckSettings/index.d.ts +2 -0
- package/dist/types/src/components/DeckSettings/index.d.ts.map +1 -0
- package/dist/types/src/components/Plank/Plank.d.ts +14 -0
- package/dist/types/src/components/Plank/Plank.d.ts.map +1 -0
- package/dist/types/src/components/Plank/Plank.stories.d.ts +8 -0
- package/dist/types/src/components/Plank/Plank.stories.d.ts.map +1 -0
- package/dist/types/src/components/{DeckLayout → Plank}/PlankControls.d.ts +8 -1
- package/dist/types/src/components/Plank/PlankControls.d.ts.map +1 -0
- package/dist/types/src/components/{DeckLayout → Plank}/PlankError.d.ts +2 -2
- package/dist/types/src/components/Plank/PlankError.d.ts.map +1 -0
- package/dist/types/src/components/Plank/PlankHeading.d.ts +20 -0
- package/dist/types/src/components/Plank/PlankHeading.d.ts.map +1 -0
- package/dist/types/src/components/Plank/PlankLoading.d.ts.map +1 -0
- package/dist/types/src/components/Plank/index.d.ts +6 -0
- package/dist/types/src/components/Plank/index.d.ts.map +1 -0
- package/dist/types/src/components/Sidebar/ComplementarySidebar.d.ts.map +1 -0
- package/dist/types/src/components/Sidebar/Sidebar.d.ts.map +1 -0
- package/dist/types/src/components/Sidebar/SidebarButton.d.ts.map +1 -0
- package/dist/types/src/components/Sidebar/index.d.ts +4 -0
- package/dist/types/src/components/Sidebar/index.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +1 -1
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/events.d.ts +0 -1
- package/dist/types/src/events.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +0 -1
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/layout.d.ts +7 -1
- package/dist/types/src/layout.d.ts.map +1 -1
- package/dist/types/src/meta.d.ts +2 -5
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +4 -0
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types.d.ts +50 -48
- package/dist/types/src/types.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +1 -0
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/src/util/set-active.d.ts +2 -2
- package/dist/types/src/util/set-active.d.ts.map +1 -1
- package/dist/types/src/util/useCompanions.d.ts +8 -0
- package/dist/types/src/util/useCompanions.d.ts.map +1 -0
- package/dist/types/src/util/useHoistStatusbar.d.ts.map +1 -1
- package/package.json +28 -29
- package/src/DeckPlugin.ts +0 -1
- package/src/capabilities/capabilities.ts +3 -4
- package/src/capabilities/intent-resolver.ts +63 -9
- package/src/capabilities/react-root.tsx +1 -9
- package/src/capabilities/react-surface.tsx +3 -4
- package/src/capabilities/settings.ts +7 -2
- package/src/capabilities/state.ts +4 -11
- package/src/capabilities/tools.ts +34 -22
- package/src/capabilities/url-handler.ts +2 -8
- package/src/components/DeckLayout/ActiveNode.tsx +2 -1
- package/src/components/DeckLayout/Banner.tsx +5 -3
- package/src/components/DeckLayout/ContentEmpty.tsx +1 -1
- package/src/components/DeckLayout/DeckLayout.tsx +58 -24
- package/src/components/DeckLayout/Fullscreen.tsx +1 -1
- package/src/components/DeckLayout/Toast.tsx +1 -1
- package/src/components/DeckLayout/index.ts +2 -0
- package/src/components/{LayoutSettings.tsx → DeckSettings/DeckSettings.tsx} +15 -10
- package/src/components/DeckSettings/index.ts +5 -0
- package/src/components/Plank/Plank.stories.tsx +43 -0
- package/src/components/Plank/Plank.tsx +230 -0
- package/src/components/{DeckLayout → Plank}/PlankControls.tsx +73 -27
- package/src/components/{DeckLayout → Plank}/PlankError.tsx +3 -3
- package/src/components/Plank/PlankHeading.tsx +207 -0
- package/src/components/Plank/index.ts +9 -0
- package/src/components/{DeckLayout → Sidebar}/ComplementarySidebar.tsx +65 -81
- package/src/components/Sidebar/index.ts +7 -0
- package/src/components/index.ts +1 -1
- package/src/events.ts +0 -1
- package/src/hooks/index.ts +0 -1
- package/src/index.ts +1 -0
- package/src/layout.ts +19 -2
- package/src/meta.ts +4 -4
- package/src/translations.ts +4 -0
- package/src/types.ts +81 -79
- package/src/util/index.ts +1 -0
- package/src/util/set-active.ts +2 -2
- package/src/util/useCompanions.ts +18 -0
- package/src/util/useHoistStatusbar.ts +2 -2
- package/dist/lib/browser/chunk-22AQ5IVX.mjs.map +0 -7
- package/dist/lib/browser/chunk-FYKBOM3C.mjs.map +0 -7
- package/dist/lib/browser/chunk-IZ5RPJ6T.mjs +0 -24
- package/dist/lib/browser/chunk-YCKJNTKG.mjs.map +0 -7
- package/dist/lib/browser/chunk-Z23S33X6.mjs.map +0 -7
- package/dist/lib/browser/intent-resolver-P5BVUQKU.mjs.map +0 -7
- package/dist/lib/browser/react-root-EP4UF3KA.mjs.map +0 -7
- package/dist/lib/browser/react-surface-5B3RLJCD.mjs.map +0 -7
- package/dist/lib/browser/settings-X3P2HKQJ.mjs.map +0 -7
- package/dist/lib/browser/state-2MOTLKVR.mjs.map +0 -7
- package/dist/lib/browser/tools-64LXGLYR.mjs +0 -59
- package/dist/lib/browser/tools-64LXGLYR.mjs.map +0 -7
- package/dist/lib/browser/url-handler-MVHTKUYA.mjs.map +0 -7
- package/dist/types/src/components/DeckLayout/ComplementarySidebar.d.ts.map +0 -1
- package/dist/types/src/components/DeckLayout/NodePlankHeading.d.ts +0 -15
- package/dist/types/src/components/DeckLayout/NodePlankHeading.d.ts.map +0 -1
- package/dist/types/src/components/DeckLayout/Plank.d.ts +0 -13
- package/dist/types/src/components/DeckLayout/Plank.d.ts.map +0 -1
- package/dist/types/src/components/DeckLayout/PlankControls.d.ts.map +0 -1
- package/dist/types/src/components/DeckLayout/PlankError.d.ts.map +0 -1
- package/dist/types/src/components/DeckLayout/PlankLoading.d.ts.map +0 -1
- package/dist/types/src/components/DeckLayout/Sidebar.d.ts.map +0 -1
- package/dist/types/src/components/DeckLayout/SidebarButton.d.ts.map +0 -1
- package/dist/types/src/components/LayoutSettings.d.ts +0 -6
- package/dist/types/src/components/LayoutSettings.d.ts.map +0 -1
- package/dist/types/src/hooks/useNode.d.ts +0 -11
- package/dist/types/src/hooks/useNode.d.ts.map +0 -1
- package/src/components/DeckLayout/NodePlankHeading.tsx +0 -148
- package/src/components/DeckLayout/Plank.tsx +0 -149
- package/src/hooks/useNode.ts +0 -46
- /package/dist/lib/browser/{app-graph-builder-IYHAGFA3.mjs.map → app-graph-builder-VYZ4IWI3.mjs.map} +0 -0
- /package/dist/lib/browser/{check-app-scheme-S3EYUPMF.mjs.map → check-app-scheme-SEYECDHI.mjs.map} +0 -0
- /package/dist/lib/browser/{chunk-IZ5RPJ6T.mjs.map → chunk-B4LOJUWW.mjs.map} +0 -0
- /package/dist/types/src/components/{DeckLayout → Plank}/PlankLoading.d.ts +0 -0
- /package/dist/types/src/components/{DeckLayout → Sidebar}/ComplementarySidebar.d.ts +0 -0
- /package/dist/types/src/components/{DeckLayout → Sidebar}/Sidebar.d.ts +0 -0
- /package/dist/types/src/components/{DeckLayout → Sidebar}/SidebarButton.d.ts +0 -0
- /package/src/components/{DeckLayout → Plank}/PlankLoading.tsx +0 -0
- /package/src/components/{DeckLayout → Sidebar}/Sidebar.tsx +0 -0
- /package/src/components/{DeckLayout → Sidebar}/SidebarButton.tsx +0 -0
|
@@ -7,24 +7,28 @@ import React from 'react';
|
|
|
7
7
|
import { Input, Select, useTranslation } from '@dxos/react-ui';
|
|
8
8
|
import { DeprecatedFormContainer, DeprecatedFormInput } from '@dxos/react-ui-form';
|
|
9
9
|
|
|
10
|
-
import { DECK_PLUGIN } from '
|
|
10
|
+
import { DECK_PLUGIN } from '../../meta';
|
|
11
11
|
import {
|
|
12
|
+
type DeckSettingsProps,
|
|
12
13
|
type NewPlankPositioning,
|
|
13
14
|
NewPlankPositions,
|
|
14
|
-
type DeckSettingsProps,
|
|
15
15
|
type Overscroll,
|
|
16
16
|
OverscrollOptions,
|
|
17
|
-
} from '
|
|
17
|
+
} from '../../types';
|
|
18
18
|
|
|
19
19
|
const isSocket = !!(globalThis as any).__args;
|
|
20
20
|
|
|
21
|
-
export const
|
|
21
|
+
export const DeckSettings = ({ settings }: { settings: DeckSettingsProps }) => {
|
|
22
22
|
const { t } = useTranslation(DECK_PLUGIN);
|
|
23
23
|
|
|
24
24
|
return (
|
|
25
25
|
<DeprecatedFormContainer>
|
|
26
|
+
<DeprecatedFormInput label={t('settings enable deck label')}>
|
|
27
|
+
<Input.Switch checked={settings.enableDeck} onCheckedChange={(checked) => (settings.enableDeck = checked)} />
|
|
28
|
+
</DeprecatedFormInput>
|
|
26
29
|
<DeprecatedFormInput label={t('select new plank positioning label')}>
|
|
27
30
|
<Select.Root
|
|
31
|
+
disabled={!settings.enableDeck}
|
|
28
32
|
value={settings.newPlankPositioning ?? 'start'}
|
|
29
33
|
onValueChange={(value) => (settings.newPlankPositioning = value as NewPlankPositioning)}
|
|
30
34
|
>
|
|
@@ -44,6 +48,7 @@ export const LayoutSettings = ({ settings }: { settings: DeckSettingsProps }) =>
|
|
|
44
48
|
</DeprecatedFormInput>
|
|
45
49
|
<DeprecatedFormInput label={t('settings overscroll label')}>
|
|
46
50
|
<Select.Root
|
|
51
|
+
disabled={!settings.enableDeck}
|
|
47
52
|
value={settings.overscroll ?? 'none'}
|
|
48
53
|
onValueChange={(value) => (settings.overscroll = value as Overscroll)}
|
|
49
54
|
>
|
|
@@ -61,6 +66,12 @@ export const LayoutSettings = ({ settings }: { settings: DeckSettingsProps }) =>
|
|
|
61
66
|
</Select.Portal>
|
|
62
67
|
</Select.Root>
|
|
63
68
|
</DeprecatedFormInput>
|
|
69
|
+
<DeprecatedFormInput label={t('settings enable statusbar label')}>
|
|
70
|
+
<Input.Switch
|
|
71
|
+
checked={settings.enableStatusbar}
|
|
72
|
+
onCheckedChange={(checked) => (settings.enableStatusbar = checked)}
|
|
73
|
+
/>
|
|
74
|
+
</DeprecatedFormInput>
|
|
64
75
|
<DeprecatedFormInput label={t('settings show hints label')}>
|
|
65
76
|
<Input.Switch checked={settings.showHints} onCheckedChange={(checked) => (settings.showHints = checked)} />
|
|
66
77
|
</DeprecatedFormInput>
|
|
@@ -72,12 +83,6 @@ export const LayoutSettings = ({ settings }: { settings: DeckSettingsProps }) =>
|
|
|
72
83
|
/>
|
|
73
84
|
</DeprecatedFormInput>
|
|
74
85
|
)}
|
|
75
|
-
<DeprecatedFormInput label={t('settings enable statusbar label')}>
|
|
76
|
-
<Input.Switch
|
|
77
|
-
checked={settings.enableStatusbar}
|
|
78
|
-
onCheckedChange={(checked) => (settings.enableStatusbar = checked)}
|
|
79
|
-
/>
|
|
80
|
-
</DeprecatedFormInput>
|
|
81
86
|
</DeprecatedFormContainer>
|
|
82
87
|
);
|
|
83
88
|
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import '@dxos-theme';
|
|
6
|
+
|
|
7
|
+
import { type StoryObj, type Meta } from '@storybook/react';
|
|
8
|
+
|
|
9
|
+
import { IntentPlugin } from '@dxos/app-framework';
|
|
10
|
+
import { withPluginManager } from '@dxos/app-framework/testing';
|
|
11
|
+
import { GraphPlugin } from '@dxos/plugin-graph';
|
|
12
|
+
import { withTheme, withLayout } from '@dxos/storybook-utils';
|
|
13
|
+
|
|
14
|
+
import { Plank } from './Plank';
|
|
15
|
+
import translations from '../../translations';
|
|
16
|
+
|
|
17
|
+
// TODO(burdon): invariant violation: No capability found for dxos.org/plugin/deck/capability/state
|
|
18
|
+
const meta: Meta<typeof Plank> = {
|
|
19
|
+
title: 'plugins/plugin-deck/Plank',
|
|
20
|
+
component: Plank,
|
|
21
|
+
decorators: [
|
|
22
|
+
withPluginManager({
|
|
23
|
+
plugins: [IntentPlugin(), GraphPlugin()],
|
|
24
|
+
}),
|
|
25
|
+
withTheme,
|
|
26
|
+
withLayout({ fullscreen: true, tooltips: true }),
|
|
27
|
+
],
|
|
28
|
+
parameters: {
|
|
29
|
+
layout: 'centered',
|
|
30
|
+
translations,
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export default meta;
|
|
35
|
+
|
|
36
|
+
type Story = StoryObj<typeof meta>;
|
|
37
|
+
|
|
38
|
+
export const Default: Story = {
|
|
39
|
+
args: {
|
|
40
|
+
id: 'plank-1',
|
|
41
|
+
part: 'solo',
|
|
42
|
+
},
|
|
43
|
+
};
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, {
|
|
6
|
+
Fragment,
|
|
7
|
+
type KeyboardEvent,
|
|
8
|
+
type PropsWithChildren,
|
|
9
|
+
memo,
|
|
10
|
+
useCallback,
|
|
11
|
+
useLayoutEffect,
|
|
12
|
+
useMemo,
|
|
13
|
+
useRef,
|
|
14
|
+
} from 'react';
|
|
15
|
+
|
|
16
|
+
import {
|
|
17
|
+
LayoutAction,
|
|
18
|
+
Surface,
|
|
19
|
+
createIntent,
|
|
20
|
+
useCapability,
|
|
21
|
+
useAppGraph,
|
|
22
|
+
useIntentDispatcher,
|
|
23
|
+
} from '@dxos/app-framework';
|
|
24
|
+
import { debounce } from '@dxos/async';
|
|
25
|
+
import { useNode, type Node } from '@dxos/plugin-graph';
|
|
26
|
+
import { ATTENDABLE_PATH_SEPARATOR, useAttendableAttributes } from '@dxos/react-ui-attention';
|
|
27
|
+
import { StackItem, railGridHorizontal } from '@dxos/react-ui-stack';
|
|
28
|
+
import { mainIntrinsicSize, mx } from '@dxos/react-ui-theme';
|
|
29
|
+
|
|
30
|
+
import { PlankContentError, PlankError } from './PlankError';
|
|
31
|
+
import { PlankHeading } from './PlankHeading';
|
|
32
|
+
import { PlankLoading } from './PlankLoading';
|
|
33
|
+
import { DeckCapabilities } from '../../capabilities';
|
|
34
|
+
import { useMainSize } from '../../hooks';
|
|
35
|
+
import { parseEntryId } from '../../layout';
|
|
36
|
+
import { DeckAction, type LayoutMode, type Part, type ResolvedPart, type DeckSettingsProps } from '../../types';
|
|
37
|
+
import { useCompanions } from '../../util';
|
|
38
|
+
|
|
39
|
+
const UNKNOWN_ID = 'unknown_id';
|
|
40
|
+
|
|
41
|
+
export type PlankProps = {
|
|
42
|
+
id?: string;
|
|
43
|
+
companionId?: string;
|
|
44
|
+
part: Part;
|
|
45
|
+
path?: string[];
|
|
46
|
+
order?: number;
|
|
47
|
+
active?: string[];
|
|
48
|
+
layoutMode: LayoutMode;
|
|
49
|
+
settings?: DeckSettingsProps;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
type PlankImplProps = Omit<PlankProps, 'id' | 'companionId' | 'part'> & {
|
|
53
|
+
id: string;
|
|
54
|
+
part: ResolvedPart;
|
|
55
|
+
node?: Node;
|
|
56
|
+
companioned?: 'primary' | 'companion';
|
|
57
|
+
primary?: Node;
|
|
58
|
+
companions?: Node[];
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const PlankImpl = memo(
|
|
62
|
+
({ id, node, part, path, order, active, layoutMode, companioned, primary, companions, settings }: PlankImplProps) => {
|
|
63
|
+
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
64
|
+
const { deck, popoverAnchorId, scrollIntoView } = useCapability(DeckCapabilities.DeckState);
|
|
65
|
+
const rootElement = useRef<HTMLDivElement | null>(null);
|
|
66
|
+
const canResize = layoutMode === 'deck';
|
|
67
|
+
const Root = part.startsWith('solo') ? 'article' : StackItem.Root;
|
|
68
|
+
|
|
69
|
+
const attendableAttrs = useAttendableAttributes(primary?.id ?? id);
|
|
70
|
+
const index = active ? active.findIndex((entryId) => entryId === id) : 0;
|
|
71
|
+
const length = active?.length ?? 1;
|
|
72
|
+
const canIncrementStart = active && index !== undefined && index > 0 && length !== undefined && length > 1;
|
|
73
|
+
const canIncrementEnd = active && index !== undefined && index < length - 1 && length !== undefined;
|
|
74
|
+
|
|
75
|
+
const { variant } = parseEntryId(id);
|
|
76
|
+
const sizeKey = `${id.split('+')[0]}${variant ? `${ATTENDABLE_PATH_SEPARATOR}${variant}` : ''}`;
|
|
77
|
+
const size = deck.plankSizing[sizeKey] as number | undefined;
|
|
78
|
+
const setSize = useCallback(
|
|
79
|
+
debounce((nextSize: number) => {
|
|
80
|
+
return dispatch(createIntent(DeckAction.UpdatePlankSize, { id: sizeKey, size: nextSize }));
|
|
81
|
+
}, 200),
|
|
82
|
+
[dispatch, sizeKey],
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
// TODO(thure): Tabster’s focus group should handle moving focus to Main, but something is blocking it.
|
|
86
|
+
const handleKeyDown = useCallback((event: KeyboardEvent) => {
|
|
87
|
+
if (event.target === event.currentTarget && event.key === 'Escape') {
|
|
88
|
+
rootElement.current?.closest('main')?.focus();
|
|
89
|
+
}
|
|
90
|
+
}, []);
|
|
91
|
+
|
|
92
|
+
useLayoutEffect(() => {
|
|
93
|
+
if (scrollIntoView === id) {
|
|
94
|
+
// TODO(wittjosiah): When focused on page load, the focus is always visible.
|
|
95
|
+
// Forcing focus to something smaller than the plank prevents large focus ring in the interim.
|
|
96
|
+
const focusable = rootElement.current?.querySelector('button') || rootElement.current;
|
|
97
|
+
focusable?.focus({ preventScroll: true });
|
|
98
|
+
layoutMode === 'deck' && focusable?.scrollIntoView({ behavior: 'smooth', inline: 'center' });
|
|
99
|
+
// Clear the scroll into view state once it has been actioned.
|
|
100
|
+
void dispatch(createIntent(LayoutAction.ScrollIntoView, { part: 'current', subject: undefined }));
|
|
101
|
+
}
|
|
102
|
+
}, [id, scrollIntoView, layoutMode]);
|
|
103
|
+
|
|
104
|
+
const isSolo = layoutMode === 'solo' && part === 'solo';
|
|
105
|
+
const isAttendable =
|
|
106
|
+
(layoutMode === 'solo' && part.startsWith('solo')) || (layoutMode === 'deck' && part === 'deck');
|
|
107
|
+
|
|
108
|
+
const sizeAttrs = useMainSize();
|
|
109
|
+
|
|
110
|
+
const data = useMemo(
|
|
111
|
+
() =>
|
|
112
|
+
node && {
|
|
113
|
+
subject: node.data,
|
|
114
|
+
companionTo: primary?.data,
|
|
115
|
+
variant,
|
|
116
|
+
path,
|
|
117
|
+
popoverAnchorId,
|
|
118
|
+
},
|
|
119
|
+
[node, node?.data, path, popoverAnchorId, primary?.data],
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
// TODO(wittjosiah): Change prop to accept a component.
|
|
123
|
+
const placeholder = useMemo(() => <PlankLoading />, []);
|
|
124
|
+
|
|
125
|
+
const className = mx(
|
|
126
|
+
'attention-surface relative',
|
|
127
|
+
isSolo && mainIntrinsicSize,
|
|
128
|
+
isSolo && railGridHorizontal,
|
|
129
|
+
isSolo && 'absolute inset-0',
|
|
130
|
+
part.startsWith('solo') && 'grid',
|
|
131
|
+
part === 'deck' && (companioned === 'companion' ? '!border-separator border-ie' : '!border-separator border-li'),
|
|
132
|
+
part.startsWith('solo-') && 'row-span-2 grid-rows-subgrid min-is-0',
|
|
133
|
+
part === 'solo-companion' && '!border-separator border-is',
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
return (
|
|
137
|
+
<Root
|
|
138
|
+
ref={rootElement}
|
|
139
|
+
data-testid='deck.plank'
|
|
140
|
+
tabIndex={0}
|
|
141
|
+
{...(part.startsWith('solo')
|
|
142
|
+
? ({ ...sizeAttrs, className } as any)
|
|
143
|
+
: {
|
|
144
|
+
item: { id },
|
|
145
|
+
size,
|
|
146
|
+
onSizeChange: setSize,
|
|
147
|
+
classNames: className,
|
|
148
|
+
order,
|
|
149
|
+
role: 'article',
|
|
150
|
+
})}
|
|
151
|
+
{...(isAttendable ? attendableAttrs : {})}
|
|
152
|
+
onKeyDown={handleKeyDown}
|
|
153
|
+
>
|
|
154
|
+
{node ? (
|
|
155
|
+
<>
|
|
156
|
+
<PlankHeading
|
|
157
|
+
id={id}
|
|
158
|
+
part={part.startsWith('solo-') ? 'solo' : part}
|
|
159
|
+
node={node}
|
|
160
|
+
deckEnabled={settings?.enableDeck}
|
|
161
|
+
canIncrementStart={canIncrementStart}
|
|
162
|
+
canIncrementEnd={canIncrementEnd}
|
|
163
|
+
popoverAnchorId={popoverAnchorId}
|
|
164
|
+
primaryId={primary?.id}
|
|
165
|
+
companioned={companioned}
|
|
166
|
+
companions={companions}
|
|
167
|
+
/>
|
|
168
|
+
<Surface
|
|
169
|
+
key={node.id}
|
|
170
|
+
role='article'
|
|
171
|
+
data={data}
|
|
172
|
+
limit={1}
|
|
173
|
+
fallback={PlankContentError}
|
|
174
|
+
placeholder={placeholder}
|
|
175
|
+
/>
|
|
176
|
+
</>
|
|
177
|
+
) : (
|
|
178
|
+
<PlankError id={id} part={part} />
|
|
179
|
+
)}
|
|
180
|
+
{canResize && <StackItem.ResizeHandle />}
|
|
181
|
+
</Root>
|
|
182
|
+
);
|
|
183
|
+
},
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
const SplitFrame = ({ children }: PropsWithChildren<{}>) => {
|
|
187
|
+
const sizeAttrs = useMainSize();
|
|
188
|
+
return (
|
|
189
|
+
<div
|
|
190
|
+
role='none'
|
|
191
|
+
className={mx('grid grid-cols-[1fr_1fr] absolute inset-0', railGridHorizontal, mainIntrinsicSize)}
|
|
192
|
+
{...sizeAttrs}
|
|
193
|
+
>
|
|
194
|
+
{children}
|
|
195
|
+
</div>
|
|
196
|
+
);
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
export const Plank = ({ id = UNKNOWN_ID, ...props }: PlankProps) => {
|
|
200
|
+
const { graph } = useAppGraph();
|
|
201
|
+
const node = useNode(graph, id);
|
|
202
|
+
const companions = useCompanions(id);
|
|
203
|
+
const currentCompanion = companions.find(({ id }) => id === props.companionId);
|
|
204
|
+
|
|
205
|
+
if (props.companionId) {
|
|
206
|
+
const Root = props.part === 'solo' ? SplitFrame : Fragment;
|
|
207
|
+
return (
|
|
208
|
+
<Root>
|
|
209
|
+
<PlankImpl
|
|
210
|
+
id={id}
|
|
211
|
+
node={node}
|
|
212
|
+
companioned='primary'
|
|
213
|
+
{...props}
|
|
214
|
+
{...(props.part === 'solo' ? { part: 'solo-primary' } : {})}
|
|
215
|
+
/>
|
|
216
|
+
<PlankImpl
|
|
217
|
+
id={props.companionId}
|
|
218
|
+
node={currentCompanion}
|
|
219
|
+
companioned='companion'
|
|
220
|
+
primary={node}
|
|
221
|
+
companions={companions}
|
|
222
|
+
{...props}
|
|
223
|
+
{...(props.part === 'solo' ? { part: 'solo-companion' } : { order: props.order! + 1 })}
|
|
224
|
+
/>
|
|
225
|
+
</Root>
|
|
226
|
+
);
|
|
227
|
+
} else {
|
|
228
|
+
return <PlankImpl id={id} node={node} companions={companions} {...props} />;
|
|
229
|
+
}
|
|
230
|
+
};
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import React, { forwardRef } from 'react';
|
|
5
|
+
import React, { forwardRef, useCallback } from 'react';
|
|
6
6
|
|
|
7
|
+
import { createIntent, useIntentDispatcher } from '@dxos/app-framework';
|
|
8
|
+
import { invariant } from '@dxos/invariant';
|
|
7
9
|
import {
|
|
8
10
|
Button,
|
|
9
11
|
ButtonGroup,
|
|
@@ -15,14 +17,16 @@ import {
|
|
|
15
17
|
} from '@dxos/react-ui';
|
|
16
18
|
|
|
17
19
|
import { DECK_PLUGIN } from '../../meta';
|
|
18
|
-
import {
|
|
20
|
+
import { DeckAction } from '../../types';
|
|
19
21
|
|
|
20
22
|
export type PlankControlHandler = (event: DeckAction.PartAdjustment) => void;
|
|
21
23
|
|
|
22
24
|
export type PlankCapabilities = {
|
|
23
25
|
incrementStart?: boolean;
|
|
24
26
|
incrementEnd?: boolean;
|
|
27
|
+
deck?: boolean;
|
|
25
28
|
solo?: boolean;
|
|
29
|
+
companion?: boolean;
|
|
26
30
|
};
|
|
27
31
|
|
|
28
32
|
export type PlankControlsProps = Omit<ButtonGroupProps, 'onClick'> & {
|
|
@@ -50,16 +54,46 @@ const PlankControl = ({ icon, label, ...props }: Omit<ButtonProps, 'children'> &
|
|
|
50
54
|
);
|
|
51
55
|
};
|
|
52
56
|
|
|
57
|
+
const plankControlSpacing = 'pli-2 plb-3';
|
|
58
|
+
|
|
59
|
+
type PlankComplimentControlsProps = {
|
|
60
|
+
primary?: string;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export const PlankCompanionControls = forwardRef<HTMLDivElement, PlankComplimentControlsProps>(
|
|
64
|
+
({ primary }, forwardedRef) => {
|
|
65
|
+
const { t } = useTranslation(DECK_PLUGIN);
|
|
66
|
+
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
67
|
+
const handleCloseCompanion = useCallback(() => {
|
|
68
|
+
invariant(primary);
|
|
69
|
+
return dispatch(createIntent(DeckAction.ChangeCompanion, { primary, companion: null }));
|
|
70
|
+
}, []);
|
|
71
|
+
return (
|
|
72
|
+
<div ref={forwardedRef} className='contents app-no-drag'>
|
|
73
|
+
<PlankControl
|
|
74
|
+
label={t('close companion label')}
|
|
75
|
+
variant='ghost'
|
|
76
|
+
// icon='ph--minus--regular'
|
|
77
|
+
icon='ph--caret-left--regular'
|
|
78
|
+
onClick={handleCloseCompanion}
|
|
79
|
+
classNames={plankControlSpacing}
|
|
80
|
+
/>
|
|
81
|
+
</div>
|
|
82
|
+
);
|
|
83
|
+
},
|
|
84
|
+
);
|
|
85
|
+
|
|
53
86
|
// TODO(wittjosiah): Duplicate of stack LayoutControls?
|
|
54
87
|
// Translations were to be duplicated between packages.
|
|
55
88
|
// NOTE(thure): Pinning & unpinning are disabled indefinitely.
|
|
56
89
|
export const PlankControls = forwardRef<HTMLDivElement, PlankControlsProps>(
|
|
57
90
|
(
|
|
58
|
-
{
|
|
91
|
+
{ children, classNames, variant = 'default', capabilities, isSolo, pin, close = false, onClick, ...props },
|
|
59
92
|
forwardedRef,
|
|
60
93
|
) => {
|
|
61
94
|
const { t } = useTranslation(DECK_PLUGIN);
|
|
62
|
-
const buttonClassNames =
|
|
95
|
+
const buttonClassNames =
|
|
96
|
+
variant === 'hide-disabled' ? `disabled:hidden ${plankControlSpacing}` : plankControlSpacing;
|
|
63
97
|
|
|
64
98
|
return (
|
|
65
99
|
<ButtonGroup {...props} classNames={['app-no-drag', classNames]} ref={forwardedRef}>
|
|
@@ -73,31 +107,33 @@ export const PlankControls = forwardRef<HTMLDivElement, PlankControlsProps>(
|
|
|
73
107
|
/>
|
|
74
108
|
)} */}
|
|
75
109
|
|
|
76
|
-
{
|
|
77
|
-
<PlankControl
|
|
78
|
-
label={isSolo ? t('show deck plank label') : t('show solo plank label')}
|
|
79
|
-
classNames={buttonClassNames}
|
|
80
|
-
onClick={() => onClick?.('solo')}
|
|
81
|
-
icon={isSolo ? 'ph--corners-in--regular' : 'ph--corners-out--regular'}
|
|
82
|
-
/>
|
|
83
|
-
)}
|
|
84
|
-
|
|
85
|
-
{!isSolo && can.solo && (
|
|
110
|
+
{capabilities.deck && capabilities.solo && (
|
|
86
111
|
<>
|
|
87
112
|
<PlankControl
|
|
88
|
-
label={t('
|
|
89
|
-
disabled={!can.incrementStart}
|
|
113
|
+
label={isSolo ? t('show deck plank label') : t('show solo plank label')}
|
|
90
114
|
classNames={buttonClassNames}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
/>
|
|
94
|
-
<PlankControl
|
|
95
|
-
label={t('increment end label')}
|
|
96
|
-
disabled={!can.incrementEnd}
|
|
97
|
-
classNames={buttonClassNames}
|
|
98
|
-
onClick={() => onClick?.('increment-end')}
|
|
99
|
-
icon='ph--caret-right--regular'
|
|
115
|
+
icon={isSolo ? 'ph--corners-in--regular' : 'ph--corners-out--regular'}
|
|
116
|
+
onClick={() => onClick?.('solo')}
|
|
100
117
|
/>
|
|
118
|
+
|
|
119
|
+
{!isSolo && (
|
|
120
|
+
<>
|
|
121
|
+
<PlankControl
|
|
122
|
+
label={t('increment start label')}
|
|
123
|
+
disabled={!capabilities.incrementStart}
|
|
124
|
+
classNames={buttonClassNames}
|
|
125
|
+
icon='ph--caret-left--regular'
|
|
126
|
+
onClick={() => onClick?.('increment-start')}
|
|
127
|
+
/>
|
|
128
|
+
<PlankControl
|
|
129
|
+
label={t('increment end label')}
|
|
130
|
+
disabled={!capabilities.incrementEnd}
|
|
131
|
+
classNames={buttonClassNames}
|
|
132
|
+
icon='ph--caret-right--regular'
|
|
133
|
+
onClick={() => onClick?.('increment-end')}
|
|
134
|
+
/>
|
|
135
|
+
</>
|
|
136
|
+
)}
|
|
101
137
|
</>
|
|
102
138
|
)}
|
|
103
139
|
|
|
@@ -105,8 +141,8 @@ export const PlankControls = forwardRef<HTMLDivElement, PlankControlsProps>(
|
|
|
105
141
|
<PlankControl
|
|
106
142
|
label={t('pin end label')}
|
|
107
143
|
classNames={buttonClassNames}
|
|
108
|
-
onClick={() => onClick?.('pin-end')}
|
|
109
144
|
icon='ph--caret-line-right--regular'
|
|
145
|
+
onClick={() => onClick?.('pin-end')}
|
|
110
146
|
/>
|
|
111
147
|
)} */}
|
|
112
148
|
|
|
@@ -114,7 +150,6 @@ export const PlankControls = forwardRef<HTMLDivElement, PlankControlsProps>(
|
|
|
114
150
|
<PlankControl
|
|
115
151
|
label={t(`${typeof close === 'string' ? 'minify' : 'close'} label`)}
|
|
116
152
|
classNames={buttonClassNames}
|
|
117
|
-
onClick={() => onClick?.('close')}
|
|
118
153
|
data-testid='plankHeading.close'
|
|
119
154
|
icon={
|
|
120
155
|
close === 'minify-start'
|
|
@@ -123,6 +158,17 @@ export const PlankControls = forwardRef<HTMLDivElement, PlankControlsProps>(
|
|
|
123
158
|
? 'ph--caret-line-right--regular'
|
|
124
159
|
: 'ph--x--regular'
|
|
125
160
|
}
|
|
161
|
+
onClick={() => onClick?.('close')}
|
|
162
|
+
/>
|
|
163
|
+
)}
|
|
164
|
+
|
|
165
|
+
{capabilities.companion && (
|
|
166
|
+
<PlankControl
|
|
167
|
+
label={t('open companion label')}
|
|
168
|
+
classNames={buttonClassNames}
|
|
169
|
+
data-testid='plankHeading.companion'
|
|
170
|
+
icon='ph--square-split-horizontal--regular'
|
|
171
|
+
onClick={() => onClick?.('companion')}
|
|
126
172
|
/>
|
|
127
173
|
)}
|
|
128
174
|
{children}
|
|
@@ -8,7 +8,7 @@ import { type Node } from '@dxos/plugin-graph';
|
|
|
8
8
|
import { useTranslation } from '@dxos/react-ui';
|
|
9
9
|
import { descriptionText, mx } from '@dxos/react-ui-theme';
|
|
10
10
|
|
|
11
|
-
import {
|
|
11
|
+
import { PlankHeading, type PlankHeadingProps } from './PlankHeading';
|
|
12
12
|
import { PlankLoading } from './PlankLoading';
|
|
13
13
|
import { DECK_PLUGIN } from '../../meta';
|
|
14
14
|
|
|
@@ -38,7 +38,7 @@ export const PlankError = ({
|
|
|
38
38
|
error,
|
|
39
39
|
}: {
|
|
40
40
|
id: string;
|
|
41
|
-
part:
|
|
41
|
+
part: PlankHeadingProps['part'];
|
|
42
42
|
node?: Node;
|
|
43
43
|
error?: Error;
|
|
44
44
|
}) => {
|
|
@@ -48,7 +48,7 @@ export const PlankError = ({
|
|
|
48
48
|
}, []);
|
|
49
49
|
return (
|
|
50
50
|
<>
|
|
51
|
-
<
|
|
51
|
+
<PlankHeading id={id} part={part} node={node} pending={!timedOut} />
|
|
52
52
|
{timedOut ? <PlankContentError error={error} /> : <PlankLoading />}
|
|
53
53
|
</>
|
|
54
54
|
);
|