@dxos/plugin-deck 0.7.5-labs.a279d8c → 0.7.5-labs.d453967

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 (214) hide show
  1. package/dist/lib/browser/{app-graph-builder-67VRUD5K.mjs → app-graph-builder-CI6ZFMNL.mjs} +57 -31
  2. package/dist/lib/browser/app-graph-builder-CI6ZFMNL.mjs.map +7 -0
  3. package/dist/lib/browser/{check-app-scheme-GEX6W2R5.mjs → check-app-scheme-S3EYUPMF.mjs} +3 -3
  4. package/dist/lib/browser/{check-app-scheme-GEX6W2R5.mjs.map → check-app-scheme-S3EYUPMF.mjs.map} +2 -2
  5. package/dist/lib/browser/chunk-23KS5L3I.mjs +1124 -0
  6. package/dist/lib/browser/chunk-23KS5L3I.mjs.map +7 -0
  7. package/dist/lib/browser/chunk-4URQJVGI.mjs +24 -0
  8. package/dist/lib/browser/chunk-4URQJVGI.mjs.map +7 -0
  9. package/dist/lib/browser/{chunk-JQJ5UWVB.mjs → chunk-N7TEPFVR.mjs} +3 -2
  10. package/dist/lib/browser/{chunk-JQJ5UWVB.mjs.map → chunk-N7TEPFVR.mjs.map} +3 -3
  11. package/dist/lib/browser/chunk-PTLNGUND.mjs +126 -0
  12. package/dist/lib/browser/chunk-PTLNGUND.mjs.map +7 -0
  13. package/dist/lib/browser/{chunk-5VFDMW5M.mjs → chunk-YQ2GWTDU.mjs} +2 -2
  14. package/dist/lib/browser/chunk-YQ2GWTDU.mjs.map +7 -0
  15. package/dist/lib/browser/index.mjs +36 -82
  16. package/dist/lib/browser/index.mjs.map +4 -4
  17. package/dist/lib/browser/intent-resolver-WAYXVAFN.mjs +497 -0
  18. package/dist/lib/browser/intent-resolver-WAYXVAFN.mjs.map +7 -0
  19. package/dist/lib/browser/meta.json +1 -1
  20. package/dist/lib/browser/{react-root-AWYSGU4Q.mjs → react-root-YATKEIAZ.mjs} +10 -14
  21. package/dist/lib/browser/react-root-YATKEIAZ.mjs.map +7 -0
  22. package/dist/lib/browser/react-surface-SS2BX6FS.mjs +38 -0
  23. package/dist/lib/browser/react-surface-SS2BX6FS.mjs.map +7 -0
  24. package/dist/lib/browser/{settings-FNWW6WIJ.mjs → settings-CRQTVMN3.mjs} +6 -7
  25. package/dist/lib/browser/settings-CRQTVMN3.mjs.map +7 -0
  26. package/dist/lib/browser/state-YEQA3IIB.mjs +117 -0
  27. package/dist/lib/browser/state-YEQA3IIB.mjs.map +7 -0
  28. package/dist/lib/browser/{tools-4XY7KFQF.mjs → tools-5LDJNU56.mjs} +14 -9
  29. package/dist/lib/browser/tools-5LDJNU56.mjs.map +7 -0
  30. package/dist/lib/browser/types.mjs +16 -4
  31. package/dist/lib/browser/url-handler-HLF42IHP.mjs +70 -0
  32. package/dist/lib/browser/url-handler-HLF42IHP.mjs.map +7 -0
  33. package/dist/types/src/DeckPlugin.d.ts.map +1 -1
  34. package/dist/types/src/capabilities/{layout/app-graph-builder.d.ts → app-graph-builder.d.ts} +22 -22
  35. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -0
  36. package/dist/types/src/capabilities/capabilities.d.ts +132 -3
  37. package/dist/types/src/capabilities/capabilities.d.ts.map +1 -1
  38. package/dist/types/src/capabilities/check-app-scheme.d.ts.map +1 -0
  39. package/dist/types/src/capabilities/index.d.ts +188 -3
  40. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  41. package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -0
  42. package/dist/types/src/capabilities/react-root.d.ts.map +1 -0
  43. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
  44. package/dist/types/src/capabilities/set-active.d.ts +9 -0
  45. package/dist/types/src/capabilities/set-active.d.ts.map +1 -0
  46. package/dist/types/src/capabilities/settings.d.ts.map +1 -0
  47. package/dist/types/src/capabilities/state.d.ts +76 -0
  48. package/dist/types/src/capabilities/state.d.ts.map +1 -0
  49. package/dist/types/src/capabilities/{navigation/tools.d.ts → tools.d.ts} +1 -0
  50. package/dist/types/src/capabilities/tools.d.ts.map +1 -0
  51. package/dist/types/src/capabilities/url-handler.d.ts.map +1 -0
  52. package/dist/types/src/components/DeckLayout/ActiveNode.d.ts.map +1 -1
  53. package/dist/types/src/components/DeckLayout/ComplementarySidebar.d.ts.map +1 -1
  54. package/dist/types/src/components/DeckLayout/ContentEmpty.d.ts.map +1 -1
  55. package/dist/types/src/components/DeckLayout/DeckLayout.d.ts +1 -4
  56. package/dist/types/src/components/DeckLayout/DeckLayout.d.ts.map +1 -1
  57. package/dist/types/src/components/DeckLayout/Fullscreen.d.ts.map +1 -1
  58. package/dist/types/src/components/DeckLayout/NodePlankHeading.d.ts +3 -3
  59. package/dist/types/src/components/DeckLayout/NodePlankHeading.d.ts.map +1 -1
  60. package/dist/types/src/components/DeckLayout/Plank.d.ts +8 -6
  61. package/dist/types/src/components/DeckLayout/Plank.d.ts.map +1 -1
  62. package/dist/types/src/components/DeckLayout/PlankControls.d.ts +2 -2
  63. package/dist/types/src/components/DeckLayout/PlankControls.d.ts.map +1 -1
  64. package/dist/types/src/components/DeckLayout/PlankError.d.ts +4 -3
  65. package/dist/types/src/components/DeckLayout/PlankError.d.ts.map +1 -1
  66. package/dist/types/src/components/DeckLayout/Sidebar.d.ts.map +1 -1
  67. package/dist/types/src/components/DeckLayout/SidebarButton.d.ts +5 -3
  68. package/dist/types/src/components/DeckLayout/SidebarButton.d.ts.map +1 -1
  69. package/dist/types/src/components/DeckLayout/StatusBar.d.ts.map +1 -1
  70. package/dist/types/src/components/DeckLayout/Toast.d.ts +2 -2
  71. package/dist/types/src/components/DeckLayout/Toast.d.ts.map +1 -1
  72. package/dist/types/src/components/fragments.d.ts +2 -0
  73. package/dist/types/src/components/fragments.d.ts.map +1 -1
  74. package/dist/types/src/components/index.d.ts +0 -2
  75. package/dist/types/src/components/index.d.ts.map +1 -1
  76. package/dist/types/src/hooks/useMainSize.d.ts +2 -2
  77. package/dist/types/src/hooks/useNode.d.ts.map +1 -1
  78. package/dist/types/src/layout.d.ts +5 -19
  79. package/dist/types/src/layout.d.ts.map +1 -1
  80. package/dist/types/src/meta.d.ts +1 -0
  81. package/dist/types/src/meta.d.ts.map +1 -1
  82. package/dist/types/src/translations.d.ts +3 -3
  83. package/dist/types/src/types.d.ts +107 -2
  84. package/dist/types/src/types.d.ts.map +1 -1
  85. package/dist/types/src/util/index.d.ts +2 -1
  86. package/dist/types/src/util/index.d.ts.map +1 -1
  87. package/dist/types/src/util/layoutAppliesTopbar.d.ts +2 -0
  88. package/dist/types/src/util/layoutAppliesTopbar.d.ts.map +1 -0
  89. package/dist/types/src/util/useHoistStatusbar.d.ts.map +1 -1
  90. package/dist/types/tsconfig.tsbuildinfo +1 -1
  91. package/package.json +30 -31
  92. package/src/DeckPlugin.ts +17 -63
  93. package/src/capabilities/{layout/app-graph-builder.ts → app-graph-builder.ts} +36 -28
  94. package/src/capabilities/capabilities.ts +4 -3
  95. package/src/capabilities/{navigation/check-app-scheme.ts → check-app-scheme.ts} +2 -2
  96. package/src/capabilities/index.ts +12 -3
  97. package/src/capabilities/intent-resolver.ts +350 -0
  98. package/src/capabilities/{layout/react-root.tsx → react-root.tsx} +7 -11
  99. package/src/capabilities/react-surface.tsx +31 -0
  100. package/src/capabilities/set-active.ts +47 -0
  101. package/src/capabilities/{settings/settings.ts → settings.ts} +4 -5
  102. package/src/capabilities/state.ts +102 -0
  103. package/src/capabilities/{navigation/tools.ts → tools.ts} +10 -6
  104. package/src/capabilities/url-handler.ts +63 -0
  105. package/src/components/DeckLayout/ActiveNode.tsx +2 -3
  106. package/src/components/DeckLayout/ComplementarySidebar.tsx +120 -69
  107. package/src/components/DeckLayout/ContentEmpty.tsx +7 -10
  108. package/src/components/DeckLayout/DeckLayout.tsx +116 -64
  109. package/src/components/DeckLayout/Fullscreen.tsx +2 -3
  110. package/src/components/DeckLayout/NodePlankHeading.tsx +57 -65
  111. package/src/components/DeckLayout/Plank.tsx +32 -41
  112. package/src/components/DeckLayout/PlankControls.tsx +11 -10
  113. package/src/components/DeckLayout/PlankError.tsx +6 -5
  114. package/src/components/DeckLayout/Sidebar.tsx +17 -20
  115. package/src/components/DeckLayout/SidebarButton.tsx +25 -31
  116. package/src/components/DeckLayout/StatusBar.tsx +5 -11
  117. package/src/components/DeckLayout/Toast.tsx +2 -2
  118. package/src/components/LayoutSettings.tsx +8 -8
  119. package/src/components/fragments.ts +8 -0
  120. package/src/components/index.ts +0 -2
  121. package/src/hooks/useMainSize.ts +3 -3
  122. package/src/hooks/useNode.ts +3 -1
  123. package/src/layout.ts +43 -212
  124. package/src/meta.ts +1 -0
  125. package/src/translations.ts +8 -8
  126. package/src/types.ts +88 -2
  127. package/src/util/index.ts +2 -1
  128. package/src/util/layoutAppliesTopbar.ts +7 -0
  129. package/src/util/useHoistStatusbar.ts +17 -8
  130. package/dist/lib/browser/app-graph-builder-67VRUD5K.mjs.map +0 -7
  131. package/dist/lib/browser/chunk-2PJNBVCY.mjs +0 -39
  132. package/dist/lib/browser/chunk-2PJNBVCY.mjs.map +0 -7
  133. package/dist/lib/browser/chunk-4C2AFTET.mjs +0 -186
  134. package/dist/lib/browser/chunk-4C2AFTET.mjs.map +0 -7
  135. package/dist/lib/browser/chunk-5VFDMW5M.mjs.map +0 -7
  136. package/dist/lib/browser/chunk-KY5WXIXY.mjs +0 -44
  137. package/dist/lib/browser/chunk-KY5WXIXY.mjs.map +0 -7
  138. package/dist/lib/browser/chunk-WUMAJGVA.mjs +0 -1052
  139. package/dist/lib/browser/chunk-WUMAJGVA.mjs.map +0 -7
  140. package/dist/lib/browser/deck-PLCSKPGL.mjs +0 -26
  141. package/dist/lib/browser/deck-PLCSKPGL.mjs.map +0 -7
  142. package/dist/lib/browser/intent-resolver-FVOQSTBX.mjs +0 -152
  143. package/dist/lib/browser/intent-resolver-FVOQSTBX.mjs.map +0 -7
  144. package/dist/lib/browser/intent-resolver-K7GW4A2I.mjs +0 -249
  145. package/dist/lib/browser/intent-resolver-K7GW4A2I.mjs.map +0 -7
  146. package/dist/lib/browser/location-AIO6V3MK.mjs +0 -35
  147. package/dist/lib/browser/location-AIO6V3MK.mjs.map +0 -7
  148. package/dist/lib/browser/react-context-G6PDXUI5.mjs +0 -32
  149. package/dist/lib/browser/react-context-G6PDXUI5.mjs.map +0 -7
  150. package/dist/lib/browser/react-root-AWYSGU4Q.mjs.map +0 -7
  151. package/dist/lib/browser/react-surface-CLUABFNX.mjs +0 -28
  152. package/dist/lib/browser/react-surface-CLUABFNX.mjs.map +0 -7
  153. package/dist/lib/browser/settings-FNWW6WIJ.mjs.map +0 -7
  154. package/dist/lib/browser/state-7I5BD7SE.mjs +0 -34
  155. package/dist/lib/browser/state-7I5BD7SE.mjs.map +0 -7
  156. package/dist/lib/browser/tools-4XY7KFQF.mjs.map +0 -7
  157. package/dist/lib/browser/url-handler-JRAQRY73.mjs +0 -76
  158. package/dist/lib/browser/url-handler-JRAQRY73.mjs.map +0 -7
  159. package/dist/types/src/capabilities/layout/app-graph-builder.d.ts.map +0 -1
  160. package/dist/types/src/capabilities/layout/deck.d.ts +0 -4
  161. package/dist/types/src/capabilities/layout/deck.d.ts.map +0 -1
  162. package/dist/types/src/capabilities/layout/index.d.ts +0 -229
  163. package/dist/types/src/capabilities/layout/index.d.ts.map +0 -1
  164. package/dist/types/src/capabilities/layout/intent-resolver.d.ts.map +0 -1
  165. package/dist/types/src/capabilities/layout/react-context.d.ts +0 -8
  166. package/dist/types/src/capabilities/layout/react-context.d.ts.map +0 -1
  167. package/dist/types/src/capabilities/layout/react-root.d.ts.map +0 -1
  168. package/dist/types/src/capabilities/layout/state.d.ts +0 -42
  169. package/dist/types/src/capabilities/layout/state.d.ts.map +0 -1
  170. package/dist/types/src/capabilities/navigation/check-app-scheme.d.ts.map +0 -1
  171. package/dist/types/src/capabilities/navigation/index.d.ts +0 -6
  172. package/dist/types/src/capabilities/navigation/index.d.ts.map +0 -1
  173. package/dist/types/src/capabilities/navigation/intent-resolver.d.ts +0 -4
  174. package/dist/types/src/capabilities/navigation/intent-resolver.d.ts.map +0 -1
  175. package/dist/types/src/capabilities/navigation/location.d.ts +0 -4
  176. package/dist/types/src/capabilities/navigation/location.d.ts.map +0 -1
  177. package/dist/types/src/capabilities/navigation/set-location.d.ts +0 -10
  178. package/dist/types/src/capabilities/navigation/set-location.d.ts.map +0 -1
  179. package/dist/types/src/capabilities/navigation/tools.d.ts.map +0 -1
  180. package/dist/types/src/capabilities/navigation/url-handler.d.ts.map +0 -1
  181. package/dist/types/src/capabilities/settings/index.d.ts +0 -3
  182. package/dist/types/src/capabilities/settings/index.d.ts.map +0 -1
  183. package/dist/types/src/capabilities/settings/react-surface.d.ts.map +0 -1
  184. package/dist/types/src/capabilities/settings/settings.d.ts.map +0 -1
  185. package/dist/types/src/components/DeckContext.d.ts +0 -11
  186. package/dist/types/src/components/DeckContext.d.ts.map +0 -1
  187. package/dist/types/src/components/LayoutContext.d.ts +0 -5
  188. package/dist/types/src/components/LayoutContext.d.ts.map +0 -1
  189. package/dist/types/src/layout.test.d.ts +0 -2
  190. package/dist/types/src/layout.test.d.ts.map +0 -1
  191. package/dist/types/src/util/layout-parts.d.ts +0 -7
  192. package/dist/types/src/util/layout-parts.d.ts.map +0 -1
  193. package/src/capabilities/layout/deck.ts +0 -25
  194. package/src/capabilities/layout/index.ts +0 -12
  195. package/src/capabilities/layout/intent-resolver.ts +0 -128
  196. package/src/capabilities/layout/react-context.tsx +0 -26
  197. package/src/capabilities/layout/state.ts +0 -32
  198. package/src/capabilities/navigation/index.ts +0 -11
  199. package/src/capabilities/navigation/intent-resolver.ts +0 -216
  200. package/src/capabilities/navigation/location.ts +0 -28
  201. package/src/capabilities/navigation/set-location.ts +0 -38
  202. package/src/capabilities/navigation/url-handler.ts +0 -67
  203. package/src/capabilities/settings/index.ts +0 -8
  204. package/src/capabilities/settings/react-surface.tsx +0 -23
  205. package/src/components/DeckContext.ts +0 -19
  206. package/src/components/LayoutContext.ts +0 -12
  207. package/src/layout.test.ts +0 -380
  208. package/src/util/layout-parts.ts +0 -12
  209. /package/dist/types/src/capabilities/{navigation/check-app-scheme.d.ts → check-app-scheme.d.ts} +0 -0
  210. /package/dist/types/src/capabilities/{layout/intent-resolver.d.ts → intent-resolver.d.ts} +0 -0
  211. /package/dist/types/src/capabilities/{layout/react-root.d.ts → react-root.d.ts} +0 -0
  212. /package/dist/types/src/capabilities/{settings/react-surface.d.ts → react-surface.d.ts} +0 -0
  213. /package/dist/types/src/capabilities/{settings/settings.d.ts → settings.d.ts} +0 -0
  214. /package/dist/types/src/capabilities/{navigation/url-handler.d.ts → url-handler.d.ts} +0 -0
