@dxos/plugin-deck 0.8.1-staging.5be625a → 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-K4KVSHNT.mjs → app-graph-builder-VYZ4IWI3.mjs} +3 -3
- package/dist/lib/browser/{check-app-scheme-6SS6I3RN.mjs → check-app-scheme-SEYECDHI.mjs} +2 -2
- package/dist/lib/browser/{chunk-RZLH5F56.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-MWUT66KV.mjs → chunk-FJBMNSUC.mjs} +547 -493
- 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-2WTHB3TG.mjs → chunk-NSATFAEE.mjs} +3 -3
- package/dist/lib/browser/{chunk-2WTHB3TG.mjs.map → chunk-NSATFAEE.mjs.map} +1 -1
- package/dist/lib/browser/{chunk-7X43JKZG.mjs → chunk-RJNCG4ND.mjs} +41 -45
- package/dist/lib/browser/chunk-RJNCG4ND.mjs.map +7 -0
- package/dist/lib/browser/{chunk-WCNPMAR4.mjs → chunk-XMCG42ID.mjs} +2 -3
- package/dist/lib/browser/chunk-XMCG42ID.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +12 -8
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/{intent-resolver-MEBOMCYI.mjs → intent-resolver-UDYKO2QW.mjs} +39 -78
- 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-USUAHDML.mjs → react-root-XLXN2VEW.mjs} +8 -10
- package/dist/lib/browser/react-root-XLXN2VEW.mjs.map +7 -0
- package/dist/lib/browser/{react-surface-TQG4YYES.mjs → react-surface-WNGMZL7I.mjs} +11 -10
- package/dist/lib/browser/react-surface-WNGMZL7I.mjs.map +7 -0
- package/dist/lib/browser/{settings-DYS3FFMN.mjs → settings-HMDGSBGO.mjs} +5 -4
- package/dist/lib/browser/settings-HMDGSBGO.mjs.map +7 -0
- package/dist/lib/browser/{state-DRRCGMU2.mjs → state-7TN26M42.mjs} +4 -4
- package/dist/lib/browser/{state-DRRCGMU2.mjs.map → state-7TN26M42.mjs.map} +2 -2
- package/dist/lib/browser/{tools-NDEUSO4R.mjs → tools-SC6QEN7R.mjs} +3 -3
- package/dist/lib/browser/types.mjs +12 -12
- package/dist/lib/browser/{url-handler-4BCN7AYC.mjs → url-handler-ODG4B6NX.mjs} +4 -4
- package/dist/types/src/DeckPlugin.d.ts.map +1 -1
- package/dist/types/src/capabilities/capabilities.d.ts +10 -12
- 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 +5 -5
- 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 +2 -0
- 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/{DeckLayout/NodePlankHeading.d.ts → Plank/PlankHeading.d.ts} +7 -6
- 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/translations.d.ts +3 -0
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types.d.ts +31 -60
- 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 +35 -7
- 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 +3 -3
- 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 +27 -16
- 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/{DeckLayout → Plank}/Plank.tsx +46 -37
- package/src/components/{DeckLayout → Plank}/PlankControls.tsx +40 -25
- package/src/components/{DeckLayout → Plank}/PlankError.tsx +3 -3
- package/src/components/{DeckLayout/NodePlankHeading.tsx → Plank/PlankHeading.tsx} +98 -59
- 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 +2 -2
- package/src/translations.ts +3 -0
- package/src/types.ts +59 -86
- 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-7X43JKZG.mjs.map +0 -7
- package/dist/lib/browser/chunk-MWUT66KV.mjs.map +0 -7
- package/dist/lib/browser/chunk-NSNAYFAX.mjs +0 -24
- package/dist/lib/browser/chunk-RZLH5F56.mjs.map +0 -7
- package/dist/lib/browser/chunk-WCNPMAR4.mjs.map +0 -7
- package/dist/lib/browser/intent-resolver-MEBOMCYI.mjs.map +0 -7
- package/dist/lib/browser/react-root-USUAHDML.mjs.map +0 -7
- package/dist/lib/browser/react-surface-TQG4YYES.mjs.map +0 -7
- package/dist/lib/browser/settings-DYS3FFMN.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.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/hooks/useNode.ts +0 -46
- /package/dist/lib/browser/{app-graph-builder-K4KVSHNT.mjs.map → app-graph-builder-VYZ4IWI3.mjs.map} +0 -0
- /package/dist/lib/browser/{check-app-scheme-6SS6I3RN.mjs.map → check-app-scheme-SEYECDHI.mjs.map} +0 -0
- /package/dist/lib/browser/{chunk-NSNAYFAX.mjs.map → chunk-B4LOJUWW.mjs.map} +0 -0
- /package/dist/lib/browser/{tools-NDEUSO4R.mjs.map → tools-SC6QEN7R.mjs.map} +0 -0
- /package/dist/lib/browser/{url-handler-4BCN7AYC.mjs.map → url-handler-ODG4B6NX.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
|
@@ -2,64 +2,61 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import React, { Fragment, memo, useCallback, useEffect, useMemo } from 'react';
|
|
5
|
+
import React, { Fragment, memo, useCallback, useEffect, useMemo, type MouseEvent } from 'react';
|
|
6
6
|
|
|
7
7
|
import { createIntent, LayoutAction, Surface, useAppGraph, useIntentDispatcher } from '@dxos/app-framework';
|
|
8
8
|
import { type Node } from '@dxos/plugin-graph';
|
|
9
|
-
import { Icon, Popover, toLocalizedString, useTranslation } from '@dxos/react-ui';
|
|
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
12
|
|
|
13
13
|
import { PlankCompanionControls, PlankControls } from './PlankControls';
|
|
14
|
+
import { parseEntryId } from '../../layout';
|
|
14
15
|
import { DECK_PLUGIN } from '../../meta';
|
|
15
|
-
import { DeckAction, type ResolvedPart
|
|
16
|
+
import { PLANK_COMPANION_TYPE, DeckAction, type ResolvedPart } from '../../types';
|
|
16
17
|
import { useBreakpoints } from '../../util';
|
|
17
18
|
import { soloInlinePadding } from '../fragments';
|
|
18
19
|
|
|
19
|
-
export type
|
|
20
|
+
export type PlankHeadingProps = {
|
|
20
21
|
id: string;
|
|
21
22
|
part: ResolvedPart;
|
|
22
23
|
node?: Node;
|
|
24
|
+
deckEnabled?: boolean;
|
|
23
25
|
canIncrementStart?: boolean;
|
|
24
26
|
canIncrementEnd?: boolean;
|
|
25
27
|
popoverAnchorId?: string;
|
|
28
|
+
primaryId?: string;
|
|
26
29
|
pending?: boolean;
|
|
27
|
-
actions?: StackItemSigilAction[];
|
|
28
30
|
companioned?: 'primary' | 'companion';
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
companions?: Node[];
|
|
32
|
+
actions?: StackItemSigilAction[];
|
|
31
33
|
};
|
|
32
34
|
|
|
33
|
-
export const
|
|
35
|
+
export const PlankHeading = memo(
|
|
34
36
|
({
|
|
35
37
|
id,
|
|
36
38
|
part,
|
|
37
39
|
node,
|
|
40
|
+
deckEnabled,
|
|
38
41
|
canIncrementStart,
|
|
39
42
|
canIncrementEnd,
|
|
40
43
|
popoverAnchorId,
|
|
44
|
+
primaryId,
|
|
41
45
|
pending,
|
|
42
|
-
actions = [],
|
|
43
46
|
companioned,
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}:
|
|
47
|
+
companions,
|
|
48
|
+
actions = [],
|
|
49
|
+
}: PlankHeadingProps) => {
|
|
47
50
|
const { t } = useTranslation(DECK_PLUGIN);
|
|
51
|
+
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
48
52
|
const { graph } = useAppGraph();
|
|
49
53
|
const breakpoint = useBreakpoints();
|
|
50
54
|
const icon = node?.properties?.icon ?? 'ph--placeholder--regular';
|
|
51
55
|
const label = pending
|
|
52
56
|
? t('pending heading')
|
|
53
|
-
: toLocalizedString(
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
? [`${surfaceVariant} plank heading`, node.properties.label[1]]
|
|
57
|
-
: ['companion plank heading fallback label', { ns: DECK_PLUGIN }]
|
|
58
|
-
: node?.properties?.label) ?? ['plank heading fallback label', { ns: DECK_PLUGIN }],
|
|
59
|
-
t,
|
|
60
|
-
);
|
|
61
|
-
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
62
|
-
const ActionRoot = node && popoverAnchorId === `dxos.org/ui/${DECK_PLUGIN}/${node.id}` ? Popover.Anchor : Fragment;
|
|
57
|
+
: toLocalizedString(node?.properties?.label ?? ['plank heading fallback label', { ns: DECK_PLUGIN }], t);
|
|
58
|
+
|
|
59
|
+
const isCompanionNode = node?.type === PLANK_COMPANION_TYPE;
|
|
63
60
|
|
|
64
61
|
useEffect(() => {
|
|
65
62
|
const frame = requestAnimationFrame(() => {
|
|
@@ -70,21 +67,29 @@ export const NodePlankHeading = memo(
|
|
|
70
67
|
return () => cancelAnimationFrame(frame);
|
|
71
68
|
}, [node]);
|
|
72
69
|
|
|
73
|
-
|
|
74
|
-
const attendableId = id.split(SLUG_PATH_SEPARATOR).at(0);
|
|
70
|
+
const attendableId = primaryId ?? id;
|
|
75
71
|
const capabilities = useMemo(
|
|
76
72
|
() => ({
|
|
73
|
+
deck: deckEnabled ?? true,
|
|
77
74
|
solo: breakpoint !== 'mobile' && (part === 'solo' || part === 'deck'),
|
|
78
75
|
incrementStart: canIncrementStart,
|
|
79
76
|
incrementEnd: canIncrementEnd,
|
|
77
|
+
companion: !isCompanionNode && companions && companions.length > 0,
|
|
80
78
|
}),
|
|
81
|
-
[breakpoint, part, canIncrementStart, canIncrementEnd],
|
|
79
|
+
[breakpoint, part, companions, canIncrementStart, canIncrementEnd, isCompanionNode, deckEnabled],
|
|
82
80
|
);
|
|
83
81
|
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
82
|
+
const { variant } = parseEntryId(id);
|
|
83
|
+
const sigilActions = useMemo(() => {
|
|
84
|
+
if (!node) {
|
|
85
|
+
return undefined;
|
|
86
|
+
} else if (variant) {
|
|
87
|
+
return [];
|
|
88
|
+
} else {
|
|
89
|
+
return [actions, graph.actions(node)].filter((a) => a.length > 0);
|
|
90
|
+
}
|
|
91
|
+
}, [actions, node, variant, graph]);
|
|
92
|
+
|
|
88
93
|
const handleAction = useCallback((action: StackItemSigilAction) => {
|
|
89
94
|
typeof action.data === 'function' && action.data?.({ node: action as Node, caller: DECK_PLUGIN });
|
|
90
95
|
}, []);
|
|
@@ -113,53 +118,87 @@ export const NodePlankHeading = memo(
|
|
|
113
118
|
[dispatch, id, part],
|
|
114
119
|
);
|
|
115
120
|
|
|
121
|
+
const ActionRoot = node && popoverAnchorId === `dxos.org/ui/${DECK_PLUGIN}/${node.id}` ? Popover.Anchor : Fragment;
|
|
122
|
+
|
|
123
|
+
const handleTabClick = useCallback(
|
|
124
|
+
(event: MouseEvent) => {
|
|
125
|
+
const target = (event.target as HTMLElement).closest('[data-id]') as HTMLElement | null;
|
|
126
|
+
const tabId = target?.dataset?.id;
|
|
127
|
+
if (primaryId && tabId) {
|
|
128
|
+
void dispatch(
|
|
129
|
+
createIntent(DeckAction.ChangeCompanion, {
|
|
130
|
+
primary: primaryId,
|
|
131
|
+
companion: tabId,
|
|
132
|
+
}),
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
[primaryId],
|
|
137
|
+
);
|
|
138
|
+
|
|
116
139
|
return (
|
|
117
140
|
<StackItem.Heading
|
|
118
141
|
classNames={[
|
|
119
|
-
'plb-1 border-be border-separator items-stretch gap-1 sticky inline-start-12 app-drag',
|
|
142
|
+
'plb-1 border-be border-separator items-stretch gap-1 sticky inline-start-12 app-drag min-is-0 layout-contain',
|
|
120
143
|
part === 'solo' ? soloInlinePadding : 'pli-1',
|
|
121
|
-
surfaceVariant && 'pis-3',
|
|
122
144
|
]}
|
|
123
145
|
>
|
|
124
|
-
{
|
|
125
|
-
<
|
|
126
|
-
{
|
|
127
|
-
<
|
|
146
|
+
{companions && isCompanionNode ? (
|
|
147
|
+
<div role='none' className='flex-1 min-is-0 overflow-x-auto scrollbar-thin flex gap-1'>
|
|
148
|
+
{companions.map(({ id, properties: { icon, label } }) => (
|
|
149
|
+
<IconButton
|
|
150
|
+
key={id}
|
|
151
|
+
data-id={id}
|
|
128
152
|
icon={icon}
|
|
129
|
-
|
|
153
|
+
iconOnly={node?.id !== id}
|
|
154
|
+
label={toLocalizedString(label, t)}
|
|
155
|
+
size={5}
|
|
156
|
+
variant={node?.id === id ? 'primary' : 'default'}
|
|
157
|
+
onClick={handleTabClick}
|
|
158
|
+
/>
|
|
159
|
+
))}
|
|
160
|
+
</div>
|
|
161
|
+
) : (
|
|
162
|
+
<>
|
|
163
|
+
<ActionRoot>
|
|
164
|
+
{node && sigilActions ? (
|
|
165
|
+
<StackItem.Sigil
|
|
166
|
+
icon={icon}
|
|
167
|
+
related={part === 'complementary'}
|
|
168
|
+
attendableId={attendableId}
|
|
169
|
+
triggerLabel={t('actions menu label')}
|
|
170
|
+
actions={sigilActions}
|
|
171
|
+
onAction={handleAction}
|
|
172
|
+
>
|
|
173
|
+
<Surface role='menu-footer' data={{ subject: node.data }} />
|
|
174
|
+
</StackItem.Sigil>
|
|
175
|
+
) : (
|
|
176
|
+
<StackItem.SigilButton>
|
|
177
|
+
<span className='sr-only'>{label}</span>
|
|
178
|
+
<Icon icon={icon} size={5} />
|
|
179
|
+
</StackItem.SigilButton>
|
|
180
|
+
)}
|
|
181
|
+
</ActionRoot>
|
|
182
|
+
<TextTooltip text={label} onlyWhenTruncating>
|
|
183
|
+
<StackItem.HeadingLabel
|
|
130
184
|
attendableId={attendableId}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
onAction={handleAction}
|
|
185
|
+
related={part === 'complementary'}
|
|
186
|
+
{...(pending && { classNames: 'text-description' })}
|
|
134
187
|
>
|
|
135
|
-
|
|
136
|
-
</StackItem.
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
<span className='sr-only'>{label}</span>
|
|
140
|
-
<Icon icon={icon} size={5} />
|
|
141
|
-
</StackItem.SigilButton>
|
|
142
|
-
)}
|
|
143
|
-
</ActionRoot>
|
|
188
|
+
{label}
|
|
189
|
+
</StackItem.HeadingLabel>
|
|
190
|
+
</TextTooltip>
|
|
191
|
+
</>
|
|
144
192
|
)}
|
|
145
|
-
<TextTooltip text={label} onlyWhenTruncating>
|
|
146
|
-
<StackItem.HeadingLabel
|
|
147
|
-
attendableId={attendableId}
|
|
148
|
-
related={part === 'complementary'}
|
|
149
|
-
{...(pending && { classNames: 'text-description' })}
|
|
150
|
-
>
|
|
151
|
-
{label}
|
|
152
|
-
</StackItem.HeadingLabel>
|
|
153
|
-
</TextTooltip>
|
|
154
193
|
{node && part !== 'complementary' && <Surface role='navbar-end' data={{ subject: node.data }} />}
|
|
155
194
|
{companioned === 'companion' ? (
|
|
156
|
-
<PlankCompanionControls primary={
|
|
195
|
+
<PlankCompanionControls primary={primaryId} />
|
|
157
196
|
) : (
|
|
158
197
|
<PlankControls
|
|
159
198
|
capabilities={capabilities}
|
|
160
199
|
isSolo={part === 'solo'}
|
|
161
|
-
onClick={handlePlankAction}
|
|
162
200
|
close={part === 'complementary' ? 'minify-end' : true}
|
|
201
|
+
onClick={handlePlankAction}
|
|
163
202
|
/>
|
|
164
203
|
)}
|
|
165
204
|
</StackItem.Heading>
|
|
@@ -3,83 +3,85 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import React, {
|
|
6
|
+
Fragment,
|
|
7
|
+
type MouseEvent,
|
|
6
8
|
type PropsWithChildren,
|
|
7
9
|
useCallback,
|
|
8
10
|
useEffect,
|
|
9
11
|
useMemo,
|
|
10
12
|
useState,
|
|
11
|
-
type MouseEvent,
|
|
12
|
-
Fragment,
|
|
13
13
|
} from 'react';
|
|
14
14
|
|
|
15
15
|
import {
|
|
16
|
-
createIntent,
|
|
17
16
|
LayoutAction,
|
|
18
17
|
Surface,
|
|
18
|
+
createIntent,
|
|
19
19
|
useAppGraph,
|
|
20
|
-
useCapabilities,
|
|
21
20
|
useCapability,
|
|
22
21
|
useIntentDispatcher,
|
|
23
22
|
} from '@dxos/app-framework';
|
|
24
|
-
import {
|
|
25
|
-
|
|
26
|
-
useTranslation,
|
|
27
|
-
toLocalizedString,
|
|
28
|
-
IconButton,
|
|
29
|
-
ScrollArea as NaturalScrollArea,
|
|
30
|
-
type Label,
|
|
31
|
-
} from '@dxos/react-ui';
|
|
32
|
-
import { useAttended } from '@dxos/react-ui-attention';
|
|
23
|
+
import { type Node } from '@dxos/plugin-graph';
|
|
24
|
+
import { Main, useTranslation, toLocalizedString, IconButton, type Label } from '@dxos/react-ui';
|
|
33
25
|
import { Tabs } from '@dxos/react-ui-tabs';
|
|
34
|
-
import { byPosition } from '@dxos/util';
|
|
26
|
+
import { byPosition, type Position } from '@dxos/util';
|
|
35
27
|
|
|
36
|
-
import { PlankContentError } from './PlankError';
|
|
37
|
-
import { PlankLoading } from './PlankLoading';
|
|
38
28
|
import { ToggleComplementarySidebarButton } from './SidebarButton';
|
|
39
29
|
import { DeckCapabilities } from '../../capabilities';
|
|
40
|
-
import { useNode } from '../../hooks';
|
|
41
30
|
import { DECK_PLUGIN } from '../../meta';
|
|
42
|
-
import {
|
|
31
|
+
import { ATTENDABLE_PATH_SEPARATOR, DECK_COMPANION_TYPE } from '../../types';
|
|
43
32
|
import { layoutAppliesTopbar, useBreakpoints, useHoistStatusbar } from '../../util';
|
|
33
|
+
import { PlankContentError, PlankLoading } from '../Plank';
|
|
34
|
+
|
|
35
|
+
const label = ['complementary sidebar title', { ns: DECK_PLUGIN }] satisfies Label;
|
|
36
|
+
|
|
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
|
+
};
|
|
44
59
|
|
|
45
60
|
export type ComplementarySidebarProps = {
|
|
46
61
|
current?: string;
|
|
47
62
|
};
|
|
48
63
|
|
|
49
|
-
const label = ['complementary sidebar title', { ns: DECK_PLUGIN }] satisfies Label;
|
|
50
|
-
|
|
51
64
|
export const ComplementarySidebar = ({ current }: ComplementarySidebarProps) => {
|
|
52
65
|
const { t } = useTranslation(DECK_PLUGIN);
|
|
53
66
|
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
54
67
|
const layout = useCapability(DeckCapabilities.MutableDeckState);
|
|
55
|
-
const attended = useAttended();
|
|
56
|
-
const { graph } = useAppGraph();
|
|
57
|
-
const node = useNode(graph, attended[0]);
|
|
58
68
|
const breakpoint = useBreakpoints();
|
|
59
69
|
const topbar = layoutAppliesTopbar(breakpoint);
|
|
60
70
|
const hoistStatusbar = useHoistStatusbar(breakpoint);
|
|
61
71
|
|
|
62
|
-
const
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
return true;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return panel.filter(node);
|
|
70
|
-
})
|
|
71
|
-
.toSorted(byPosition);
|
|
72
|
-
const activePanelId = availablePanels.find((panel) => panel.id === current)?.id ?? availablePanels[0]?.id;
|
|
73
|
-
const [internalValue, setInternalValue] = useState(activePanelId);
|
|
72
|
+
const companions = useDeckCompanions();
|
|
73
|
+
const activeCompanion = companions.find((companion) => getCompanionId(companion.id) === current) ?? companions.at(0);
|
|
74
|
+
const activeId = getCompanionId(activeCompanion?.id ?? 'never');
|
|
75
|
+
const [internalValue, setInternalValue] = useState(activeId);
|
|
74
76
|
|
|
75
77
|
useEffect(() => {
|
|
76
|
-
setInternalValue(
|
|
77
|
-
}, [
|
|
78
|
+
setInternalValue(activeId);
|
|
79
|
+
}, [activeId]);
|
|
78
80
|
|
|
79
81
|
const handleTabClick = useCallback(
|
|
80
82
|
(event: MouseEvent) => {
|
|
81
83
|
const nextValue = event.currentTarget.getAttribute('data-value') as string;
|
|
82
|
-
if (nextValue ===
|
|
84
|
+
if (nextValue === activeId) {
|
|
83
85
|
layout.complementarySidebarState = layout.complementarySidebarState === 'expanded' ? 'collapsed' : 'expanded';
|
|
84
86
|
} else {
|
|
85
87
|
setInternalValue(nextValue);
|
|
@@ -87,21 +89,18 @@ export const ComplementarySidebar = ({ current }: ComplementarySidebarProps) =>
|
|
|
87
89
|
void dispatch(createIntent(LayoutAction.UpdateComplementary, { part: 'complementary', subject: nextValue }));
|
|
88
90
|
}
|
|
89
91
|
},
|
|
90
|
-
[layout,
|
|
92
|
+
[layout, activeId, dispatch],
|
|
91
93
|
);
|
|
92
94
|
|
|
93
95
|
const data = useMemo(
|
|
94
96
|
() =>
|
|
95
|
-
|
|
96
|
-
id:
|
|
97
|
-
subject:
|
|
98
|
-
workspace: layout.activeDeck,
|
|
99
|
-
popoverAnchorId: layout.popoverAnchorId,
|
|
97
|
+
activeCompanion && {
|
|
98
|
+
id: activeCompanion.id,
|
|
99
|
+
subject: activeCompanion.data,
|
|
100
100
|
},
|
|
101
|
-
[
|
|
101
|
+
[activeCompanion?.id, activeCompanion?.data],
|
|
102
102
|
);
|
|
103
103
|
|
|
104
|
-
// TODO(burdon): Scroll area should be controlled by surface.
|
|
105
104
|
return (
|
|
106
105
|
<Main.ComplementarySidebar
|
|
107
106
|
label={label}
|
|
@@ -110,29 +109,23 @@ export const ComplementarySidebar = ({ current }: ComplementarySidebarProps) =>
|
|
|
110
109
|
hoistStatusbar && 'block-end-[--statusbar-size]',
|
|
111
110
|
]}
|
|
112
111
|
>
|
|
113
|
-
<Tabs.Root
|
|
114
|
-
orientation='vertical'
|
|
115
|
-
verticalVariant='stateless'
|
|
116
|
-
value={internalValue}
|
|
117
|
-
attendableId={attended[0]}
|
|
118
|
-
classNames='contents'
|
|
119
|
-
>
|
|
112
|
+
<Tabs.Root orientation='vertical' verticalVariant='stateless' value={internalValue} classNames='contents'>
|
|
120
113
|
<div
|
|
121
114
|
role='none'
|
|
122
115
|
className='absolute z-[1] inset-block-0 inline-end-0 !is-[--r0-size] pbs-[env(safe-area-inset-top)] pbe-[env(safe-area-inset-bottom)] border-is border-separator grid grid-cols-1 grid-rows-[1fr_min-content] bg-baseSurface contain-layout app-drag'
|
|
123
116
|
>
|
|
124
117
|
<Tabs.Tablist classNames='grid grid-cols-1 auto-rows-[--rail-action] p-1 gap-1 !overflow-y-auto'>
|
|
125
|
-
{
|
|
126
|
-
<Tabs.Tab key={
|
|
118
|
+
{companions.map((companion) => (
|
|
119
|
+
<Tabs.Tab key={getCompanionId(companion.id)} value={getCompanionId(companion.id)} asChild>
|
|
127
120
|
<IconButton
|
|
128
|
-
label={toLocalizedString(
|
|
129
|
-
icon={
|
|
121
|
+
label={toLocalizedString(companion.properties.label, t)}
|
|
122
|
+
icon={companion.properties.icon}
|
|
130
123
|
size={5}
|
|
131
124
|
iconOnly
|
|
132
125
|
tooltipSide='left'
|
|
133
|
-
data-value={
|
|
126
|
+
data-value={getCompanionId(companion.id)}
|
|
134
127
|
variant={
|
|
135
|
-
|
|
128
|
+
activeId === getCompanionId(companion.id)
|
|
136
129
|
? layout.complementarySidebarState === 'expanded'
|
|
137
130
|
? 'primary'
|
|
138
131
|
: 'default'
|
|
@@ -152,16 +145,16 @@ export const ComplementarySidebar = ({ current }: ComplementarySidebarProps) =>
|
|
|
152
145
|
<ToggleComplementarySidebarButton />
|
|
153
146
|
</div>
|
|
154
147
|
</div>
|
|
155
|
-
{
|
|
148
|
+
{companions.map((companion) => (
|
|
156
149
|
<Tabs.Tabpanel
|
|
157
|
-
key={
|
|
158
|
-
value={
|
|
150
|
+
key={getCompanionId(companion.id)}
|
|
151
|
+
value={getCompanionId(companion.id)}
|
|
159
152
|
classNames='absolute data-[state="inactive"]:-z-[1] inset-block-0 inline-start-0 is-[calc(100%-var(--r0-size))] lg:is-[--r1-size] grid grid-cols-1 grid-rows-[var(--rail-size)_1fr_min-content] pbs-[env(safe-area-inset-top)]'
|
|
160
153
|
{...(layout.complementarySidebarState !== 'expanded' && { inert: 'true' })}
|
|
161
154
|
>
|
|
162
155
|
<ComplementarySidebarPanel
|
|
163
|
-
|
|
164
|
-
|
|
156
|
+
companion={companion}
|
|
157
|
+
activeId={activeId}
|
|
165
158
|
data={data}
|
|
166
159
|
hoistStatusbar={hoistStatusbar}
|
|
167
160
|
/>
|
|
@@ -173,45 +166,36 @@ export const ComplementarySidebar = ({ current }: ComplementarySidebarProps) =>
|
|
|
173
166
|
};
|
|
174
167
|
|
|
175
168
|
type ComplementarySidebarPanelProps = {
|
|
176
|
-
|
|
177
|
-
|
|
169
|
+
companion: DeckCompanion;
|
|
170
|
+
activeId: string;
|
|
178
171
|
data?: {
|
|
179
172
|
id: string;
|
|
180
173
|
subject: any;
|
|
181
|
-
workspace: string;
|
|
182
|
-
popoverAnchorId?: string;
|
|
183
174
|
};
|
|
184
175
|
hoistStatusbar: boolean;
|
|
185
176
|
};
|
|
186
177
|
|
|
187
178
|
const ScrollArea = ({ children }: PropsWithChildren) => {
|
|
188
|
-
return
|
|
189
|
-
<NaturalScrollArea.Root>
|
|
190
|
-
<NaturalScrollArea.Viewport>{children}</NaturalScrollArea.Viewport>
|
|
191
|
-
<NaturalScrollArea.Scrollbar orientation='vertical'>
|
|
192
|
-
<NaturalScrollArea.Thumb />
|
|
193
|
-
</NaturalScrollArea.Scrollbar>
|
|
194
|
-
</NaturalScrollArea.Root>
|
|
195
|
-
);
|
|
179
|
+
return <div className='flex flex-col grow overflow-x-hidden overflow-y-auto scrollbar-thin'>{children}</div>;
|
|
196
180
|
};
|
|
197
181
|
|
|
198
|
-
const ComplementarySidebarPanel = ({
|
|
182
|
+
const ComplementarySidebarPanel = ({ companion, activeId, data, hoistStatusbar }: ComplementarySidebarPanelProps) => {
|
|
199
183
|
const { t } = useTranslation(DECK_PLUGIN);
|
|
200
184
|
|
|
201
|
-
if (
|
|
185
|
+
if (getCompanionId(companion.id) !== activeId && !data) {
|
|
202
186
|
return null;
|
|
203
187
|
}
|
|
204
188
|
|
|
205
|
-
const Wrapper =
|
|
189
|
+
const Wrapper = companion.properties.fixed ? Fragment : ScrollArea;
|
|
206
190
|
|
|
207
191
|
return (
|
|
208
192
|
<>
|
|
209
193
|
<h2 className='flex items-center pli-2 border-separator border-be font-medium'>
|
|
210
|
-
{toLocalizedString(
|
|
194
|
+
{toLocalizedString(companion.properties.label, t)}
|
|
211
195
|
</h2>
|
|
212
196
|
<Wrapper>
|
|
213
197
|
<Surface
|
|
214
|
-
role={`
|
|
198
|
+
role={`deck-companion--${getCompanionId(companion.id)}`}
|
|
215
199
|
data={data}
|
|
216
200
|
fallback={PlankContentError}
|
|
217
201
|
placeholder={<PlankLoading />}
|
package/src/components/index.ts
CHANGED
package/src/events.ts
CHANGED
|
@@ -7,6 +7,5 @@ import { Events } from '@dxos/app-framework';
|
|
|
7
7
|
import { DECK_PLUGIN } from './meta';
|
|
8
8
|
|
|
9
9
|
export namespace DeckEvents {
|
|
10
|
-
export const SetupComplementaryPanels = Events.createStateEvent(`${DECK_PLUGIN}/setup-complementary-panels`);
|
|
11
10
|
export const StateReady = Events.createStateEvent(`${DECK_PLUGIN}/state-ready`);
|
|
12
11
|
}
|
package/src/hooks/index.ts
CHANGED
package/src/index.ts
CHANGED
package/src/layout.ts
CHANGED
|
@@ -4,12 +4,29 @@
|
|
|
4
4
|
|
|
5
5
|
import { produce } from 'immer';
|
|
6
6
|
|
|
7
|
+
import { ATTENDABLE_PATH_SEPARATOR } from '@dxos/react-ui-attention';
|
|
8
|
+
|
|
7
9
|
import { type DeckAction, type NewPlankPositioning } from './types';
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
export const createEntryId = (entryId: string, variant?: string) =>
|
|
12
|
+
variant ? `${entryId}${ATTENDABLE_PATH_SEPARATOR}${variant}` : entryId;
|
|
13
|
+
|
|
14
|
+
export const parseEntryId = (entryId: string) => {
|
|
15
|
+
const [id, variant] = entryId.split(ATTENDABLE_PATH_SEPARATOR);
|
|
16
|
+
return { id, variant };
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
type OpenLayoutEntryOptions = {
|
|
20
|
+
key?: string;
|
|
21
|
+
positioning?: NewPlankPositioning;
|
|
22
|
+
pivotId?: string;
|
|
23
|
+
variant?: string;
|
|
24
|
+
};
|
|
10
25
|
|
|
11
|
-
export const openEntry = (deck: string[],
|
|
26
|
+
export const openEntry = (deck: string[], _entryId: string, options?: OpenLayoutEntryOptions): string[] => {
|
|
12
27
|
return produce(deck, (draft) => {
|
|
28
|
+
const entryId = createEntryId(_entryId, options?.variant);
|
|
29
|
+
|
|
13
30
|
// Check that the entry is not already in the part
|
|
14
31
|
if (draft.find((id) => id === entryId)) {
|
|
15
32
|
return;
|
package/src/meta.ts
CHANGED
package/src/translations.ts
CHANGED
|
@@ -47,11 +47,14 @@ export default [
|
|
|
47
47
|
'show solo plank label': 'Maximize',
|
|
48
48
|
'close label': 'Close',
|
|
49
49
|
'minify label': 'Minify',
|
|
50
|
+
'open companion label': 'Open companion',
|
|
51
|
+
'close companion label': 'Close companion',
|
|
50
52
|
'settings overscroll label': 'Plank scrolling',
|
|
51
53
|
'select overscroll placeholder': 'Select plank scrolling behavior',
|
|
52
54
|
'settings overscroll centering label': 'Centering',
|
|
53
55
|
'settings overscroll none label': 'None',
|
|
54
56
|
'settings enable statusbar label': 'Show status bar',
|
|
57
|
+
'settings enable deck label': 'Enable Deck',
|
|
55
58
|
'close current label': 'Close current plank',
|
|
56
59
|
'close others label': 'Close other planks',
|
|
57
60
|
'close all label': 'Close all planks',
|