@dxos/plugin-deck 0.7.5-main.9d2a38b → 0.7.5-main.c41020f

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 (233) hide show
  1. package/dist/lib/browser/{app-graph-builder-67VRUD5K.mjs → app-graph-builder-IYHAGFA3.mjs} +61 -31
  2. package/dist/lib/browser/app-graph-builder-IYHAGFA3.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-5VFDMW5M.mjs → chunk-22AQ5IVX.mjs} +2 -2
  6. package/dist/lib/browser/chunk-22AQ5IVX.mjs.map +7 -0
  7. package/dist/lib/browser/chunk-FT33W5CI.mjs +128 -0
  8. package/dist/lib/browser/chunk-FT33W5CI.mjs.map +7 -0
  9. package/dist/lib/browser/chunk-G2X3ZDCE.mjs +24 -0
  10. package/dist/lib/browser/chunk-G2X3ZDCE.mjs.map +7 -0
  11. package/dist/lib/browser/chunk-KANJBSIX.mjs +97 -0
  12. package/dist/lib/browser/chunk-KANJBSIX.mjs.map +7 -0
  13. package/dist/lib/browser/{chunk-JQJ5UWVB.mjs → chunk-N7TEPFVR.mjs} +3 -2
  14. package/dist/lib/browser/{chunk-JQJ5UWVB.mjs.map → chunk-N7TEPFVR.mjs.map} +3 -3
  15. package/dist/lib/browser/chunk-O4RFYYQ6.mjs +1114 -0
  16. package/dist/lib/browser/chunk-O4RFYYQ6.mjs.map +7 -0
  17. package/dist/lib/browser/index.mjs +45 -78
  18. package/dist/lib/browser/index.mjs.map +4 -4
  19. package/dist/lib/browser/intent-resolver-ZD67BRUI.mjs +488 -0
  20. package/dist/lib/browser/intent-resolver-ZD67BRUI.mjs.map +7 -0
  21. package/dist/lib/browser/meta.json +1 -1
  22. package/dist/lib/browser/{react-root-UL7ZDRVZ.mjs → react-root-6ILKHD5J.mjs} +12 -17
  23. package/dist/lib/browser/react-root-6ILKHD5J.mjs.map +7 -0
  24. package/dist/lib/browser/react-surface-O75FKXAI.mjs +39 -0
  25. package/dist/lib/browser/react-surface-O75FKXAI.mjs.map +7 -0
  26. package/dist/lib/browser/{settings-FNWW6WIJ.mjs → settings-H35U6NHE.mjs} +6 -7
  27. package/dist/lib/browser/settings-H35U6NHE.mjs.map +7 -0
  28. package/dist/lib/browser/state-U4SHOPJW.mjs +129 -0
  29. package/dist/lib/browser/state-U4SHOPJW.mjs.map +7 -0
  30. package/dist/lib/browser/tools-64LXGLYR.mjs +59 -0
  31. package/dist/lib/browser/tools-64LXGLYR.mjs.map +7 -0
  32. package/dist/lib/browser/types.mjs +16 -4
  33. package/dist/lib/browser/url-handler-MVHTKUYA.mjs +72 -0
  34. package/dist/lib/browser/url-handler-MVHTKUYA.mjs.map +7 -0
  35. package/dist/types/src/DeckPlugin.d.ts.map +1 -1
  36. package/dist/types/src/capabilities/app-graph-builder.d.ts +181 -0
  37. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -0
  38. package/dist/types/src/capabilities/capabilities.d.ts +137 -8
  39. package/dist/types/src/capabilities/capabilities.d.ts.map +1 -1
  40. package/dist/types/src/capabilities/check-app-scheme.d.ts.map +1 -0
  41. package/dist/types/src/capabilities/index.d.ts +188 -3
  42. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  43. package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -0
  44. package/dist/types/src/capabilities/react-root.d.ts.map +1 -0
  45. package/dist/types/src/capabilities/react-surface.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 +79 -0
  48. package/dist/types/src/capabilities/state.d.ts.map +1 -0
  49. package/dist/types/src/capabilities/tools.d.ts +10 -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 +1 -2
  53. package/dist/types/src/components/DeckLayout/ActiveNode.d.ts.map +1 -1
  54. package/dist/types/src/components/DeckLayout/Banner.d.ts +1 -2
  55. package/dist/types/src/components/DeckLayout/Banner.d.ts.map +1 -1
  56. package/dist/types/src/components/DeckLayout/ComplementarySidebar.d.ts +1 -4
  57. package/dist/types/src/components/DeckLayout/ComplementarySidebar.d.ts.map +1 -1
  58. package/dist/types/src/components/DeckLayout/ContentEmpty.d.ts +1 -2
  59. package/dist/types/src/components/DeckLayout/ContentEmpty.d.ts.map +1 -1
  60. package/dist/types/src/components/DeckLayout/DeckLayout.d.ts +2 -7
  61. package/dist/types/src/components/DeckLayout/DeckLayout.d.ts.map +1 -1
  62. package/dist/types/src/components/DeckLayout/Fallback.d.ts +1 -2
  63. package/dist/types/src/components/DeckLayout/Fallback.d.ts.map +1 -1
  64. package/dist/types/src/components/DeckLayout/Fullscreen.d.ts +1 -2
  65. package/dist/types/src/components/DeckLayout/Fullscreen.d.ts.map +1 -1
  66. package/dist/types/src/components/DeckLayout/NodePlankHeading.d.ts +3 -3
  67. package/dist/types/src/components/DeckLayout/NodePlankHeading.d.ts.map +1 -1
  68. package/dist/types/src/components/DeckLayout/Plank.d.ts +8 -6
  69. package/dist/types/src/components/DeckLayout/Plank.d.ts.map +1 -1
  70. package/dist/types/src/components/DeckLayout/PlankControls.d.ts +2 -2
  71. package/dist/types/src/components/DeckLayout/PlankControls.d.ts.map +1 -1
  72. package/dist/types/src/components/DeckLayout/PlankError.d.ts +6 -6
  73. package/dist/types/src/components/DeckLayout/PlankError.d.ts.map +1 -1
  74. package/dist/types/src/components/DeckLayout/PlankLoading.d.ts +1 -2
  75. package/dist/types/src/components/DeckLayout/PlankLoading.d.ts.map +1 -1
  76. package/dist/types/src/components/DeckLayout/Sidebar.d.ts +1 -2
  77. package/dist/types/src/components/DeckLayout/Sidebar.d.ts.map +1 -1
  78. package/dist/types/src/components/DeckLayout/SidebarButton.d.ts +6 -5
  79. package/dist/types/src/components/DeckLayout/SidebarButton.d.ts.map +1 -1
  80. package/dist/types/src/components/DeckLayout/StatusBar.d.ts +1 -2
  81. package/dist/types/src/components/DeckLayout/StatusBar.d.ts.map +1 -1
  82. package/dist/types/src/components/DeckLayout/Toast.d.ts +2 -3
  83. package/dist/types/src/components/DeckLayout/Toast.d.ts.map +1 -1
  84. package/dist/types/src/components/DeckLayout/Topbar.d.ts +1 -2
  85. package/dist/types/src/components/DeckLayout/Topbar.d.ts.map +1 -1
  86. package/dist/types/src/components/LayoutSettings.d.ts +1 -2
  87. package/dist/types/src/components/LayoutSettings.d.ts.map +1 -1
  88. package/dist/types/src/components/fragments.d.ts +2 -0
  89. package/dist/types/src/components/fragments.d.ts.map +1 -1
  90. package/dist/types/src/components/index.d.ts +0 -2
  91. package/dist/types/src/components/index.d.ts.map +1 -1
  92. package/dist/types/src/events.d.ts +1 -0
  93. package/dist/types/src/events.d.ts.map +1 -1
  94. package/dist/types/src/hooks/useMainSize.d.ts +2 -2
  95. package/dist/types/src/hooks/useNode.d.ts.map +1 -1
  96. package/dist/types/src/layout.d.ts +5 -19
  97. package/dist/types/src/layout.d.ts.map +1 -1
  98. package/dist/types/src/meta.d.ts +1 -0
  99. package/dist/types/src/meta.d.ts.map +1 -1
  100. package/dist/types/src/translations.d.ts +3 -3
  101. package/dist/types/src/types.d.ts +117 -2
  102. package/dist/types/src/types.d.ts.map +1 -1
  103. package/dist/types/src/util/index.d.ts +3 -1
  104. package/dist/types/src/util/index.d.ts.map +1 -1
  105. package/dist/types/src/util/layoutAppliesTopbar.d.ts +2 -0
  106. package/dist/types/src/util/layoutAppliesTopbar.d.ts.map +1 -0
  107. package/dist/types/src/util/set-active.d.ts +9 -0
  108. package/dist/types/src/util/set-active.d.ts.map +1 -0
  109. package/dist/types/src/util/useHoistStatusbar.d.ts.map +1 -1
  110. package/package.json +32 -31
  111. package/src/DeckPlugin.ts +23 -59
  112. package/src/capabilities/{layout/app-graph-builder.ts → app-graph-builder.ts} +40 -28
  113. package/src/capabilities/capabilities.ts +5 -7
  114. package/src/capabilities/{navigation/check-app-scheme.ts → check-app-scheme.ts} +2 -2
  115. package/src/capabilities/index.ts +12 -3
  116. package/src/capabilities/intent-resolver.ts +368 -0
  117. package/src/capabilities/{layout/react-root.tsx → react-root.tsx} +8 -14
  118. package/src/capabilities/react-surface.tsx +31 -0
  119. package/src/capabilities/{settings/settings.ts → settings.ts} +4 -5
  120. package/src/capabilities/state.ts +108 -0
  121. package/src/capabilities/tools.ts +66 -0
  122. package/src/capabilities/url-handler.ts +65 -0
  123. package/src/components/DeckLayout/ActiveNode.tsx +2 -3
  124. package/src/components/DeckLayout/ComplementarySidebar.tsx +185 -77
  125. package/src/components/DeckLayout/ContentEmpty.tsx +7 -10
  126. package/src/components/DeckLayout/DeckLayout.tsx +141 -84
  127. package/src/components/DeckLayout/Fullscreen.tsx +2 -3
  128. package/src/components/DeckLayout/NodePlankHeading.tsx +57 -65
  129. package/src/components/DeckLayout/Plank.tsx +33 -41
  130. package/src/components/DeckLayout/PlankControls.tsx +12 -11
  131. package/src/components/DeckLayout/PlankError.tsx +6 -5
  132. package/src/components/DeckLayout/Sidebar.tsx +17 -20
  133. package/src/components/DeckLayout/SidebarButton.tsx +25 -31
  134. package/src/components/DeckLayout/StatusBar.tsx +5 -11
  135. package/src/components/DeckLayout/Toast.tsx +2 -2
  136. package/src/components/LayoutSettings.tsx +8 -8
  137. package/src/components/fragments.ts +8 -0
  138. package/src/components/index.ts +0 -2
  139. package/src/events.ts +1 -0
  140. package/src/hooks/useMainSize.ts +3 -3
  141. package/src/hooks/useNode.ts +3 -1
  142. package/src/layout.ts +43 -212
  143. package/src/meta.ts +1 -0
  144. package/src/translations.ts +8 -8
  145. package/src/types.ts +103 -4
  146. package/src/util/index.ts +3 -1
  147. package/src/util/layoutAppliesTopbar.ts +7 -0
  148. package/src/util/set-active.ts +47 -0
  149. package/src/util/useHoistStatusbar.ts +13 -8
  150. package/dist/lib/browser/app-graph-builder-67VRUD5K.mjs.map +0 -7
  151. package/dist/lib/browser/chunk-2M4PXYNB.mjs +0 -1052
  152. package/dist/lib/browser/chunk-2M4PXYNB.mjs.map +0 -7
  153. package/dist/lib/browser/chunk-2PJNBVCY.mjs +0 -39
  154. package/dist/lib/browser/chunk-2PJNBVCY.mjs.map +0 -7
  155. package/dist/lib/browser/chunk-4C2AFTET.mjs +0 -186
  156. package/dist/lib/browser/chunk-4C2AFTET.mjs.map +0 -7
  157. package/dist/lib/browser/chunk-5VFDMW5M.mjs.map +0 -7
  158. package/dist/lib/browser/chunk-KY5WXIXY.mjs +0 -44
  159. package/dist/lib/browser/chunk-KY5WXIXY.mjs.map +0 -7
  160. package/dist/lib/browser/deck-PLCSKPGL.mjs +0 -26
  161. package/dist/lib/browser/deck-PLCSKPGL.mjs.map +0 -7
  162. package/dist/lib/browser/intent-resolver-FVOQSTBX.mjs +0 -152
  163. package/dist/lib/browser/intent-resolver-FVOQSTBX.mjs.map +0 -7
  164. package/dist/lib/browser/intent-resolver-K7GW4A2I.mjs +0 -249
  165. package/dist/lib/browser/intent-resolver-K7GW4A2I.mjs.map +0 -7
  166. package/dist/lib/browser/location-QHRBQBQN.mjs +0 -35
  167. package/dist/lib/browser/location-QHRBQBQN.mjs.map +0 -7
  168. package/dist/lib/browser/react-context-3BDW7W2N.mjs +0 -32
  169. package/dist/lib/browser/react-context-3BDW7W2N.mjs.map +0 -7
  170. package/dist/lib/browser/react-root-UL7ZDRVZ.mjs.map +0 -7
  171. package/dist/lib/browser/react-surface-VPNOGGNN.mjs +0 -28
  172. package/dist/lib/browser/react-surface-VPNOGGNN.mjs.map +0 -7
  173. package/dist/lib/browser/settings-FNWW6WIJ.mjs.map +0 -7
  174. package/dist/lib/browser/state-7I5BD7SE.mjs +0 -34
  175. package/dist/lib/browser/state-7I5BD7SE.mjs.map +0 -7
  176. package/dist/lib/browser/url-handler-Z5B7LD3N.mjs +0 -76
  177. package/dist/lib/browser/url-handler-Z5B7LD3N.mjs.map +0 -7
  178. package/dist/types/src/capabilities/layout/app-graph-builder.d.ts +0 -181
  179. package/dist/types/src/capabilities/layout/app-graph-builder.d.ts.map +0 -1
  180. package/dist/types/src/capabilities/layout/deck.d.ts +0 -4
  181. package/dist/types/src/capabilities/layout/deck.d.ts.map +0 -1
  182. package/dist/types/src/capabilities/layout/index.d.ts +0 -229
  183. package/dist/types/src/capabilities/layout/index.d.ts.map +0 -1
  184. package/dist/types/src/capabilities/layout/intent-resolver.d.ts.map +0 -1
  185. package/dist/types/src/capabilities/layout/react-context.d.ts +0 -8
  186. package/dist/types/src/capabilities/layout/react-context.d.ts.map +0 -1
  187. package/dist/types/src/capabilities/layout/react-root.d.ts.map +0 -1
  188. package/dist/types/src/capabilities/layout/state.d.ts +0 -42
  189. package/dist/types/src/capabilities/layout/state.d.ts.map +0 -1
  190. package/dist/types/src/capabilities/navigation/check-app-scheme.d.ts.map +0 -1
  191. package/dist/types/src/capabilities/navigation/index.d.ts +0 -5
  192. package/dist/types/src/capabilities/navigation/index.d.ts.map +0 -1
  193. package/dist/types/src/capabilities/navigation/intent-resolver.d.ts +0 -4
  194. package/dist/types/src/capabilities/navigation/intent-resolver.d.ts.map +0 -1
  195. package/dist/types/src/capabilities/navigation/location.d.ts +0 -4
  196. package/dist/types/src/capabilities/navigation/location.d.ts.map +0 -1
  197. package/dist/types/src/capabilities/navigation/set-location.d.ts +0 -10
  198. package/dist/types/src/capabilities/navigation/set-location.d.ts.map +0 -1
  199. package/dist/types/src/capabilities/navigation/url-handler.d.ts.map +0 -1
  200. package/dist/types/src/capabilities/settings/index.d.ts +0 -3
  201. package/dist/types/src/capabilities/settings/index.d.ts.map +0 -1
  202. package/dist/types/src/capabilities/settings/react-surface.d.ts.map +0 -1
  203. package/dist/types/src/capabilities/settings/settings.d.ts.map +0 -1
  204. package/dist/types/src/components/DeckContext.d.ts +0 -11
  205. package/dist/types/src/components/DeckContext.d.ts.map +0 -1
  206. package/dist/types/src/components/LayoutContext.d.ts +0 -5
  207. package/dist/types/src/components/LayoutContext.d.ts.map +0 -1
  208. package/dist/types/src/layout.test.d.ts +0 -2
  209. package/dist/types/src/layout.test.d.ts.map +0 -1
  210. package/dist/types/src/util/layout-parts.d.ts +0 -7
  211. package/dist/types/src/util/layout-parts.d.ts.map +0 -1
  212. package/src/capabilities/layout/deck.ts +0 -25
  213. package/src/capabilities/layout/index.ts +0 -12
  214. package/src/capabilities/layout/intent-resolver.ts +0 -128
  215. package/src/capabilities/layout/react-context.tsx +0 -26
  216. package/src/capabilities/layout/state.ts +0 -32
  217. package/src/capabilities/navigation/index.ts +0 -10
  218. package/src/capabilities/navigation/intent-resolver.ts +0 -216
  219. package/src/capabilities/navigation/location.ts +0 -28
  220. package/src/capabilities/navigation/set-location.ts +0 -38
  221. package/src/capabilities/navigation/url-handler.ts +0 -67
  222. package/src/capabilities/settings/index.ts +0 -8
  223. package/src/capabilities/settings/react-surface.tsx +0 -23
  224. package/src/components/DeckContext.ts +0 -19
  225. package/src/components/LayoutContext.ts +0 -12
  226. package/src/layout.test.ts +0 -380
  227. package/src/util/layout-parts.ts +0 -12
  228. /package/dist/types/src/capabilities/{navigation/check-app-scheme.d.ts → check-app-scheme.d.ts} +0 -0
  229. /package/dist/types/src/capabilities/{layout/intent-resolver.d.ts → intent-resolver.d.ts} +0 -0
  230. /package/dist/types/src/capabilities/{layout/react-root.d.ts → react-root.d.ts} +0 -0
  231. /package/dist/types/src/capabilities/{settings/react-surface.d.ts → react-surface.d.ts} +0 -0
  232. /package/dist/types/src/capabilities/{settings/settings.d.ts → settings.d.ts} +0 -0
  233. /package/dist/types/src/capabilities/{navigation/url-handler.d.ts → url-handler.d.ts} +0 -0
