@dxos/plugin-deck 0.6.13 → 0.6.14-main.1366248

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.
Files changed (57) hide show
  1. package/dist/lib/browser/{chunk-YVHGFQQR.mjs → chunk-GVOGPULO.mjs} +1 -1
  2. package/dist/lib/browser/chunk-GVOGPULO.mjs.map +7 -0
  3. package/dist/lib/browser/chunk-NIRHDTX4.mjs +17 -0
  4. package/dist/lib/browser/chunk-NIRHDTX4.mjs.map +7 -0
  5. package/dist/lib/browser/index.mjs +334 -314
  6. package/dist/lib/browser/index.mjs.map +4 -4
  7. package/dist/lib/browser/meta.json +1 -1
  8. package/dist/lib/browser/meta.mjs +1 -1
  9. package/dist/lib/browser/types.mjs +11 -0
  10. package/dist/lib/browser/types.mjs.map +7 -0
  11. package/dist/types/src/DeckPlugin.d.ts.map +1 -1
  12. package/dist/types/src/components/DeckLayout/ActiveNode.d.ts +1 -3
  13. package/dist/types/src/components/DeckLayout/ActiveNode.d.ts.map +1 -1
  14. package/dist/types/src/components/DeckLayout/ComplementarySidebar.d.ts +4 -4
  15. package/dist/types/src/components/DeckLayout/ComplementarySidebar.d.ts.map +1 -1
  16. package/dist/types/src/components/DeckLayout/DeckLayout.d.ts +5 -5
  17. package/dist/types/src/components/DeckLayout/DeckLayout.d.ts.map +1 -1
  18. package/dist/types/src/components/DeckLayout/NodePlankHeading.d.ts +9 -7
  19. package/dist/types/src/components/DeckLayout/NodePlankHeading.d.ts.map +1 -1
  20. package/dist/types/src/components/DeckLayout/Plank.d.ts +2 -2
  21. package/dist/types/src/components/DeckLayout/Plank.d.ts.map +1 -1
  22. package/dist/types/src/components/DeckLayout/PlankError.d.ts +1 -2
  23. package/dist/types/src/components/DeckLayout/PlankError.d.ts.map +1 -1
  24. package/dist/types/src/components/DeckLayout/Sidebar.d.ts +2 -3
  25. package/dist/types/src/components/DeckLayout/Sidebar.d.ts.map +1 -1
  26. package/dist/types/src/components/DeckLayout/StatusBar.d.ts +3 -1
  27. package/dist/types/src/components/DeckLayout/StatusBar.d.ts.map +1 -1
  28. package/dist/types/src/components/DeckLayout/Toast.d.ts.map +1 -1
  29. package/dist/types/src/components/LayoutSettings.d.ts.map +1 -1
  30. package/dist/types/src/hooks/useNode.d.ts.map +1 -1
  31. package/dist/types/src/layout.d.ts.map +1 -1
  32. package/dist/types/src/meta.d.ts.map +1 -1
  33. package/dist/types/src/translations.d.ts +1 -3
  34. package/dist/types/src/translations.d.ts.map +1 -1
  35. package/dist/types/src/types.d.ts +14 -2
  36. package/dist/types/src/types.d.ts.map +1 -1
  37. package/dist/types/src/util/overscroll.d.ts +1 -1
  38. package/dist/types/src/util/overscroll.d.ts.map +1 -1
  39. package/package.json +42 -33
  40. package/src/DeckPlugin.tsx +104 -80
  41. package/src/components/DeckLayout/ActiveNode.tsx +4 -1
  42. package/src/components/DeckLayout/ComplementarySidebar.tsx +59 -28
  43. package/src/components/DeckLayout/DeckLayout.tsx +67 -98
  44. package/src/components/DeckLayout/NodePlankHeading.tsx +130 -127
  45. package/src/components/DeckLayout/Plank.tsx +48 -32
  46. package/src/components/DeckLayout/PlankError.tsx +1 -9
  47. package/src/components/DeckLayout/Sidebar.tsx +7 -8
  48. package/src/components/DeckLayout/StatusBar.tsx +12 -3
  49. package/src/components/DeckLayout/Toast.tsx +3 -3
  50. package/src/components/LayoutSettings.tsx +17 -20
  51. package/src/hooks/useNode.ts +5 -1
  52. package/src/layout.ts +1 -0
  53. package/src/meta.ts +3 -1
  54. package/src/translations.ts +1 -3
  55. package/src/types.ts +16 -1
  56. package/src/util/overscroll.ts +5 -5
  57. package/dist/lib/browser/chunk-YVHGFQQR.mjs.map +0 -7