@@ -6,65 +6,56 @@ import React, { type KeyboardEvent, memo, useCallback, useLayoutEffect, useMemo,
6
6
 
7
7
  import {
8
8
  createIntent,
9
- indexInPart,
10
9
  LayoutAction,
11
- partLength,
12
10
  Surface,
11
+ useCapability,
12
+ useAppGraph,
13
13
  useIntentDispatcher,
14
- type Layout,
15
- type LayoutCoordinate,
16
- type LayoutEntry,
17
- type LayoutPart,
18
- type LayoutParts,
19
14
  } from '@dxos/app-framework';
20
15
  import { debounce } from '@dxos/async';
21
- import { useGraph } from '@dxos/plugin-graph';
22
16
  import { useAttendableAttributes } from '@dxos/react-ui-attention';
23
17
  import { StackItem, railGridHorizontal } from '@dxos/react-ui-stack';
24
18
  import { mainIntrinsicSize, mx } from '@dxos/react-ui-theme';
25
19
 
26
- import { NodePlankHeading } from './NodePlankHeading';
20
+ import { NodePlankHeading, type NodePlankHeadingProps } from './NodePlankHeading';
27
21
  import { PlankContentError, PlankError } from './PlankError';
28
22
  import { PlankLoading } from './PlankLoading';
23
+ import { DeckCapabilities } from '../../capabilities';
29
24
  import { useNode, useMainSize } from '../../hooks';
30
- import { DeckAction } from '../../types';
31
- import { useDeckContext } from '../DeckContext';
32
- import { useLayout } from '../LayoutContext';
25
+ import { DeckAction, type LayoutMode } from '../../types';
33
26
 
34
27
  const UNKNOWN_ID = 'unknown_id';
35
28
 
36
29
  export type PlankProps = {
37
- entry?: LayoutEntry;
38
- layoutParts: LayoutParts;
39
- // TODO(wittjosiah): Remove. Pass in LayoutCoordinate instead of LayoutEntry.
40
- part: LayoutPart;
41
- layoutMode: Layout['layoutMode'];
30
+ id?: string;
31
+ part: NodePlankHeadingProps['part'];
32
+ path?: string[];
42
33
  order?: number;
34
+ active?: string[];
35
+ layoutMode: LayoutMode;
43
36
  };
44
37
 
45
- export const Plank = memo(({ entry, layoutParts, part, layoutMode, order }: PlankProps) => {
38
+ export const Plank = memo(({ id = UNKNOWN_ID, part, path, order, active, layoutMode }: PlankProps) => {
46
39
  const { dispatchPromise: dispatch } = useIntentDispatcher();
47
- const coordinate: LayoutCoordinate = useMemo(() => ({ part, entryId: entry?.id ?? UNKNOWN_ID }), [entry?.id, part]);
48
- const { popoverAnchorId, scrollIntoView } = useLayout();
49
- const { plankSizing } = useDeckContext();
50
- const { graph } = useGraph();
51
- const node = useNode(graph, entry?.id);
40
+ const { deck, popoverAnchorId, scrollIntoView } = useCapability(DeckCapabilities.DeckState);
41
+ const { graph } = useAppGraph();
42
+ const node = useNode(graph, id);
52
43
  const rootElement = useRef<HTMLDivElement | null>(null);
53
44
  const canResize = layoutMode === 'deck';
54
45
  const Root = part === 'solo' ? 'article' : StackItem.Root;
55
46
 
56
- const attendableAttrs = useAttendableAttributes(coordinate.entryId);
57
- const index = indexInPart(layoutParts, coordinate);
58
- const length = partLength(layoutParts, part);
59
- const canIncrementStart = part === 'main' && index !== undefined && index > 0 && length !== undefined && length > 1;
60
- const canIncrementEnd = part === 'main' && index !== undefined && index < length - 1 && length !== undefined;
47
+ const attendableAttrs = useAttendableAttributes(id);
48
+ const index = active ? active.findIndex((entryId) => entryId === id) : 0;
49
+ const length = active?.length ?? 1;
50
+ const canIncrementStart = active && index !== undefined && index > 0 && length !== undefined && length > 1;
51
+ const canIncrementEnd = active && index !== undefined && index < length - 1 && length !== undefined;
61
52
 
62
- const size = plankSizing?.[coordinate.entryId] as number | undefined;
53
+ const size = deck.plankSizing[id] as number | undefined;
63
54
  const setSize = useCallback(
64
55
  debounce((nextSize: number) => {
65
- return dispatch(createIntent(DeckAction.UpdatePlankSize, { id: coordinate.entryId, size: nextSize }));
56
+ return dispatch(createIntent(DeckAction.UpdatePlankSize, { id, size: nextSize }));
66
57
  }, 200),
67
- [dispatch, coordinate.entryId],
58
+ [dispatch, id],
68
59
  );
69
60
 
70
61
  // TODO(thure): Tabster’s focus group should handle moving focus to Main, but something is blocking it.
@@ -75,19 +66,19 @@ export const Plank = memo(({ entry, layoutParts, part, layoutMode, order }: Plan
75
66
  }, []);
76
67
 
77
68
  useLayoutEffect(() => {
78
- if (scrollIntoView === coordinate.entryId) {
69
+ if (scrollIntoView === id) {
79
70
  // TODO(wittjosiah): When focused on page load, the focus is always visible.
80
71
  // Forcing focus to something smaller than the plank prevents large focus ring in the interim.
81
72
  const focusable = rootElement.current?.querySelector('button') || rootElement.current;
82
73
  focusable?.focus({ preventScroll: true });
83
74
  layoutMode === 'deck' && focusable?.scrollIntoView({ behavior: 'smooth', inline: 'center' });
84
75
  // Clear the scroll into view state once it has been actioned.
85
- void dispatch(createIntent(LayoutAction.ScrollIntoView, { id: undefined }));
76
+ void dispatch(createIntent(LayoutAction.ScrollIntoView, { part: 'current', subject: undefined }));
86
77
  }
87
- }, [coordinate.entryId, scrollIntoView, layoutMode]);
78
+ }, [id, scrollIntoView, layoutMode]);
88
79
 
89
80
  const isSolo = layoutMode === 'solo' && part === 'solo';
90
- const isAttendable = isSolo || (layoutMode === 'deck' && part === 'main');
81
+ const isAttendable = isSolo || (layoutMode === 'deck' && part === 'deck');
91
82
 
92
83
  const sizeAttrs = useMainSize();
93
84
 
@@ -95,11 +86,10 @@ export const Plank = memo(({ entry, layoutParts, part, layoutMode, order }: Plan
95
86
  () =>
96
87
  node && {
97
88
  subject: node.data,
98
- path: entry?.path,
99
- coordinate,
89
+ path,
100
90
  popoverAnchorId,
101
91
  },
102
- [node, node?.data, entry?.path, coordinate, popoverAnchorId],
92
+ [node, node?.data, path, popoverAnchorId],
103
93
  );
104
94
 
105
95
  // TODO(wittjosiah): Change prop to accept a component.
@@ -120,7 +110,7 @@ export const Plank = memo(({ entry, layoutParts, part, layoutMode, order }: Plan
120
110
  {...(part === 'solo'
121
111
  ? ({ ...sizeAttrs, className } as any)
122
112
  : {
123
- item: { id: entry?.id ?? 'never' },
113
+ item: { id },
124
114
  size,
125
115
  onSizeChange: setSize,
126
116
  classNames: className,
@@ -133,7 +123,8 @@ export const Plank = memo(({ entry, layoutParts, part, layoutMode, order }: Plan
133
123
  {node ? (
134
124
  <>
135
125
  <NodePlankHeading
136
- coordinate={coordinate}
126
+ id={id}
127
+ part={part}
137
128
  node={node}
138
129
  canIncrementStart={canIncrementStart}
139
130
  canIncrementEnd={canIncrementEnd}
@@ -149,7 +140,7 @@ export const Plank = memo(({ entry, layoutParts, part, layoutMode, order }: Plan
149
140
  />
150
141
  </>
151
142
  ) : (
152
- <PlankError layoutCoordinate={coordinate} />
143
+ <PlankError id={id} part={part} />
153
144
  )}
154
145
  {canResize && <StackItem.ResizeHandle />}
155
146
  </Root>
@@ -4,7 +4,6 @@
4
4
 
5
5
  import React, { forwardRef } from 'react';
6
6
 
7
- import { type PartAdjustment } from '@dxos/app-framework';
8
7
  import {
9
8
  Button,
10
9
  ButtonGroup,
@@ -16,8 +15,9 @@ import {
16
15
  } from '@dxos/react-ui';
17
16
 
18
17
  import { DECK_PLUGIN } from '../../meta';
18
+ import { type DeckAction } from '../../types';
19
19
 
20
- export type PlankControlHandler = (event: PartAdjustment) => void;
20
+ export type PlankControlHandler = (event: DeckAction.PartAdjustment) => void;
21
21
 
22
22
  export type PlankCapabilities = {
23
23
  incrementStart?: boolean;
@@ -52,17 +52,18 @@ const PlankControl = ({ icon, label, ...props }: Omit<ButtonProps, 'children'> &
52
52
 
53
53
  // TODO(wittjosiah): Duplicate of stack LayoutControls?
54
54
  // Translations were to be duplicated between packages.
55
+ // NOTE(thure): Pinning & unpinning are disabled indefinitely.
55
56
  export const PlankControls = forwardRef<HTMLDivElement, PlankControlsProps>(
56
57
  (
57
- { onClick, variant = 'default', capabilities: can, isSolo, pin, close = false, children, ...props },
58
+ { onClick, variant = 'default', capabilities: can, isSolo, pin, close = false, children, classNames, ...props },
58
59
  forwardedRef,
59
60
  ) => {
60
61
  const { t } = useTranslation(DECK_PLUGIN);
61
- const buttonClassNames = variant === 'hide-disabled' ? 'disabled:hidden !pli-2 !plb-3' : '!pli-2 !plb-3';
62
+ const buttonClassNames = variant === 'hide-disabled' ? 'disabled:hidden pli-2 plb-3' : 'pli-2 plb-3';
62
63
 
63
64
  return (
64
- <ButtonGroup {...props} ref={forwardedRef}>
65
- {pin && !isSolo && ['both', 'start'].includes(pin) && (
65
+ <ButtonGroup {...props} classNames={['app-no-drag', classNames]} ref={forwardedRef}>
66
+ {/* {pin && !isSolo && ['both', 'start'].includes(pin) && (
66
67
  <PlankControl
67
68
  label={t('pin start label')}
68
69
  variant='ghost'
@@ -70,14 +71,14 @@ export const PlankControls = forwardRef<HTMLDivElement, PlankControlsProps>(
70
71
  onClick={() => onClick?.('pin-start')}
71
72
  icon='ph--caret-line-left--regular'
72
73
  />
73
- )}
74
+ )} */}
74
75
 
75
76
  {can.solo && (
76
77
  <PlankControl
77
78
  label={isSolo ? t('show deck plank label') : t('show solo plank label')}
78
79
  classNames={buttonClassNames}
79
80
  onClick={() => onClick?.('solo')}
80
- icon={isSolo ? 'ph--arrow-u-down-left--regular' : 'ph--arrows-out--regular'}
81
+ icon={isSolo ? 'ph--corners-in--regular' : 'ph--corners-out--regular'}
81
82
  />
82
83
  )}
83
84
 
@@ -100,14 +101,14 @@ export const PlankControls = forwardRef<HTMLDivElement, PlankControlsProps>(
100
101
  </>
101
102
  )}
102
103
 
103
- {pin && !isSolo && ['both', 'end'].includes(pin) && (
104
+ {/* {pin && !isSolo && ['both', 'end'].includes(pin) && (
104
105
  <PlankControl
105
106
  label={t('pin end label')}
106
107
  classNames={buttonClassNames}
107
108
  onClick={() => onClick?.('pin-end')}
108
109
  icon='ph--caret-line-right--regular'
109
110
  />
110
- )}
111
+ )} */}
111
112
 
112
113
  {close && !isSolo && (
113
114
  <PlankControl
@@ -4,12 +4,11 @@
4
4
 
5
5
  import React, { useEffect, useState } from 'react';
6
6
 
7
- import { type LayoutCoordinate } from '@dxos/app-framework';
8
7
  import { type Node } from '@dxos/plugin-graph';
9
8
  import { useTranslation } from '@dxos/react-ui';
10
9
  import { descriptionText, mx } from '@dxos/react-ui-theme';
11
10
 
12
- import { NodePlankHeading } from './NodePlankHeading';
11
+ import { NodePlankHeading, type NodePlankHeadingProps } from './NodePlankHeading';
13
12
  import { PlankLoading } from './PlankLoading';
14
13
  import { DECK_PLUGIN } from '../../meta';
15
14
 
@@ -33,11 +32,13 @@ export const PlankContentError = ({ error }: { error?: Error }) => {
33
32
  };
34
33
 
35
34
  export const PlankError = ({
36
- layoutCoordinate,
35
+ id,
36
+ part,
37
37
  node,
38
38
  error,
39
39
  }: {
40
- layoutCoordinate: LayoutCoordinate;
40
+ id: string;
41
+ part: NodePlankHeadingProps['part'];
41
42
  node?: Node;
42
43
  error?: Error;
43
44
  }) => {
@@ -47,7 +48,7 @@ export const PlankError = ({
47
48
  }, []);
48
49
  return (
49
50
  <>
50
- <NodePlankHeading coordinate={layoutCoordinate} node={node} pending={!timedOut} />
51
+ <NodePlankHeading id={id} part={part} node={node} pending={!timedOut} />
51
52
  {timedOut ? <PlankContentError error={error} /> : <PlankLoading />}
52
53
  </>
53
54
  );
@@ -4,35 +4,32 @@
4
4
 
5
5
  import React, { useMemo } from 'react';
6
6
 
7
- import { Surface } from '@dxos/app-framework';
7
+ import { Surface, useCapability } from '@dxos/app-framework';
8
8
  import { Main } from '@dxos/react-ui';
9
- import { mx } from '@dxos/react-ui-theme';
10
9
 
11
- import { Banner } from './Banner';
12
- import { useBreakpoints } from '../../util';
13
- import { useHoistStatusbar } from '../../util/useHoistStatusbar';
14
- import { useLayout } from '../LayoutContext';
10
+ import { DeckCapabilities } from '../../capabilities';
11
+ import { layoutAppliesTopbar, useBreakpoints, useHoistStatusbar } from '../../util';
15
12
 
16
13
  export const Sidebar = () => {
17
- const layoutContext = useLayout();
18
- const { popoverAnchorId } = layoutContext;
14
+ const { popoverAnchorId, activeDeck: current } = useCapability(DeckCapabilities.DeckState);
19
15
  const breakpoint = useBreakpoints();
16
+ const topbar = layoutAppliesTopbar(breakpoint);
20
17
  const hoistStatusbar = useHoistStatusbar(breakpoint);
21
18
 
22
- const navigationData = useMemo(() => ({ popoverAnchorId }), [popoverAnchorId]);
19
+ const navigationData = useMemo(
20
+ () => ({ popoverAnchorId, topbar, hoistStatusbar, current }),
21
+ [popoverAnchorId, topbar, hoistStatusbar, current],
22
+ );
23
23
 
24
24
  return (
25
- <Main.NavigationSidebar classNames='grid grid-cols-1 grid-rows-[var(--rail-size)_var(--rail-action)_1fr_min-content_min-content] md:grid-rows-[var(--rail-size)_var(--rail-action)_1fr_min-content] lg:grid-rows-[1fr_min-content] overflow-hidden lg:block-start-[calc(env(safe-area-inset-top)+var(--rail-size))]'>
26
- {breakpoint !== 'desktop' && (
27
- <>
28
- <Banner variant='sidebar' />
29
- <Surface role='search-input' limit={1} />
30
- </>
31
- )}
32
- <div role='none' className={mx('!overflow-y-auto', breakpoint !== 'desktop' && 'border-be border-separator')}>
33
- <Surface role='navigation' data={navigationData} limit={1} />
34
- </div>
35
- {!hoistStatusbar && <Surface role='status-bar--sidebar-footer' limit={1} />}
25
+ <Main.NavigationSidebar
26
+ classNames={[
27
+ 'grid',
28
+ topbar && 'block-start-[calc(env(safe-area-inset-top)+var(--rail-size))]',
29
+ hoistStatusbar && 'block-end-[--statusbar-size]',
30
+ ]}
31
+ >
32
+ <Surface role='navigation' data={navigationData} limit={1} />
36
33
  </Main.NavigationSidebar>
37
34
  );
38
35
  };
@@ -4,29 +4,35 @@
4
4
 
5
5
  import React from 'react';
6
6
 
7
- import { IconButton, useTranslation } from '@dxos/react-ui';
7
+ import { useCapability } from '@dxos/app-framework';
8
+ import { IconButton, type IconButtonProps, type ThemedClassName, useTranslation } from '@dxos/react-ui';
8
9
 
10
+ import { DeckCapabilities } from '../../capabilities';
9
11
  import { DECK_PLUGIN } from '../../meta';
10
- import { useLayout } from '../LayoutContext';
11
12
 
12
- export const ToggleSidebarButton = () => {
13
- const layoutContext = useLayout();
13
+ export const ToggleSidebarButton = ({
14
+ classNames,
15
+ variant = 'ghost',
16
+ }: ThemedClassName<Pick<IconButtonProps, 'variant'>>) => {
17
+ const layoutContext = useCapability(DeckCapabilities.MutableDeckState);
14
18
  const { t } = useTranslation(DECK_PLUGIN);
15
19
  return (
16
20
  <IconButton
17
- variant='ghost'
21
+ variant={variant}
18
22
  iconOnly
19
23
  icon='ph--sidebar--regular'
20
24
  size={4}
21
25
  label={t('open navigation sidebar label')}
22
- onClick={() => (layoutContext.sidebarOpen = !layoutContext.sidebarOpen)}
23
- classNames='!pli-2 order-first'
26
+ onClick={() =>
27
+ (layoutContext.sidebarState = layoutContext.sidebarState === 'expanded' ? 'collapsed' : 'expanded')
28
+ }
29
+ classNames={classNames}
24
30
  />
25
31
  );
26
32
  };
27
33
 
28
34
  export const CloseSidebarButton = () => {
29
- const layoutContext = useLayout();
35
+ const layoutContext = useCapability(DeckCapabilities.MutableDeckState);
30
36
  const { t } = useTranslation(DECK_PLUGIN);
31
37
  return (
32
38
  <IconButton
@@ -35,40 +41,28 @@ export const CloseSidebarButton = () => {
35
41
  icon='ph--caret-line-left--regular'
36
42
  size={4}
37
43
  label={t('close navigation sidebar label')}
38
- onClick={() => (layoutContext.sidebarOpen = false)}
39
- classNames='!rounded-none !pli-1 ch-focus-ring-inset pie-[max(.5rem,env(safe-area-inset-left))]'
44
+ onClick={() => (layoutContext.sidebarState = 'collapsed')}
45
+ classNames='rounded-none pli-1 dx-focus-ring-inset pie-[max(.5rem,env(safe-area-inset-left))]'
40
46
  />
41
47
  );
42
48
  };
43
49
 
44
- export const ToggleComplementarySidebarButton = () => {
45
- const layoutContext = useLayout();
50
+ export const ToggleComplementarySidebarButton = ({ inR0, classNames }: ThemedClassName<{ inR0?: boolean }>) => {
51
+ const layoutContext = useCapability(DeckCapabilities.MutableDeckState);
46
52
  const { t } = useTranslation(DECK_PLUGIN);
47
53
  return (
48
54
  <IconButton
49
55
  iconOnly
50
- onClick={() => (layoutContext.complementarySidebarOpen = !layoutContext.complementarySidebarOpen)}
56
+ onClick={() =>
57
+ (layoutContext.complementarySidebarState =
58
+ layoutContext.complementarySidebarState === 'expanded' ? 'collapsed' : 'expanded')
59
+ }
51
60
  variant='ghost'
52
61
  label={t('open complementary sidebar label')}
53
- classNames='!pli-2 !plb-3 [&>svg]:-scale-x-100'
62
+ classNames={['[&>svg]:-scale-x-100', classNames]}
54
63
  icon='ph--sidebar-simple--regular'
55
- size={4}
56
- />
57
- );
58
- };
59
-
60
- export const CloseComplementarySidebarButton = () => {
61
- const layoutContext = useLayout();
62
- const { t } = useTranslation(DECK_PLUGIN);
63
- return (
64
- <IconButton
65
- iconOnly
66
- variant='ghost'
67
- size={4}
68
- icon='ph--caret-line-right--regular'
69
- label={t('close complementary sidebar label')}
70
- classNames='!rounded-none border-is border-separator ch-focus-ring-inset pie-2 lg:pie-[max(.5rem,env(safe-area-inset-right))]'
71
- onClick={() => (layoutContext.complementarySidebarOpen = false)}
64
+ size={inR0 ? 5 : 4}
65
+ tooltipSide={inR0 ? 'left' : undefined}
72
66
  />
73
67
  );
74
68
  };
@@ -5,23 +5,17 @@
5
5
  import React from 'react';
6
6
 
7
7
  import { Surface } from '@dxos/app-framework';
8
- import { mainPadding, mainPaddingTransitions, mx } from '@dxos/react-ui-theme';
9
-
10
- import { useMainSize } from '../../hooks';
8
+ import { useLandmarkMover } from '@dxos/react-ui';
11
9
 
12
10
  export const StatusBar = ({ showHints }: { showHints?: boolean }) => {
13
- const sizeAttrs = useMainSize();
11
+ const mover = useLandmarkMover(undefined, '3');
14
12
  return (
15
13
  <div
16
14
  role='contentinfo'
17
- {...sizeAttrs}
18
- className={mx(
19
- 'fixed block-end-0 inset-inline-0 flex justify-between items-center border-bs border-separator z-[2] pbe-[env(safe-area-inset-bottom)]',
20
- mainPadding,
21
- mainPaddingTransitions,
22
- )}
15
+ className='fixed block-end-0 inset-inline-0 bs-[--statusbar-size] border-bs border-separator z-[2] flex text-description'
16
+ {...mover}
23
17
  >
24
- <div role='none'>{showHints && <Surface role='hints' limit={1} />}</div>
18
+ {showHints && <Surface role='hints' limit={1} />}
25
19
  <Surface role='status-bar' limit={1} />
26
20
  </div>
27
21
  );
@@ -4,7 +4,7 @@
4
4
 
5
5
  import React from 'react';
6
6
 
7
- import type { Toast as ToastProps } from '@dxos/app-framework';
7
+ import { type LayoutAction } from '@dxos/app-framework';
8
8
  import {
9
9
  Button,
10
10
  Icon,
@@ -28,7 +28,7 @@ export const Toast = ({
28
28
  closeLabel,
29
29
  onAction,
30
30
  onOpenChange,
31
- }: ToastProps & Pick<ToastRootProps, 'onOpenChange'>) => {
31
+ }: LayoutAction.Toast & Pick<ToastRootProps, 'onOpenChange'>) => {
32
32
  const { t } = useTranslation(DECK_PLUGIN);
33
33
 
34
34
  return (
@@ -5,7 +5,7 @@
5
5
  import React from 'react';
6
6
 
7
7
  import { Input, Select, useTranslation } from '@dxos/react-ui';
8
- import { DeprecatedFormInput } from '@dxos/react-ui-form';
8
+ import { DeprecatedFormContainer, DeprecatedFormInput } from '@dxos/react-ui-form';
9
9
 
10
10
  import { DECK_PLUGIN } from '../meta';
11
11
  import {
@@ -22,7 +22,7 @@ export const LayoutSettings = ({ settings }: { settings: DeckSettingsProps }) =>
22
22
  const { t } = useTranslation(DECK_PLUGIN);
23
23
 
24
24
  return (
25
- <>
25
+ <DeprecatedFormContainer>
26
26
  <DeprecatedFormInput label={t('select new plank positioning label')}>
27
27
  <Select.Root
28
28
  value={settings.newPlankPositioning ?? 'start'}
@@ -72,12 +72,12 @@ export const LayoutSettings = ({ settings }: { settings: DeckSettingsProps }) =>
72
72
  />
73
73
  </DeprecatedFormInput>
74
74
  )}
75
- <DeprecatedFormInput label={t('settings custom slots')}>
76
- <Input.Switch checked={settings.customSlots} onCheckedChange={(checked) => (settings.customSlots = checked)} />
75
+ <DeprecatedFormInput label={t('settings enable ide-style statusbar label')}>
76
+ <Input.Switch
77
+ checked={settings.enableIdeStyleStatusbar}
78
+ onCheckedChange={(checked) => (settings.enableIdeStyleStatusbar = checked)}
79
+ />
77
80
  </DeprecatedFormInput>
78
- <DeprecatedFormInput label={t('settings flat deck')}>
79
- <Input.Switch checked={settings.flatDeck} onCheckedChange={(checked) => (settings.flatDeck = checked)} />
80
- </DeprecatedFormInput>
81
- </>
81
+ </DeprecatedFormContainer>
82
82
  );
83
83
  };
@@ -2,5 +2,13 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
+ import { mx } from '@dxos/react-ui-theme';
6
+
5
7
  export const soloInlinePadding =
6
8
  'pis-[calc(env(safe-area-inset-left)+.25rem)] pie-[calc(env(safe-area-inset-left)+.25rem)]';
9
+
10
+ const sidebarToggleStyles = 'bs-[--rail-item] is-[--rail-item] absolute block-end-2 z-[1] !bg-deck lg:hidden';
11
+
12
+ export const fixedSidebarToggleStyles = mx(sidebarToggleStyles, 'inline-start-2');
13
+
14
+ export const fixedComplementarySidebarToggleStyles = mx(sidebarToggleStyles, 'inline-end-2');
@@ -3,6 +3,4 @@
3
3
  //
4
4
 
5
5
  export * from './DeckLayout';
6
- export * from './DeckContext';
7
- export * from './LayoutContext';
8
6
  export * from './LayoutSettings';
@@ -5,9 +5,9 @@
5
5
  import { useMainContext } from '@dxos/react-ui';
6
6
 
7
7
  export const useMainSize = () => {
8
- const { navigationSidebarOpen, complementarySidebarOpen } = useMainContext('DeckPluginPlank');
8
+ const { navigationSidebarState, complementarySidebarState } = useMainContext('DeckPluginPlank');
9
9
  return {
10
- 'data-sidebar-inline-start-state': navigationSidebarOpen ? 'open' : 'closed',
11
- 'data-sidebar-inline-end-state': complementarySidebarOpen ? 'open' : 'closed',
10
+ 'data-sidebar-inline-start-state': navigationSidebarState,
11
+ 'data-sidebar-inline-end-state': complementarySidebarState,
12
12
  };
13
13
  };
@@ -34,7 +34,9 @@ export const useNode = <T = any>(graph: Graph, id?: string, timeout?: number): N
34
34
  if (node) {
35
35
  setNodeState(node);
36
36
  }
37
- } catch {}
37
+ } catch {
38
+ // TODO(ZaymonFC): This leaves the resolved node in an invalid state in the case of a timeout.
39
+ }
38
40
  });
39
41
 
40
42
  return () => cancelAnimationFrame(frame);