@dxos/plugin-deck 0.6.13 → 0.6.14-main.2b6a0f3
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/{chunk-YVHGFQQR.mjs → chunk-GVOGPULO.mjs} +1 -1
- package/dist/lib/browser/chunk-GVOGPULO.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +331 -264
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/meta.mjs +1 -1
- package/dist/types/src/DeckPlugin.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/ActiveNode.d.ts +1 -3
- package/dist/types/src/components/DeckLayout/ActiveNode.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/ComplementarySidebar.d.ts +2 -4
- package/dist/types/src/components/DeckLayout/ComplementarySidebar.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/DeckLayout.d.ts +3 -4
- package/dist/types/src/components/DeckLayout/DeckLayout.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/NodePlankHeading.d.ts +9 -7
- package/dist/types/src/components/DeckLayout/NodePlankHeading.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/Plank.d.ts +1 -1
- package/dist/types/src/components/DeckLayout/Plank.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/PlankError.d.ts +1 -2
- package/dist/types/src/components/DeckLayout/PlankError.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/Sidebar.d.ts +2 -3
- package/dist/types/src/components/DeckLayout/Sidebar.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/StatusBar.d.ts +3 -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/LayoutSettings.d.ts.map +1 -1
- package/dist/types/src/hooks/useNode.d.ts.map +1 -1
- package/dist/types/src/layout.d.ts.map +1 -1
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +5 -3
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types.d.ts +1 -1
- package/dist/types/src/types.d.ts.map +1 -1
- package/dist/types/src/util/overscroll.d.ts +1 -1
- package/dist/types/src/util/overscroll.d.ts.map +1 -1
- package/package.json +31 -29
- package/src/DeckPlugin.tsx +93 -71
- package/src/components/DeckLayout/ActiveNode.tsx +4 -1
- package/src/components/DeckLayout/ComplementarySidebar.tsx +70 -28
- package/src/components/DeckLayout/DeckLayout.tsx +64 -96
- package/src/components/DeckLayout/NodePlankHeading.tsx +130 -127
- package/src/components/DeckLayout/Plank.tsx +31 -22
- package/src/components/DeckLayout/PlankError.tsx +1 -9
- package/src/components/DeckLayout/Sidebar.tsx +6 -5
- package/src/components/DeckLayout/StatusBar.tsx +12 -3
- package/src/components/DeckLayout/Toast.tsx +3 -3
- package/src/components/LayoutSettings.tsx +5 -8
- package/src/hooks/useNode.ts +5 -1
- package/src/layout.ts +1 -0
- package/src/meta.ts +3 -1
- package/src/translations.ts +7 -3
- package/src/types.ts +1 -1
- package/src/util/overscroll.ts +5 -5
- package/dist/lib/browser/chunk-YVHGFQQR.mjs.map +0 -7
package/src/DeckPlugin.tsx
CHANGED
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import { batch, effect } from '@preact/signals-core';
|
|
5
|
+
import { batch } from '@preact/signals-core';
|
|
7
6
|
import { setAutoFreeze } from 'immer';
|
|
8
7
|
import React, { type PropsWithChildren } from 'react';
|
|
9
8
|
|
|
@@ -33,6 +32,7 @@ import {
|
|
|
33
32
|
} from '@dxos/app-framework';
|
|
34
33
|
import { type UnsubscribeCallback } from '@dxos/async';
|
|
35
34
|
import { create, getTypename, isReactiveObject } from '@dxos/echo-schema';
|
|
35
|
+
import { scheduledEffect } from '@dxos/echo-signals/core';
|
|
36
36
|
import { LocalStorageStore } from '@dxos/local-storage';
|
|
37
37
|
import { log } from '@dxos/log';
|
|
38
38
|
import { parseAttentionPlugin, type AttentionPluginProvides } from '@dxos/plugin-attention';
|
|
@@ -41,7 +41,6 @@ import { createExtension, type Node } from '@dxos/plugin-graph';
|
|
|
41
41
|
import { ObservabilityAction } from '@dxos/plugin-observability/meta';
|
|
42
42
|
import { fullyQualifiedId } from '@dxos/react-client/echo';
|
|
43
43
|
import { translations as deckTranslations } from '@dxos/react-ui-deck';
|
|
44
|
-
import { Mosaic } from '@dxos/react-ui-mosaic';
|
|
45
44
|
|
|
46
45
|
import {
|
|
47
46
|
DeckLayout,
|
|
@@ -71,7 +70,7 @@ const isSocket = !!(globalThis as any).__args;
|
|
|
71
70
|
// TODO(mjamesderocher): Can we get this directly from Socket?
|
|
72
71
|
const appScheme = 'composer://';
|
|
73
72
|
|
|
74
|
-
// TODO(burdon): Evolve into customizable prefs
|
|
73
|
+
// TODO(burdon): Evolve into customizable prefs.
|
|
75
74
|
const customSlots: DeckLayoutProps['slots'] = {
|
|
76
75
|
wallpaper: {
|
|
77
76
|
classNames:
|
|
@@ -112,7 +111,7 @@ export const DeckPlugin = ({
|
|
|
112
111
|
let handleNavigation: () => Promise<void> | undefined;
|
|
113
112
|
|
|
114
113
|
const settings = new LocalStorageStore<DeckSettingsProps>('dxos.org/settings/layout', {
|
|
115
|
-
|
|
114
|
+
showHints: false,
|
|
116
115
|
customSlots: false,
|
|
117
116
|
flatDeck: false,
|
|
118
117
|
enableNativeRedirect: false,
|
|
@@ -190,6 +189,28 @@ export const DeckPlugin = ({
|
|
|
190
189
|
}
|
|
191
190
|
};
|
|
192
191
|
|
|
192
|
+
/**
|
|
193
|
+
* Update the active state and ensure that attention is on an active element.
|
|
194
|
+
*/
|
|
195
|
+
const handleSetLocation = (next: LayoutParts) => {
|
|
196
|
+
if (attentionPlugin) {
|
|
197
|
+
const attended = attentionPlugin.provides.attention.attended;
|
|
198
|
+
const [attendedId] = Array.from(attended);
|
|
199
|
+
const ids = (layout.values.layoutMode === 'deck' ? next.main : next.solo)?.map(({ id }) => id) ?? [];
|
|
200
|
+
const isAttendedAvailable = !!attendedId && ids.includes(attendedId);
|
|
201
|
+
if (!isAttendedAvailable) {
|
|
202
|
+
// Allow new plank to render before focusing.
|
|
203
|
+
requestAnimationFrame(() => {
|
|
204
|
+
const nextAttended = layout.values.layoutMode === 'solo' ? next.solo?.[0].id : next.main?.[0]?.id;
|
|
205
|
+
const article = document.querySelector<HTMLElement>(`article[data-attendable-id="${nextAttended}"]`);
|
|
206
|
+
article?.focus();
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
location.values.active = next;
|
|
212
|
+
};
|
|
213
|
+
|
|
193
214
|
return {
|
|
194
215
|
meta,
|
|
195
216
|
ready: async (plugins) => {
|
|
@@ -198,16 +219,21 @@ export const DeckPlugin = ({
|
|
|
198
219
|
attentionPlugin = resolvePlugin(plugins, parseAttentionPlugin);
|
|
199
220
|
clientPlugin = resolvePlugin(plugins, parseClientPlugin);
|
|
200
221
|
|
|
201
|
-
// prettier-ignore
|
|
202
222
|
layout
|
|
203
223
|
.prop({ key: 'layoutMode', storageKey: 'layout-mode', type: LocalStorageStore.enum<LayoutMode>() })
|
|
204
224
|
.prop({ key: 'sidebarOpen', storageKey: 'sidebar-open', type: LocalStorageStore.bool() })
|
|
205
|
-
.prop({
|
|
225
|
+
.prop({
|
|
226
|
+
key: 'complementarySidebarOpen',
|
|
227
|
+
storageKey: 'complementary-sidebar-open',
|
|
228
|
+
type: LocalStorageStore.bool(),
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
deck.prop({
|
|
232
|
+
key: 'plankSizing',
|
|
233
|
+
storageKey: 'plank-sizing',
|
|
234
|
+
type: LocalStorageStore.json<Record<string, number>>(),
|
|
235
|
+
});
|
|
206
236
|
|
|
207
|
-
// prettier-ignore
|
|
208
|
-
deck.prop({ key: 'plankSizing', storageKey: 'plank-sizing', type: LocalStorageStore.json<Record<string, number>>() });
|
|
209
|
-
|
|
210
|
-
// prettier-ignore
|
|
211
237
|
location
|
|
212
238
|
.prop({ key: 'active', storageKey: 'active', type: LocalStorageStore.json<LayoutParts>() })
|
|
213
239
|
.prop({ key: 'closed', storageKey: 'closed', type: LocalStorageStore.json<string[]>() });
|
|
@@ -220,14 +246,17 @@ export const DeckPlugin = ({
|
|
|
220
246
|
}),
|
|
221
247
|
);
|
|
222
248
|
|
|
223
|
-
// prettier-ignore
|
|
224
249
|
settings
|
|
225
|
-
.prop({ key: '
|
|
250
|
+
.prop({ key: 'showHints', storageKey: 'show-hints', type: LocalStorageStore.bool() })
|
|
226
251
|
.prop({ key: 'customSlots', storageKey: 'customSlots', type: LocalStorageStore.bool() })
|
|
227
252
|
.prop({ key: 'flatDeck', storageKey: 'flatDeck', type: LocalStorageStore.bool() })
|
|
228
253
|
.prop({ key: 'enableNativeRedirect', storageKey: 'enable-native-redirect', type: LocalStorageStore.bool() })
|
|
229
254
|
.prop({ key: 'disableDeck', storageKey: 'disable-deck', type: LocalStorageStore.bool() }) // Deprecated.
|
|
230
|
-
.prop({
|
|
255
|
+
.prop({
|
|
256
|
+
key: 'newPlankPositioning',
|
|
257
|
+
storageKey: 'newPlankPositioning',
|
|
258
|
+
type: LocalStorageStore.enum<NewPlankPositioning>(),
|
|
259
|
+
})
|
|
231
260
|
.prop({ key: 'overscroll', storageKey: 'overscroll', type: LocalStorageStore.enum<Overscroll>() });
|
|
232
261
|
|
|
233
262
|
if (!isSocket && settings.values.enableNativeRedirect) {
|
|
@@ -237,7 +266,7 @@ export const DeckPlugin = ({
|
|
|
237
266
|
handleNavigation = async () => {
|
|
238
267
|
const pathname = window.location.pathname;
|
|
239
268
|
if (pathname === '/reset') {
|
|
240
|
-
|
|
269
|
+
handleSetLocation({ sidebar: [{ id: NAV_ID }] });
|
|
241
270
|
location.values.closed = [];
|
|
242
271
|
layout.values.layoutMode = 'solo';
|
|
243
272
|
window.location.pathname = '/';
|
|
@@ -250,7 +279,7 @@ export const DeckPlugin = ({
|
|
|
250
279
|
}
|
|
251
280
|
|
|
252
281
|
const startingLayout = removePart(location.values.active, 'solo');
|
|
253
|
-
|
|
282
|
+
handleSetLocation(mergeLayoutParts(layoutFromUri, startingLayout));
|
|
254
283
|
layout.values.layoutMode = 'solo';
|
|
255
284
|
};
|
|
256
285
|
|
|
@@ -258,23 +287,13 @@ export const DeckPlugin = ({
|
|
|
258
287
|
window.addEventListener('popstate', handleNavigation);
|
|
259
288
|
|
|
260
289
|
unsubscriptionCallbacks.push(
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
unsubscriptionCallbacks.push(
|
|
269
|
-
effect(() => {
|
|
270
|
-
const soloId = location.values.active.solo?.[0].id;
|
|
271
|
-
if (layout.values.layoutMode === 'solo' && soloId && layout.values.scrollIntoView !== soloId) {
|
|
272
|
-
void intentPlugin?.provides.intent.dispatch({
|
|
273
|
-
action: LayoutAction.SCROLL_INTO_VIEW,
|
|
274
|
-
data: { id: soloId },
|
|
275
|
-
});
|
|
276
|
-
}
|
|
277
|
-
}),
|
|
290
|
+
scheduledEffect(
|
|
291
|
+
() => ({ selectedPath: soloPartToUri(location.values.active) }),
|
|
292
|
+
({ selectedPath }) => {
|
|
293
|
+
// TODO(thure): In some browsers, this only preserves the most recent state change, even though this is not `history.replace`…
|
|
294
|
+
history.pushState(null, '', `/${selectedPath}${window.location.search}`);
|
|
295
|
+
},
|
|
296
|
+
),
|
|
278
297
|
);
|
|
279
298
|
|
|
280
299
|
layoutModeHistory.values.push(`${layout.values.layoutMode}`);
|
|
@@ -310,8 +329,7 @@ export const DeckPlugin = ({
|
|
|
310
329
|
},
|
|
311
330
|
properties: {
|
|
312
331
|
label: ['toggle fullscreen label', { ns: DECK_PLUGIN }],
|
|
313
|
-
icon:
|
|
314
|
-
iconSymbol: 'ph--arrows-out--regular',
|
|
332
|
+
icon: 'ph--arrows-out--regular',
|
|
315
333
|
keyBinding: {
|
|
316
334
|
macos: 'ctrl+meta+f',
|
|
317
335
|
windows: 'shift+ctrl+f',
|
|
@@ -329,31 +347,27 @@ export const DeckPlugin = ({
|
|
|
329
347
|
),
|
|
330
348
|
root: () => {
|
|
331
349
|
return (
|
|
332
|
-
<
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
}}
|
|
354
|
-
/>
|
|
355
|
-
<Mosaic.DragOverlay />
|
|
356
|
-
</Mosaic.Root>
|
|
350
|
+
<DeckLayout
|
|
351
|
+
layoutParts={location.values.active}
|
|
352
|
+
showHints={settings.values.showHints}
|
|
353
|
+
overscroll={settings.values.overscroll}
|
|
354
|
+
flatDeck={settings.values.flatDeck}
|
|
355
|
+
slots={settings.values.customSlots ? customSlots : undefined}
|
|
356
|
+
toasts={layout.values.toasts}
|
|
357
|
+
onDismissToast={(id) => {
|
|
358
|
+
const index = layout.values.toasts.findIndex((toast) => toast.id === id);
|
|
359
|
+
if (index !== -1) {
|
|
360
|
+
// Allow time for the toast to animate out.
|
|
361
|
+
// TODO(burdon): Factor out and unregister timeout.
|
|
362
|
+
setTimeout(() => {
|
|
363
|
+
if (layout.values.toasts[index].id === currentUndoId) {
|
|
364
|
+
currentUndoId = undefined;
|
|
365
|
+
}
|
|
366
|
+
layout.values.toasts.splice(index, 1);
|
|
367
|
+
}, 1_000);
|
|
368
|
+
}
|
|
369
|
+
}}
|
|
370
|
+
/>
|
|
357
371
|
);
|
|
358
372
|
},
|
|
359
373
|
surface: {
|
|
@@ -472,7 +486,7 @@ export const DeckPlugin = ({
|
|
|
472
486
|
}
|
|
473
487
|
});
|
|
474
488
|
|
|
475
|
-
|
|
489
|
+
handleSetLocation(newLayout);
|
|
476
490
|
});
|
|
477
491
|
|
|
478
492
|
const ids = openIds(location.values.active);
|
|
@@ -522,10 +536,12 @@ export const DeckPlugin = ({
|
|
|
522
536
|
const layoutEntry = { id: data.id };
|
|
523
537
|
const effectivePart = getEffectivePart(data.part, layout.values.layoutMode);
|
|
524
538
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
539
|
+
handleSetLocation(
|
|
540
|
+
openEntry(location.values.active, effectivePart, layoutEntry, {
|
|
541
|
+
positioning: data.positioning ?? settings.values.newPlankPositioning,
|
|
542
|
+
pivotId: data.pivotId,
|
|
543
|
+
}),
|
|
544
|
+
);
|
|
529
545
|
|
|
530
546
|
const intents = [];
|
|
531
547
|
if (data.scrollIntoView && layout.values.layoutMode === 'deck') {
|
|
@@ -561,7 +577,11 @@ export const DeckPlugin = ({
|
|
|
561
577
|
}
|
|
562
578
|
});
|
|
563
579
|
|
|
564
|
-
|
|
580
|
+
handleSetLocation(newLayout);
|
|
581
|
+
// TODO(wittjosiah): This needs to also set the closed state.
|
|
582
|
+
// The closed state should be the existing closed state plus the newly closed ids.
|
|
583
|
+
// The closed state should also be updated when opening entries to remove the id from closed.
|
|
584
|
+
// When SET is called the closed ids should also be calculated and set.
|
|
565
585
|
return { data: true };
|
|
566
586
|
});
|
|
567
587
|
}
|
|
@@ -570,7 +590,7 @@ export const DeckPlugin = ({
|
|
|
570
590
|
case NavigationAction.SET: {
|
|
571
591
|
return batch(() => {
|
|
572
592
|
if (isLayoutParts(intent.data?.activeParts)) {
|
|
573
|
-
|
|
593
|
+
handleSetLocation(intent.data!.activeParts);
|
|
574
594
|
}
|
|
575
595
|
return { data: true };
|
|
576
596
|
});
|
|
@@ -581,10 +601,12 @@ export const DeckPlugin = ({
|
|
|
581
601
|
if (isLayoutAdjustment(intent.data)) {
|
|
582
602
|
const adjustment = intent.data;
|
|
583
603
|
if (adjustment.type === 'increment-end' || adjustment.type === 'increment-start') {
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
604
|
+
handleSetLocation(
|
|
605
|
+
incrementPlank(location.values.active, {
|
|
606
|
+
type: adjustment.type,
|
|
607
|
+
layoutCoordinate: adjustment.layoutCoordinate,
|
|
608
|
+
}),
|
|
609
|
+
);
|
|
588
610
|
}
|
|
589
611
|
|
|
590
612
|
if (adjustment.type === 'solo') {
|
|
@@ -6,10 +6,13 @@ import React from 'react';
|
|
|
6
6
|
|
|
7
7
|
import { Surface } from '@dxos/app-framework';
|
|
8
8
|
import { useGraph } from '@dxos/plugin-graph';
|
|
9
|
+
import { useAttended } from '@dxos/react-ui-attention';
|
|
9
10
|
|
|
10
11
|
import { useNode, useNodeActionExpander } from '../../hooks';
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
// TODO(burdon): Factor out to effect in plugin set document title.
|
|
14
|
+
export const ActiveNode = () => {
|
|
15
|
+
const [id] = useAttended();
|
|
13
16
|
const { graph } = useGraph();
|
|
14
17
|
const activeNode = useNode(graph, id);
|
|
15
18
|
useNodeActionExpander(activeNode);
|
|
@@ -2,12 +2,18 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import React from 'react';
|
|
5
|
+
import React, { useMemo } from 'react';
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
type LayoutCoordinate,
|
|
9
|
+
NavigationAction,
|
|
10
|
+
SLUG_PATH_SEPARATOR,
|
|
11
|
+
Surface,
|
|
12
|
+
useIntentDispatcher,
|
|
13
|
+
} from '@dxos/app-framework';
|
|
8
14
|
import { useGraph } from '@dxos/plugin-graph';
|
|
9
15
|
import { Main } from '@dxos/react-ui';
|
|
10
|
-
import {
|
|
16
|
+
import { useAttended } from '@dxos/react-ui-attention';
|
|
11
17
|
import { deckGrid } from '@dxos/react-ui-deck';
|
|
12
18
|
import { mx } from '@dxos/react-ui-theme';
|
|
13
19
|
|
|
@@ -15,44 +21,80 @@ import { NodePlankHeading } from './NodePlankHeading';
|
|
|
15
21
|
import { PlankContentError } from './PlankError';
|
|
16
22
|
import { PlankLoading } from './PlankLoading';
|
|
17
23
|
import { useNode, useNodeActionExpander } from '../../hooks';
|
|
24
|
+
import { DECK_PLUGIN } from '../../meta';
|
|
18
25
|
import { useLayout } from '../LayoutContext';
|
|
19
26
|
|
|
20
27
|
export type ComplementarySidebarProps = {
|
|
21
|
-
|
|
22
|
-
layoutParts: LayoutParts;
|
|
28
|
+
panel?: string;
|
|
23
29
|
flatDeck?: boolean;
|
|
24
30
|
};
|
|
25
31
|
|
|
26
|
-
|
|
32
|
+
type Panel = { id: string; icon: string };
|
|
33
|
+
|
|
34
|
+
// TODO(burdon): Should be provided by plugins.
|
|
35
|
+
const panels: Panel[] = [
|
|
36
|
+
{ id: 'settings', icon: 'ph--gear--regular' },
|
|
37
|
+
{ id: 'comments', icon: 'ph--chat-text--regular' },
|
|
38
|
+
{ id: 'automation', icon: 'ph--atom--regular' },
|
|
39
|
+
{ id: 'debug', icon: 'ph--bug--regular' },
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
const getPanel = (id?: string): Panel['id'] => {
|
|
43
|
+
const panel = panels.find((p) => p.id === id) ?? panels[0];
|
|
44
|
+
return panel.id;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const ComplementarySidebar = ({ panel, flatDeck }: ComplementarySidebarProps) => {
|
|
27
48
|
const { popoverAnchorId } = useLayout();
|
|
49
|
+
const attended = useAttended();
|
|
50
|
+
const part = getPanel(panel);
|
|
51
|
+
const id = attended[0] ? `${attended[0]}${SLUG_PATH_SEPARATOR}${part}` : undefined;
|
|
28
52
|
const { graph } = useGraph();
|
|
29
53
|
const node = useNode(graph, id);
|
|
30
|
-
|
|
31
|
-
const complementaryAttrs = createAttendableAttributes(id?.split(SLUG_PATH_SEPARATOR)[0] ?? 'never');
|
|
32
|
-
|
|
54
|
+
const dispatch = useIntentDispatcher();
|
|
33
55
|
useNodeActionExpander(node);
|
|
34
56
|
|
|
57
|
+
const actions = useMemo(
|
|
58
|
+
() =>
|
|
59
|
+
panels.map(({ id, icon }) => ({
|
|
60
|
+
id: `complementary-${id}`,
|
|
61
|
+
data: () => {
|
|
62
|
+
void dispatch({ action: NavigationAction.OPEN, data: { activeParts: { complementary: id } } });
|
|
63
|
+
},
|
|
64
|
+
properties: {
|
|
65
|
+
label: [`open ${id} label`, { ns: DECK_PLUGIN }],
|
|
66
|
+
icon,
|
|
67
|
+
menuItemType: 'toggle',
|
|
68
|
+
isChecked: part === id,
|
|
69
|
+
},
|
|
70
|
+
})),
|
|
71
|
+
[part],
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
// TODO(wittjosiah): Ensure that id is always defined.
|
|
75
|
+
const coordinate: LayoutCoordinate = useMemo(() => ({ entryId: id ?? 'unknown', part: 'complementary' }), [id]);
|
|
76
|
+
|
|
35
77
|
return (
|
|
36
|
-
<Main.ComplementarySidebar
|
|
37
|
-
{
|
|
38
|
-
<
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
78
|
+
<Main.ComplementarySidebar>
|
|
79
|
+
<div role='none' className={mx(deckGrid, 'grid-cols-1 bs-full')}>
|
|
80
|
+
<NodePlankHeading
|
|
81
|
+
coordinate={coordinate}
|
|
82
|
+
node={node}
|
|
83
|
+
popoverAnchorId={popoverAnchorId}
|
|
84
|
+
flatDeck={flatDeck}
|
|
85
|
+
actions={actions}
|
|
86
|
+
/>
|
|
87
|
+
<div className='row-span-2 divide-y divide-separator'>
|
|
88
|
+
{node && (
|
|
89
|
+
<Surface
|
|
90
|
+
role={`complementary--${part}`}
|
|
91
|
+
data={{ subject: node.properties.object, popoverAnchorId }}
|
|
92
|
+
fallback={PlankContentError}
|
|
93
|
+
placeholder={<PlankLoading />}
|
|
94
|
+
/>
|
|
95
|
+
)}
|
|
54
96
|
</div>
|
|
55
|
-
|
|
97
|
+
</div>
|
|
56
98
|
</Main.ComplementarySidebar>
|
|
57
99
|
);
|
|
58
100
|
};
|