@@ -3,24 +3,17 @@
3
3
  //
4
4
 
5
5
  import { Sidebar as MenuIcon } from '@phosphor-icons/react';
6
- import React, { useCallback, useEffect, useMemo, useRef, useState, useLayoutEffect, type UIEvent } from 'react';
6
+ import { untracked } from '@preact/signals-core';
7
+ import React, { useCallback, useEffect, useMemo, useRef, type UIEvent } from 'react';
7
8
 
8
- import {
9
- SLUG_PATH_SEPARATOR,
10
- type Attention,
11
- type LayoutEntry,
12
- type LayoutParts,
13
- Surface,
14
- type Toast as ToastSchema,
15
- firstIdInPart,
16
- usePlugin,
17
- } from '@dxos/app-framework';
18
- import { Button, Dialog, Main, Popover, useTranslation } from '@dxos/react-ui';
9
+ import { type LayoutParts, Surface, type Toast as ToastSchema, firstIdInPart, usePlugin } from '@dxos/app-framework';
10
+ import { type AttentionPluginProvides } from '@dxos/plugin-attention';
11
+ import { Button, Dialog, Main, Popover, useOnTransition, useTranslation } from '@dxos/react-ui';
19
12
  import { Deck } from '@dxos/react-ui-deck';
20
- import { getSize } from '@dxos/react-ui-theme';
13
+ import { getSize, mainPaddingTransitions } from '@dxos/react-ui-theme';
21
14
 
22
15
  import { ActiveNode } from './ActiveNode';
23
- import { ComplementarySidebar } from './ComplementarySidebar';
16
+ import { ComplementarySidebar, type ComplementarySidebarProps } from './ComplementarySidebar';
24
17
  import { ContentEmpty } from './ContentEmpty';
25
18
  import { Fullscreen } from './Fullscreen';
26
19
  import { Plank } from './Plank';
@@ -35,25 +28,24 @@ import { useLayout } from '../LayoutContext';
35
28
 
36
29
  export type DeckLayoutProps = {
37
30
  layoutParts: LayoutParts;
38
- attention: Attention;
39
31
  toasts: ToastSchema[];
40
32
  flatDeck?: boolean;
41
33
  overscroll: Overscroll;
42
- showHintsFooter: boolean;
34
+ showHints: boolean;
43
35
  slots?: {
44
36
  wallpaper?: { classNames?: string };
45
37
  };
46
38
  onDismissToast: (id: string) => void;
47
- };
39
+ } & Pick<ComplementarySidebarProps, 'panels'>;
48
40
 