@@ -1,38 +0,0 @@
1
- //
2
- // Copyright 2025 DXOS.org
3
- //
4
-
5
- import { openIds, type Layout, type LayoutParts, type Capabilities } from '@dxos/app-framework';
6
- import { type AttentionManager } from '@dxos/plugin-attention';
7
-
8
- export type SetLocationOptions = {
9
- next: LayoutParts;
10
- location: Capabilities.MutableLocation;
11
- layout: Layout;
12
- attention?: AttentionManager;
13
- };
14
-
15
- export const setLocation = ({ next, location, layout, attention }: SetLocationOptions) => {
16
- const part = layout.layoutMode === 'solo' ? 'solo' : 'main';
17
- const ids = openIds(next, [part]);
18
-
19
- const current = openIds(location.active, [part]);
20
- const removed = current.filter((id) => !ids.includes(id));
21
- const closed = Array.from(new Set([...location.closed.filter((id) => !ids.includes(id)), ...removed]));
22
-
23
- location.closed = closed;
24
- location.active = next;
25
-
26
- if (attention) {
27
- const attended = attention.current;
28
- const [attendedId] = Array.from(attended);
29
- const isAttendedAvailable = !!attendedId && ids.includes(attendedId);
30
- if (!isAttendedAvailable) {
31
- const currentIds = location.active[part]?.map(({ id }) => id) ?? [];
32
- const attendedIndex = currentIds.indexOf(attendedId);
33
- // If outside of bounds, focus on the first/last plank, otherwise focus on the new plank in the same position.
34
- const index = attendedIndex === -1 ? 0 : attendedIndex >= ids.length ? ids.length - 1 : attendedIndex;
35
- return next[part]?.[index].id;
36
- }
37
- }
38
- };
@@ -1,67 +0,0 @@
1
- //
2
- // Copyright 2025 DXOS.org
3
- //
4
-
5
- import {
6
- Capabilities,
7
- contributes,
8
- createIntent,
9
- LayoutAction,
10
- type LayoutParts,
11
- type PluginsContext,
12
- } from '@dxos/app-framework';
13
- import { scheduledEffect } from '@dxos/echo-signals/core';
14
- import { AttentionCapabilities } from '@dxos/plugin-attention';
15
-
16
- import { setLocation as naturalSetLocation } from './set-location';
17
- import { NAV_ID } from '../../components';
18
- import { mergeLayoutParts, removePart, soloPartToUri, uriToSoloPart } from '../../layout';
19
-
20
- export default async (context: PluginsContext) => {
21
- const { dispatchPromise: dispatch } = context.requestCapability(Capabilities.IntentDispatcher) ?? {};
22
- const location = context.requestCapability(Capabilities.MutableLocation);
23
- const layout = context.requestCapability(Capabilities.MutableLayout);
24
- const attention = context.requestCapability(AttentionCapabilities.Attention);
25
-
26
- const handleNavigation = async () => {
27
- const setLocation = (next: LayoutParts) => naturalSetLocation({ next, layout, location, attention });
28
-
29
- const pathname = window.location.pathname;
30
- if (pathname === '/reset') {
31
- setLocation({ sidebar: [{ id: NAV_ID }] });
32
- location.closed = [];
33
- layout.layoutMode = 'solo';
34
- window.location.pathname = '/';
35
- return;
36
- }
37
-
38
- const startingLayout = removePart(location.active, 'solo');
39
- const layoutFromUri = uriToSoloPart(pathname);
40
- if (!layoutFromUri) {
41
- const toAttend = setLocation(startingLayout);
42
- layout.layoutMode = 'deck';
43
- await dispatch?.(createIntent(LayoutAction.ScrollIntoView, { id: toAttend }));
44
- return;
45
- }
46
-
47
- const toAttend = setLocation(mergeLayoutParts(layoutFromUri, startingLayout));
48
- layout.layoutMode = 'solo';
49
- await dispatch?.(createIntent(LayoutAction.ScrollIntoView, { id: toAttend }));
50
- };
51
-
52
- await handleNavigation();
53
- window.addEventListener('popstate', handleNavigation);
54
-
55
- const unsubscribe = scheduledEffect(
56
- () => ({ selectedPath: soloPartToUri(location.active) }),
57
- ({ selectedPath }) => {
58
- // TODO(thure): In some browsers, this only preserves the most recent state change, even though this is not `history.replace`…
59
- history.pushState(null, '', `/${selectedPath}${window.location.search}`);
60
- },
61
- );
62
-
63
- return contributes(Capabilities.Null, null, () => {
64
- window.removeEventListener('popstate', handleNavigation);
65
- unsubscribe();
66
- });
67
- };
@@ -1,8 +0,0 @@
1
- //
2
- // Copyright 2025 DXOS.org
3
- //
4
-
5
- import { lazy } from '@dxos/app-framework';
6
-
7
- export const ReactSurface = lazy(() => import('./react-surface'));
8
- export const DeckSettings = lazy(() => import('./settings'));
@@ -1,23 +0,0 @@
1
- //
2
- // Copyright 2025 DXOS.org
3
- //
4
-
5
- import React from 'react';
6
-
7
- import { Capabilities, contributes, useCapability } from '@dxos/app-framework';
8
-
9
- import { LayoutSettings } from '../../components';
10
- import { DECK_PLUGIN } from '../../meta';
11
- import { type DeckSettingsProps } from '../../types';
12
-
13
- export default () =>
14
- contributes(Capabilities.ReactSurface, {
15
- id: DECK_PLUGIN,
16
- role: 'settings',
17
- filter: (data): data is any => data.subject === DECK_PLUGIN,
18
- component: () => {
19
- const store = useCapability(Capabilities.SettingsStore);
20
- const settings = store.getStore<DeckSettingsProps>(DECK_PLUGIN)!.value;
21
- return <LayoutSettings settings={settings} />;
22
- },
23
- });
@@ -1,19 +0,0 @@
1
- //
2
- // Copyright 2023 DXOS.org
3
- //
4
-
5
- import { type Context, createContext, useContext } from 'react';
6
-
7
- import { type LayoutMode } from '@dxos/app-framework';
8
- import { raise } from '@dxos/debug';
9
-
10
- export type PlankSizing = Record<string, number>;
11
- export type DeckContextType = {
12
- plankSizing: PlankSizing;
13
- currentUndoId: string | undefined;
14
- layoutModeHistory: LayoutMode[];
15
- };
16
-
17
- export const DeckContext: Context<DeckContextType | null> = createContext<DeckContextType | null>(null);
18
-
19
- export const useDeckContext = (): DeckContextType => useContext(DeckContext) ?? raise(new Error('Missing DeckContext'));
@@ -1,12 +0,0 @@
1
- //
2
- // Copyright 2023 DXOS.org
3
- //
4
-
5
- import { type Context, createContext, useContext } from 'react';
6
-
7
- import type { Layout } from '@dxos/app-framework';
8
- import { raise } from '@dxos/debug';
9
-
10
- export const LayoutContext: Context<Layout | null> = createContext<Layout | null>(null);
11
-
12
- export const useLayout = (): Layout => useContext(LayoutContext) ?? raise(new Error('Missing LayoutContext'));
@@ -1,380 +0,0 @@
1
- //
2
- // Copyright 2024 DXOS.org
3
- //
4
-
5
- import { expect, describe, test } from 'vitest';
6
-
7
- import { type LayoutParts, type LayoutAdjustment, type LayoutEntry } from '@dxos/app-framework';
8
-
9
- import { uriToActiveParts, activePartsToUri, incrementPlank, mergeLayoutParts, openEntry } from './layout';
10
-
11
- describe('Layout URI parsing and formatting', () => {
12
- test('uriToActiveParts parses a simple URI correctly', () => {
13
- const uri = 'https://composer.space/main-id1~path1+id2_sidebar-id3';
14
- const result = uriToActiveParts(uri);
15
- expect(result).to.deep.equal({
16
- main: [{ id: 'id1', path: 'path1' }, { id: 'id2' }],
17
- sidebar: [{ id: 'id3' }],
18
- });
19
- });
20
-
21
- test('activePartsToUri formats a simple object correctly', () => {
22
- const activeParts: LayoutParts = {
23
- main: [{ id: 'id1', path: 'path1' }, { id: 'id2' }],
24
- sidebar: [{ id: 'id3' }],
25
- };
26
- const result = activePartsToUri(activeParts);
27
- expect(result).to.equal('main-id1~path1+id2_sidebar-id3');
28
- });
29
-
30
- test('activePartsToUri handles complex cases with multiple parts, and simple paths', () => {
31
- const complexActiveParts: LayoutParts = {
32
- main: [{ id: 'id1', path: 'path1' }, { id: 'id2' }, { id: 'id3', path: 'path3' }],
33
- sidebar: [{ id: 'id4' }, { id: 'id5', path: 'path5' }],
34
- complementary: [{ id: 'id6', path: 'path6' }, { id: 'id7' }],
35
- };
36
- const result = activePartsToUri(complexActiveParts);
37
- expect(result).to.equal('main-id1~path1+id2+id3~path3_sidebar-id4+id5~path5_complementary-id6~path6+id7');
38
- });
39
-
40
- test('Round trip: URI to object and back to URI', () => {
41
- const originalUri = 'main-id1~path1+id2_sidebar-id3_complementary-id4~path4';
42
- const activeParts = uriToActiveParts(originalUri);
43
- const resultUri = activePartsToUri(activeParts);
44
- expect(resultUri).to.equal(originalUri);
45
- });
46
-
47
- test('Round trip: object to URI and back to object', () => {
48
- const originalParts: LayoutParts = {
49
- main: [{ id: 'id1', path: 'path1' }, { id: 'id2' }],
50
- sidebar: [{ id: 'id3' }],
51
- complementary: [{ id: 'id4', path: 'path4' }],
52
- };
53
- const uri = activePartsToUri(originalParts);
54
- const resultParts = uriToActiveParts(`https://composer.space/${uri}`);
55
- expect(resultParts).to.deep.equal(originalParts);
56
- });
57
-
58
- test('uriToActiveParts handles missing parts', () => {
59
- const uri = 'https://composer.space/main-id1~path1_sidebar-id2';
60
- const result = uriToActiveParts(uri);
61
- expect(result).to.deep.equal({
62
- main: [{ id: 'id1', path: 'path1' }],
63
- sidebar: [{ id: 'id2' }],
64
- });
65
- });
66
-
67
- test('activePartsToUri excludes empty parts', () => {
68
- const activeParts: LayoutParts = {
69
- main: [{ id: 'id1', path: 'path1' }],
70
- };
71
- const result = activePartsToUri(activeParts);
72
- expect(result).to.equal('main-id1~path1');
73
- });
74
- });
75
-
76
- describe('Layout adjustment', () => {
77
- test('adjustLayout moves an item left in the main part', () => {
78
- const layout: LayoutParts = {
79
- main: [{ id: 'id1' }, { id: 'id2' }, { id: 'id3' }],
80
- sidebar: [{ id: 'sid1' }],
81
- };
82
- const adjustment: LayoutAdjustment = {
83
- layoutCoordinate: { part: 'main', entryId: 'id2' },
84
- type: 'increment-start',
85
- };
86
- const result = incrementPlank(layout, adjustment);
87
- expect(result.main).to.deep.equal([{ id: 'id2' }, { id: 'id1' }, { id: 'id3' }]);
88
- expect(result.sidebar).to.deep.equal([{ id: 'sid1' }]);
89
- });
90
-
91
- test('adjustLayout moves an item right in the main part', () => {
92
- const layout: LayoutParts = {
93
- main: [{ id: 'id1' }, { id: 'id2' }, { id: 'id3' }],
94
- sidebar: [{ id: 'sid1' }],
95
- };
96
- const adjustment: LayoutAdjustment = {
97
- layoutCoordinate: { part: 'main', entryId: 'id2' },
98
- type: 'increment-end',
99
- };
100
- const result = incrementPlank(layout, adjustment);
101
- expect(result.main).to.deep.equal([{ id: 'id1' }, { id: 'id3' }, { id: 'id2' }]);
102
- expect(result.sidebar).to.deep.equal([{ id: 'sid1' }]);
103
- });
104
-
105
- test('adjustLayout does not move items in non-main parts', () => {
106
- const layout: LayoutParts = {
107
- main: [{ id: 'id1' }],
108
- sidebar: [{ id: 'sid1' }, { id: 'sid2' }, { id: 'sid3' }],
109
- };
110
- const adjustment: LayoutAdjustment = {
111
- layoutCoordinate: { part: 'sidebar', entryId: 'sid2' },
112
- type: 'increment-end',
113
- };
114
- const result = incrementPlank(layout, adjustment);
115
- expect(result).to.deep.equal(layout);
116
- });
117
-
118
- test('adjustLayout does not move the first item left in main', () => {
119
- const layout: LayoutParts = {
120
- main: [{ id: 'id1' }, { id: 'id2' }],
121
- };
122
- const adjustment: LayoutAdjustment = {
123
- layoutCoordinate: { part: 'main', entryId: 'id1' },
124
- type: 'increment-start',
125
- };
126
- const result = incrementPlank(layout, adjustment);
127
- expect(result).to.deep.equal(layout);
128
- });
129
-
130
- test('adjustLayout does not move the last item right in main', () => {
131
- const layout: LayoutParts = {
132
- main: [{ id: 'id1' }, { id: 'id2' }],
133
- };
134
- const adjustment: LayoutAdjustment = {
135
- layoutCoordinate: { part: 'main', entryId: 'id2' },
136
- type: 'increment-end',
137
- };
138
- const result = incrementPlank(layout, adjustment);
139
- expect(result).to.deep.equal(layout);
140
- });
141
-
142
- test('adjustLayout handles non-existent slugId in main', () => {
143
- const layout: LayoutParts = {
144
- main: [{ id: 'id1' }, { id: 'id2' }],
145
- };
146
- const adjustment: LayoutAdjustment = {
147
- layoutCoordinate: { part: 'main', entryId: 'id3' },
148
- type: 'increment-start',
149
- };
150
- const result = incrementPlank(layout, adjustment);
151
- expect(result).to.deep.equal(layout);
152
- });
153
-
154
- test('adjustLayout preserves other parts when adjusting main', () => {
155
- const layout: LayoutParts = {
156
- main: [{ id: 'id1' }, { id: 'id2' }],
157
- sidebar: [{ id: 'sid1' }],
158
- complementary: [{ id: 'cid1' }],
159
- };
160
- const adjustment: LayoutAdjustment = {
161
- layoutCoordinate: { part: 'main', entryId: 'id2' },
162
- type: 'increment-start',
163
- };
164
- const result = incrementPlank(layout, adjustment);
165
- expect(result.main).to.deep.equal([{ id: 'id2' }, { id: 'id1' }]);
166
- expect(result.sidebar).to.deep.equal([{ id: 'sid1' }]);
167
- expect(result.complementary).to.deep.equal([{ id: 'cid1' }]);
168
- });
169
-
170
- test('adjustLayout handles empty main part', () => {
171
- const layout: LayoutParts = {
172
- main: [],
173
- sidebar: [{ id: 'sid1' }],
174
- };
175
- const adjustment: LayoutAdjustment = {
176
- layoutCoordinate: { part: 'main', entryId: 'id1' },
177
- type: 'increment-start',
178
- };
179
- const result = incrementPlank(layout, adjustment);
180
- expect(result).to.deep.equal(layout);
181
- });
182
-
183
- test('adjustLayout handles undefined main part', () => {
184
- const layout: LayoutParts = {
185
- sidebar: [{ id: 'sid1' }],
186
- };
187
- const adjustment: LayoutAdjustment = {
188
- layoutCoordinate: { part: 'main', entryId: 'id1' },
189
- type: 'increment-start',
190
- };
191
- const result = incrementPlank(layout, adjustment);
192
- expect(result).to.deep.equal(layout);
193
- });
194
-
195
- test('adjustLayout handles main part with only one item', () => {
196
- const layout: LayoutParts = {
197
- main: [{ id: 'id1' }],
198
- };
199
- const adjustment: LayoutAdjustment = {
200
- layoutCoordinate: { part: 'main', entryId: 'id1' },
201
- type: 'increment-end',
202
- };
203
- const result = incrementPlank(layout, adjustment);
204
- expect(result).to.deep.equal(layout);
205
- });
206
- });
207
-
208
- describe('Layout parts merging', () => {
209
- test('merges two simple layout parts', () => {
210
- const part1: LayoutParts = { main: [{ id: 'id1' }] };
211
- const part2: LayoutParts = { sidebar: [{ id: 'id2' }] };
212
- const result = mergeLayoutParts(part1, part2);
213
- expect(result).to.deep.equal({
214
- main: [{ id: 'id1' }],
215
- sidebar: [{ id: 'id2' }],
216
- });
217
- });
218
-
219
- test('replaces entries with the same id in the same part', () => {
220
- const part1: LayoutParts = { main: [{ id: 'id1', path: 'path1' }] };
221
- const part2: LayoutParts = { main: [{ id: 'id1', path: 'path2' }] };
222
- const result = mergeLayoutParts(part1, part2);
223
- expect(result).to.deep.equal({
224
- main: [{ id: 'id1', path: 'path2' }],
225
- });
226
- });
227
-
228
- test('merges multiple layout parts', () => {
229
- const part1: LayoutParts = { main: [{ id: 'id1' }] };
230
- const part2: LayoutParts = { sidebar: [{ id: 'id2' }] };
231
- const part3: LayoutParts = { complementary: [{ id: 'id3' }] };
232
- const result = mergeLayoutParts(part1, part2, part3);
233
- expect(result).to.deep.equal({
234
- main: [{ id: 'id1' }],
235
- sidebar: [{ id: 'id2' }],
236
- complementary: [{ id: 'id3' }],
237
- });
238
- });
239
-
240
- test('handles empty layout parts', () => {
241
- const part1: LayoutParts = { main: [{ id: 'id1' }] };
242
- const part2: LayoutParts = {};
243
- const result = mergeLayoutParts(part1, part2);
244
- expect(result).to.deep.equal({
245
- main: [{ id: 'id1' }],
246
- });
247
- });
248
-
249
- test('merges parts with multiple entries', () => {
250
- const part1: LayoutParts = { main: [{ id: 'id1' }, { id: 'id2' }] };
251
- const part2: LayoutParts = { main: [{ id: 'id3' }], sidebar: [{ id: 'id4' }] };
252
- const result = mergeLayoutParts(part1, part2);
253
- expect(result).to.deep.equal({
254
- main: [{ id: 'id1' }, { id: 'id2' }, { id: 'id3' }],
255
- sidebar: [{ id: 'id4' }],
256
- });
257
- });
258
-
259
- test('replaces entries with the same id and keeps unique entries', () => {
260
- const part1: LayoutParts = {
261
- main: [{ id: 'id1', path: 'path1' }, { id: 'id2' }],
262
- sidebar: [{ id: 'id3' }],
263
- };
264
- const part2: LayoutParts = {
265
- main: [{ id: 'id1', path: 'path2' }, { id: 'id4' }],
266
- complementary: [{ id: 'id5' }],
267
- };
268
- const result = mergeLayoutParts(part1, part2);
269
- expect(result).to.deep.equal({
270
- main: [{ id: 'id1', path: 'path2' }, { id: 'id2' }, { id: 'id4' }],
271
- sidebar: [{ id: 'id3' }],
272
- complementary: [{ id: 'id5' }],
273
- });
274
- });
275
-
276
- test('merges complex layout parts', () => {
277
- const part1: LayoutParts = {
278
- main: [{ id: 'id1', path: 'path1' }, { id: 'id2' }],
279
- sidebar: [{ id: 'id3' }],
280
- };
281
- const part2: LayoutParts = {
282
- main: [{ id: 'id1', path: 'path2' }, { id: 'id4' }],
283
- complementary: [{ id: 'id5' }],
284
- };
285
- const part3: LayoutParts = {
286
- sidebar: [{ id: 'id6' }],
287
- fullScreen: [{ id: 'id7' }],
288
- };
289
- const result = mergeLayoutParts(part1, part2, part3);
290
- expect(result).to.deep.equal({
291
- main: [{ id: 'id1', path: 'path2' }, { id: 'id2' }, { id: 'id4' }],
292
- sidebar: [{ id: 'id3' }, { id: 'id6' }],
293
- complementary: [{ id: 'id5' }],
294
- fullScreen: [{ id: 'id7' }],
295
- });
296
- });
297
-
298
- test('handles merging with duplicate entries in the same part', () => {
299
- const part1: LayoutParts = {
300
- main: [{ id: 'id1' }, { id: 'id1' }, { id: 'id2' }],
301
- };
302
- const result = mergeLayoutParts(part1);
303
- expect(result).to.deep.equal({
304
- main: [{ id: 'id1' }, { id: 'id2' }],
305
- });
306
- });
307
-
308
- test('preserves order of entries when merging', () => {
309
- const part1: LayoutParts = { main: [{ id: 'id1' }, { id: 'id2' }] };
310
- const part2: LayoutParts = { main: [{ id: 'id3' }, { id: 'id1' }] };
311
- const result = mergeLayoutParts(part1, part2);
312
- expect(result).to.deep.equal({
313
- main: [{ id: 'id1' }, { id: 'id2' }, { id: 'id3' }],
314
- });
315
- });
316
- });
317
-
318
- describe('openEntry', () => {
319
- const initialLayout: LayoutParts = {
320
- main: [
321
- { id: 'id1', path: 'path1' },
322
- { id: 'id2', path: 'path2' },
323
- { id: 'id3', path: 'path3' },
324
- ],
325
- sidebar: [{ id: 'sid1', path: 'sidepath1' }],
326
- };
327
-
328
- const newEntry: LayoutEntry = { id: 'new', path: 'newpath' };
329
-
330
- test('adds entry to start of main without pivot', () => {
331
- const result = openEntry(initialLayout, 'main', newEntry, { positioning: 'start' });
332
- expect(result.main?.[0]).to.deep.equal(newEntry);
333
- expect(result.main?.length).to.equal(4);
334
- });
335
-
336
- test('adds entry to end of main without pivot', () => {
337
- const result = openEntry(initialLayout, 'main', newEntry, { positioning: 'end' });
338
- expect(result.main?.[result.main.length - 1]).to.deep.equal(newEntry);
339
- expect(result.main?.length).to.equal(4);
340
- });
341
-
342
- test('adds entry before pivot in main', () => {
343
- const result = openEntry(initialLayout, 'main', newEntry, { positioning: 'start', pivotId: 'id2' });
344
- expect(result.main?.[1]).to.deep.equal(newEntry);
345
- expect(result.main?.length).to.equal(4);
346
- });
347
-
348
- test('adds entry after pivot in main', () => {
349
- const result = openEntry(initialLayout, 'main', newEntry, { positioning: 'end', pivotId: 'id2' });
350
- expect(result.main?.[2]).to.deep.equal(newEntry);
351
- expect(result.main?.length).to.equal(4);
352
- });
353
-
354
- test('adds entry to start when pivot is not found', () => {
355
- const result = openEntry(initialLayout, 'main', newEntry, { positioning: 'start', pivotId: 'nonexistent' });
356
- expect(result.main?.[0]).to.deep.equal(newEntry);
357
- expect(result.main?.length).to.equal(4);
358
- });
359
-
360
- test('does not add duplicate entry to main', () => {
361
- const result = openEntry(initialLayout, 'main', initialLayout.main![0], { positioning: 'start' });
362
- expect(result.main).to.deep.equal(initialLayout.main);
363
- });
364
-
365
- test('replaces entry in non-main part', () => {
366
- const result = openEntry(initialLayout, 'sidebar', newEntry);
367
- expect(result.sidebar).to.deep.equal([newEntry]);
368
- });
369
-
370
- test('creates new part if it does not exist', () => {
371
- const result = openEntry(initialLayout, 'complementary', newEntry);
372
- expect(result.complementary).to.deep.equal([newEntry]);
373
- });
374
-
375
- test('handles undefined main part', () => {
376
- const layoutWithoutMain: LayoutParts = { sidebar: [{ id: 'sid1', path: 'sidepath1' }] };
377
- const result = openEntry(layoutWithoutMain, 'main', newEntry);
378
- expect(result.main).to.deep.equal([newEntry]);
379
- });
380
- });
@@ -1,12 +0,0 @@
1
- //
2
- // Copyright 2024 DXOS.org
3
- //
4
-
5
- import { type LayoutMode, type LayoutPart } from '@dxos/app-framework';
6
-
7
- /**
8
- * If in solo mode and the part is the main part, open it in solo mode.
9
- * From the dispatch POV we refer to both 'solo' and 'main' as 'main'.
10
- */
11
- export const getEffectivePart = (partName: LayoutPart, layoutMode: LayoutMode): LayoutPart =>
12
- layoutMode === 'solo' && partName === 'main' ? 'solo' : partName;