49
41
  export const DeckLayout = ({
50
42
  layoutParts,
51
- attention,
52
43
  toasts,
53
44
  flatDeck,
54
45
  overscroll,
55
- showHintsFooter,
46
+ showHints,
56
47
  slots,
48
+ panels,
57
49
  onDismissToast,
58
50
  }: DeckLayoutProps) => {
59
51
  const context = useLayout();
@@ -70,36 +62,44 @@ export const DeckLayout = ({
70
62
  } = context;
71
63
  const { t } = useTranslation(DECK_PLUGIN);
72
64
  const { plankSizing } = useDeckContext();
65
+ // NOTE: Not `useAttended` so that the layout component is not re-rendered when the attended list changes.
66
+ const attentionPlugin = usePlugin<AttentionPluginProvides>('dxos.org/plugin/attention');
73
67
  const searchPlugin = usePlugin('dxos.org/plugin/search');
74
68
  const fullScreenSlug = useMemo(() => firstIdInPart(layoutParts, 'fullScreen'), [layoutParts]);
75
69
 
76
- const [scrollLeft, setScrollLeft] = useState<number | null>(null);
77
- const deckRef = useRef<HTMLDivElement | null>(null);
78
- const restoreScrollRef = useRef<boolean>(false);
70
+ const scrollLeftRef = useRef<number | null>();
71
+ const deckRef = useRef<HTMLDivElement>(null);
72
+
73
+ // Ensure the first plank is attended when the deck is first rendered.
74
+ useEffect(() => {
75
+ const attended = untracked(() => attentionPlugin?.provides.attention.attended ?? []);
76
+ const firstId = layoutMode === 'solo' ? firstIdInPart(layoutParts, 'solo') : firstIdInPart(layoutParts, 'main');
77
+ if (attended.length === 0 && firstId) {
78
+ // TODO(wittjosiah): Focusing the type button is a workaround.
79
+ // If the plank is directly focused on first load the focus ring appears.
80
+ document.querySelector<HTMLElement>(`article[data-attendable-id="${firstId}"] button`)?.focus();
81
+ }
82
+ }, []);
79
83
 
80
84
  /**
81
85
  * Clear scroll restoration state if the window is resized
82
86
  */
83
87
  const handleResize = useCallback(() => {
84
- setScrollLeft(null);
88
+ scrollLeftRef.current = null;
85
89
  }, []);
90
+
86
91
  useEffect(() => {
87
92
  window.addEventListener('resize', handleResize);
88
93
  return () => window.removeEventListener('resize', handleResize);
89
94
  }, [handleResize]);
90
95
 
91
- /**
92
- * Restore scroll when returning to deck mode
93
- */
94
- useLayoutEffect(() => {
95
- if (layoutMode !== 'deck') {
96
- restoreScrollRef.current = true;
97
- } else if (restoreScrollRef.current && deckRef.current && scrollLeft) {
98
- // console.log('[restoring scrollLeft]', scrollLeft);
99
- deckRef.current.scrollLeft = scrollLeft;
100
- restoreScrollRef.current = false;
96
+ const restoreScroll = useCallback(() => {
97
+ if (deckRef.current && scrollLeftRef.current != null) {
98
+ deckRef.current.scrollLeft = scrollLeftRef.current;
101
99
  }
102
- }, [layoutMode, deckRef.current, scrollLeft]);
100
+ }, []);
101
+
102
+ useOnTransition(layoutMode, (mode) => mode !== 'deck', 'deck', restoreScroll);
103
103
 
104
104
  /**
105
105
  * Save scroll position as the user scrolls
@@ -107,48 +107,20 @@ export const DeckLayout = ({
107
107
  const handleScroll = useCallback(
108
108
  (event: UIEvent) => {
109
109
  if (layoutMode === 'deck' && event.currentTarget === event.target) {
110
- // console.log('[save scroll left]', (event.target as HTMLDivElement).scrollLeft);
111
- setScrollLeft((event.target as HTMLDivElement).scrollLeft);
110
+ scrollLeftRef.current = (event.target as HTMLDivElement).scrollLeft;
112
111
  }
113
112
  },
114
113
  [layoutMode],
115
114
  );
116
115
 
117
- const complementarySlug = useMemo(() => {
118
- const entry = layoutParts.complementary?.at(0);
119
- if (entry) {
120
- return entry.path ? `${entry.id}${SLUG_PATH_SEPARATOR}${entry.path}` : entry.id;
121
- }
122
- }, [layoutParts]);
123
-
124
- const firstAttendedId = useMemo(() => Array.from(attention.attended ?? [])[0], [attention.attended]);
116
+ const isEmpty = layoutParts.main?.length === 0 && layoutParts.solo?.length === 0;
125
117
 
126
- useEffect(() => {
127
- // TODO(burdon): Can we prevent the need to re-scroll since the planks are preserved?
128
- // E.g., hide the deck and just move the solo article?
129
- if (layoutMode === 'deck' && firstAttendedId) {
130
- // setTimeout(() => {
131
- // const el = deckRef.current?.querySelector(`article[data-attendable-id="${firstAttendedId}"]`);
132
- // el?.scrollIntoView({ behavior: 'smooth', inline: 'center' });
133
- // }, 0);
134
- }
135
- }, [layoutMode, firstAttendedId]);
136
-
137
- // TODO(burdon): Needs cleaning up.
138
- const parts: LayoutEntry[] = useMemo(() => {
139
- const parts = [...(layoutParts.main ?? [])];
140
- for (const part of layoutParts.solo ?? []) {
141
- if (!parts.find((entry) => entry.id === part.id)) {
142
- parts.push(part);
143
- }
118
+ const padding = useMemo(() => {
119
+ if (layoutMode === 'deck' && overscroll === 'centering') {
120
+ return calculateOverscroll(layoutParts.main, plankSizing, sidebarOpen, complementarySidebarOpen);
144
121
  }
145
- return parts;
146
- }, [layoutParts.main, layoutParts.solo]);
147
-
148
- const padding =
149
- layoutMode === 'deck' && overscroll === 'centering'
150
- ? calculateOverscroll(layoutParts.main, plankSizing, sidebarOpen, complementarySidebarOpen)
151
- : {};
122
+ return {};
123
+ }, [layoutMode, overscroll, layoutParts.main, plankSizing, sidebarOpen, complementarySidebarOpen]);
152
124
 
153
125
  if (layoutMode === 'fullscreen') {
154
126
  return <Fullscreen id={fullScreenSlug} />;
@@ -167,31 +139,22 @@ export const DeckLayout = ({
167
139
  }
168
140
  }}
169
141
  >
170
- {/* TODO(burdon): Factor out hook to set document title. */}
171
- <ActiveNode id={firstAttendedId} />
142
+ <ActiveNode />
172
143
 
173
144
  <Main.Root
174
145
  navigationSidebarOpen={context.sidebarOpen}
175
146
  onNavigationSidebarOpenChange={(next) => (context.sidebarOpen = next)}
176
- {...(complementarySidebarOpen !== null && {
177
- complementarySidebarOpen: /* complementaryAvailable && */ context.complementarySidebarOpen as boolean,
178
- onComplementarySidebarOpenChange: (next) => (context.complementarySidebarOpen = next),
179
- })}
147
+ complementarySidebarOpen={context.complementarySidebarOpen}
148
+ onComplementarySidebarOpenChange={(next) => (context.complementarySidebarOpen = next)}
180
149
  >
181
150
  {/* Notch */}
182
151
  <Main.Notch classNames='z-[21]'>
183
152
  <Surface role='notch-start' />
184
- <Button
185
- // disabled={!sidebarAvailable}
186
- onClick={() => (context.sidebarOpen = !context.sidebarOpen)}
187
- variant='ghost'
188
- classNames='p-1'
189
- >
153
+ <Button onClick={() => (context.sidebarOpen = !context.sidebarOpen)} variant='ghost' classNames='p-1'>
190
154
  <span className='sr-only'>{t('open navigation sidebar label')}</span>
191
155
  <MenuIcon weight='light' className={getSize(5)} />
192
156
  </Button>
193
157
  <Button
194
- // disabled={!complementaryAvailable}
195
158
  onClick={() => (context.complementarySidebarOpen = !context.complementarySidebarOpen)}
196
159
  variant='ghost'
197
160
  classNames='p-1'
@@ -203,38 +166,51 @@ export const DeckLayout = ({
203
166
  </Main.Notch>
204
167
 
205
168
  {/* Left sidebar. */}
206
- <Sidebar attention={attention} layoutParts={layoutParts} />
169
+ <Sidebar layoutParts={layoutParts} />
207
170
 
208
171
  {/* Right sidebar. */}
209
- <ComplementarySidebar id={complementarySlug} layoutParts={layoutParts} flatDeck={flatDeck} />
172
+ <ComplementarySidebar panels={panels} current={layoutParts.complementary?.[0].id} flatDeck={flatDeck} />
210
173
 
211
174
  {/* Dialog overlay to dismiss dialogs. */}
212
175
  <Main.Overlay />
213
176
 
214
177
  {/* No content. */}
215
- {parts.length === 0 && (
178
+ {isEmpty && (
216
179
  <Main.Content handlesFocus>
217
180
  <ContentEmpty />
218
181
  </Main.Content>
219
182
  )}
220
183
 
221
184
  {/* Solo/deck mode. */}
222
- {parts.length !== 0 && (
185
+ {!isEmpty && (
223
186
  <Main.Content bounce classNames='grid block-end-[--statusbar-size]' handlesFocus>
224
187
  <div role='none' className='relative'>
225
188
  <Deck.Root
226
189
  style={padding}
227
- classNames={[!flatDeck && 'bg-deck', 'absolute inset-0', slots?.wallpaper?.classNames]}
190
+ classNames={[
191
+ !flatDeck && 'bg-deck',
192
+ mainPaddingTransitions,
193
+ 'absolute inset-0',
194
+ slots?.wallpaper?.classNames,
195
+ ]}
228
196
  solo={layoutMode === 'solo'}
229
197
  onScroll={handleScroll}
230
198
  ref={deckRef}
231
199
  >
232
- {parts.map((layoutEntry) => (
200
+ <Plank
201
+ entry={layoutParts.solo?.[0]}
202
+ layoutParts={layoutParts}
203
+ part='solo'
204
+ layoutMode={layoutMode}
205
+ flatDeck={flatDeck}
206
+ searchEnabled={!!searchPlugin}
207
+ />
208
+ {layoutParts.main?.map((layoutEntry) => (
233
209
  <Plank
234
210
  key={layoutEntry.id}
235
211
  entry={layoutEntry}
236
212
  layoutParts={layoutParts}
237
- part={layoutMode === 'solo' && layoutEntry.id === layoutParts.solo?.[0]?.id ? 'solo' : 'main'}
213
+ part='main'
238
214
  layoutMode={layoutMode}
239
215
  flatDeck={flatDeck}
240
216
  searchEnabled={!!searchPlugin}
@@ -245,15 +221,8 @@ export const DeckLayout = ({
245
221
  </Main.Content>
246
222
  )}
247
223
 
248
- <StatusBar />
249
-
250
- {/* Help hints. */}
251
- {/* TODO(burdon): Need to make room for this in status bar. */}
252
- {showHintsFooter && (
253
- <div className='fixed bottom-0 left-0 right-0 h-[32px] z-[1] flex justify-center'>
254
- <Surface role='hints' limit={1} />
255
- </div>
256
- )}
224
+ {/* Footer status. */}
225
+ <StatusBar showHints={showHints} />
257
226
 
258
227
  {/* Global popovers. */}
259
228
  <Popover.Portal>
@@ -2,157 +2,160 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { Placeholder } from '@phosphor-icons/react';
6
- import React, { Fragment, useEffect } from 'react';
5
+ import React, { Fragment, memo, useEffect, useMemo } from 'react';
7
6
 
8
7
  import {
9
8
  LayoutAction,
10
9
  NavigationAction,
11
- SLUG_COLLECTION_INDICATOR,
12
10
  SLUG_PATH_SEPARATOR,
13
11
  Surface,
14
12
  useIntentDispatcher,
15
- indexInPart,
16
- partLength,
17
- type LayoutParts,
18
- type LayoutPart,
19
- type LayoutEntry,
13
+ type LayoutCoordinate,
20
14
  } from '@dxos/app-framework';
21
15
  import { type Node, useGraph } from '@dxos/plugin-graph';
22
- import { Popover, toLocalizedString, useMediaQuery, useTranslation } from '@dxos/react-ui';
23
- import { PlankHeading, plankHeadingIconProps } from '@dxos/react-ui-deck';
16
+ import { Icon, Popover, toLocalizedString, useMediaQuery, useTranslation } from '@dxos/react-ui';
17
+ import { PlankHeading, type PlankHeadingAction } from '@dxos/react-ui-deck';
24
18
  import { TextTooltip } from '@dxos/react-ui-text-tooltip';
25
19
 
26
20
  import { DECK_PLUGIN } from '../../meta';
27
21
 
28
- export const NodePlankHeading = ({
29
- node,
30
- id,
31
- layoutParts,
32
- layoutPart,
33
- // TODO(wittjosiah): Unused?
34
- layoutEntry,
35
- popoverAnchorId,
36
- pending,
37
- flatDeck,
38
- }: {
22
+ export type NodePlankHeadingProps = {
23
+ coordinate: LayoutCoordinate;
39
24
  node?: Node;
40
- id?: string;
41
- layoutParts?: LayoutParts;
42
- layoutPart?: LayoutPart;
43
- layoutEntry?: LayoutEntry;
25
+ canIncrementStart?: boolean;
26
+ canIncrementEnd?: boolean;
44
27
  popoverAnchorId?: string;
45
28
  pending?: boolean;
46
29
  flatDeck?: boolean;
47
- }) => {
48
- const { t } = useTranslation(DECK_PLUGIN);
49
- const { graph } = useGraph();
50
- const Icon = node?.properties?.icon ?? Placeholder;
51
- const label = pending
52
- ? t('pending heading')
53
- : toLocalizedString(node?.properties?.label ?? ['plank heading fallback label', { ns: DECK_PLUGIN }], t);
54
- const dispatch = useIntentDispatcher();
55
- const ActionRoot = node && popoverAnchorId === `dxos.org/ui/${DECK_PLUGIN}/${node.id}` ? Popover.Anchor : Fragment;
56
- const [isNotMobile] = useMediaQuery('md');
57
-
58
- useEffect(() => {
59
- const frame = requestAnimationFrame(() => {
60
- // Load actions for the node.
61
- node && graph.actions(node);
62
- });
30
+ actions?: PlankHeadingAction[];
31
+ };
63
32
 
64
- return () => cancelAnimationFrame(frame);
65
- }, [node]);
33
+ export const NodePlankHeading = memo(
34
+ ({
35
+ coordinate,
36
+ node,
37
+ canIncrementStart,
38
+ canIncrementEnd,
39
+ popoverAnchorId,
40
+ pending,
41
+ flatDeck,
42
+ actions = [],
43
+ }: NodePlankHeadingProps) => {
44
+ const { t } = useTranslation(DECK_PLUGIN);
45
+ const { graph } = useGraph();
46
+ const icon = node?.properties?.icon ?? 'ph--placeholder--regular';
47
+ const label = pending
48
+ ? t('pending heading')
49
+ : toLocalizedString(node?.properties?.label ?? ['plank heading fallback label', { ns: DECK_PLUGIN }], t);
50
+ const dispatch = useIntentDispatcher();
51
+ const ActionRoot = node && popoverAnchorId === `dxos.org/ui/${DECK_PLUGIN}/${node.id}` ? Popover.Anchor : Fragment;
52
+ const [isNotMobile] = useMediaQuery('md');
66
53
 
67
- // NOTE(Zan): Node ids may now contain a path like `${space}:${id}~comments`
68
- const attendableId = id?.split(SLUG_PATH_SEPARATOR).at(0);
54
+ useEffect(() => {
55
+ const frame = requestAnimationFrame(() => {
56
+ // Load actions for the node.
57
+ node && graph.actions(node);
58
+ });
69
59
 
70
- const layoutCoordinate = layoutPart !== undefined && id !== undefined ? { part: layoutPart, entryId: id } : undefined;
71
- const index = indexInPart(layoutParts, layoutCoordinate);
72
- const length = partLength(layoutParts, layoutPart);
60
+ return () => cancelAnimationFrame(frame);
61
+ }, [node]);
73
62
 
74
- const canIncrementStart =
75
- layoutPart === 'main' && index !== undefined && index > 0 && length !== undefined && length > 1;
76
- const canIncrementEnd = layoutPart === 'main' && index !== undefined && index < length - 1 && length !== undefined;
63
+ const layoutPart = coordinate.part;
64
+ // NOTE(Zan): Node ids may now contain a path like `${space}:${id}~comments`
65
+ const attendableId = coordinate.entryId.split(SLUG_PATH_SEPARATOR).at(0);
66
+ const capabilities = useMemo(
67
+ () => ({
68
+ solo: (layoutPart === 'solo' || layoutPart === 'main') && isNotMobile,
69
+ incrementStart: canIncrementStart,
70
+ incrementEnd: canIncrementEnd,
71
+ }),
72
+ [isNotMobile, layoutPart, canIncrementStart, canIncrementEnd],
73
+ );
77
74
 
78
- return (
79
- <PlankHeading.Root {...((layoutPart !== 'main' || !flatDeck) && { classNames: 'pie-1 border-b border-separator' })}>
80
- <ActionRoot>
81
- {node ? (
82
- <PlankHeading.ActionsMenu
83
- Icon={Icon}
75
+ return (
76
+ <PlankHeading.Root
77
+ {...((layoutPart !== 'main' || !flatDeck) && { classNames: 'pie-1 border-b border-separator' })}
78
+ >
79
+ <ActionRoot>
80
+ {node ? (
81
+ <PlankHeading.ActionsMenu
82
+ icon={icon}
83
+ related={layoutPart === 'complementary'}
84
+ attendableId={attendableId}
85
+ triggerLabel={t('actions menu label')}
86
+ actions={[actions, graph.actions(node)].filter((a) => a.length > 0)}
87
+ onAction={(action) =>
88
+ typeof action.data === 'function' && action.data?.({ node: action as Node, caller: DECK_PLUGIN })
89
+ }
90
+ >
91
+ <Surface role='menu-footer' data={{ object: node.data }} />
92
+ </PlankHeading.ActionsMenu>
93
+ ) : (
94
+ <PlankHeading.Button>
95
+ <span className='sr-only'>{label}</span>
96
+ <Icon icon={icon} size={5} />
97
+ </PlankHeading.Button>
98
+ )}
99
+ </ActionRoot>
100
+ <TextTooltip text={label} onlyWhenTruncating>
101
+ <PlankHeading.Label
84
102
  attendableId={attendableId}
85
- triggerLabel={t('actions menu label')}
86
- actions={graph.actions(node)}
87
- onAction={(action) =>
88
- typeof action.data === 'function' && action.data?.({ node: action as Node, caller: DECK_PLUGIN })
89
- }
103
+ related={layoutPart === 'complementary'}
104
+ {...(pending && { classNames: 'text-description' })}
90
105
  >
91
- <Surface role='menu-footer' data={{ object: node.data }} />
92
- </PlankHeading.ActionsMenu>
93
- ) : (
94
- <PlankHeading.Button>
95
- <span className='sr-only'>{label}</span>
96
- <Icon {...plankHeadingIconProps} />
97
- </PlankHeading.Button>
106
+ {label}
107
+ </PlankHeading.Label>
108
+ </TextTooltip>
109
+ {node && layoutPart !== 'complementary' && (
110
+ // TODO(Zan): What are we doing with layout coordinate here?
111
+ <Surface role='navbar-end' direction='inline-reverse' data={{ object: node.data }} />
98
112
  )}
99
- </ActionRoot>
100
- <TextTooltip text={label} onlyWhenTruncating>
101
- <PlankHeading.Label attendableId={node?.id} {...(pending && { classNames: 'text-description' })}>
102
- {label}
103
- </PlankHeading.Label>
104
- </TextTooltip>
105
- {node && layoutPart !== 'complementary' && (
106
- // TODO(Zan): What are we doing with layout coordinate here?
107
- <Surface role='navbar-end' direction='inline-reverse' data={{ object: node.data }} />
108
- )}
109
- {/* NOTE(thure): Pinning & unpinning are temporarily disabled */}
110
- <PlankHeading.Controls
111
- capabilities={{
112
- solo: (layoutPart === 'solo' || layoutPart === 'main') && isNotMobile,
113
- incrementStart: canIncrementStart,
114
- incrementEnd: canIncrementEnd,
115
- }}
116
- isSolo={layoutPart === 'solo'}
117
- onClick={(eventType) => {
118
- if (!layoutPart) {
119
- return;
120
- }
121
-
122
- if (eventType === 'solo') {
123
- return dispatch([
124
- {
125
- action: NavigationAction.ADJUST,
126
- data: { type: eventType, layoutCoordinate: { part: 'main', entryId: id } },
127
- },
128
- ]);
129
- }
113
+ {/* NOTE(thure): Pinning & unpinning are temporarily disabled */}
114
+ <PlankHeading.Controls
115
+ capabilities={capabilities}
116
+ isSolo={layoutPart === 'solo'}
117
+ onClick={(eventType) => {
118
+ if (!layoutPart) {
119
+ return;
120
+ }
130
121
 
131
- // TODO(Zan): Update this to use the new layout actions.
132
- return dispatch(
133
- eventType === 'close'
134
- ? layoutPart === 'complementary'
135
- ? {
136
- action: LayoutAction.SET_LAYOUT,
137
- data: {
138
- element: 'complementary',
139
- state: false,
140
- },
141
- }
142
- : {
143
- action: NavigationAction.CLOSE,
144
- data: {
145
- activeParts: {
146
- complementary: [`${id}${SLUG_PATH_SEPARATOR}comments${SLUG_COLLECTION_INDICATOR}`],
147
- [layoutPart]: [id],
148
- },
122
+ // TODO(Zan): Update this to use the new layout actions.
123
+ if (eventType === 'solo') {
124
+ return dispatch([
125
+ {
126
+ action: NavigationAction.ADJUST,
127
+ data: { type: eventType, layoutCoordinate: { part: 'main', entryId: coordinate.entryId } },
128
+ },
129
+ ]);
130
+ } else if (eventType === 'close') {
131
+ if (layoutPart === 'complementary') {
132
+ return dispatch({
133
+ action: LayoutAction.SET_LAYOUT,
134
+ data: {
135
+ element: 'complementary',
136
+ state: false,
137
+ },
138
+ });
139
+ } else {
140
+ return dispatch({
141
+ action: NavigationAction.CLOSE,
142
+ data: {
143
+ activeParts: {
144
+ [layoutPart]: [coordinate.entryId],
149
145
  },
150
- }
151
- : { action: NavigationAction.ADJUST, data: { type: eventType, layoutCoordinate } },
152
- );
153
- }}
154
- close={layoutCoordinate?.part === 'complementary' ? 'minify-end' : true}
155
- />
156
- </PlankHeading.Root>
157
- );
158
- };
146
+ },
147
+ });
148
+ }
149
+ } else {
150
+ return dispatch({
151
+ action: NavigationAction.ADJUST,
152
+ data: { type: eventType, layoutCoordinate: coordinate },
153
+ });
154
+ }
155
+ }}
156
+ close={layoutPart === 'complementary' ? 'minify-end' : true}
157
+ />
158
+ </PlankHeading.Root>
159
+ );
160
+ },
161
+ );