@dxos/plugin-deck 0.8.4-main.406dc2a → 0.8.4-main.548089c

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 (81) hide show
  1. package/dist/lib/browser/{app-graph-builder-YYP67JHW.mjs → app-graph-builder-2DE73K5P.mjs} +5 -30
  2. package/dist/lib/browser/app-graph-builder-2DE73K5P.mjs.map +7 -0
  3. package/dist/lib/browser/{check-app-scheme-GCOL6YDT.mjs → check-app-scheme-HIEVFAAX.mjs} +2 -2
  4. package/dist/lib/browser/{chunk-VX7MMQOW.mjs → chunk-27I7DJUG.mjs} +4 -4
  5. package/dist/lib/browser/{chunk-JQKOS2HB.mjs → chunk-2YHPKFFA.mjs} +55 -50
  6. package/dist/lib/browser/chunk-2YHPKFFA.mjs.map +7 -0
  7. package/dist/lib/browser/{chunk-HUWUYTOI.mjs → chunk-5KMJPIQC.mjs} +2 -2
  8. package/dist/lib/browser/{chunk-RJP5R7PY.mjs → chunk-ABGD5GHY.mjs} +16 -15
  9. package/dist/lib/browser/chunk-ABGD5GHY.mjs.map +7 -0
  10. package/dist/lib/browser/{chunk-7I6H3N4Q.mjs → chunk-F3VCCHVL.mjs} +2 -2
  11. package/dist/lib/browser/chunk-UXLU6CMW.mjs +16 -0
  12. package/dist/lib/browser/chunk-UXLU6CMW.mjs.map +7 -0
  13. package/dist/lib/browser/index.mjs +5 -5
  14. package/dist/lib/browser/{intent-resolver-7XNOEPVN.mjs → intent-resolver-Q3KETDSS.mjs} +4 -4
  15. package/dist/lib/browser/meta.json +1 -1
  16. package/dist/lib/browser/{react-root-OJEF7YCH.mjs → react-root-EXJMQNOO.mjs} +9 -8
  17. package/dist/lib/browser/react-root-EXJMQNOO.mjs.map +7 -0
  18. package/dist/lib/browser/{react-surface-XN2NJYHO.mjs → react-surface-D5R4UUKV.mjs} +7 -7
  19. package/dist/lib/browser/{settings-M3KSKRAP.mjs → settings-SDPTOCCM.mjs} +3 -3
  20. package/dist/lib/browser/state-QTVNH7N6.mjs +12 -0
  21. package/dist/lib/browser/toolkit-L5CFXJCF.mjs +52 -0
  22. package/dist/lib/browser/toolkit-L5CFXJCF.mjs.map +7 -0
  23. package/dist/lib/browser/types/index.mjs +2 -2
  24. package/dist/lib/browser/{url-handler-EHTLXZRR.mjs → url-handler-QEYGYE2H.mjs} +4 -4
  25. package/dist/types/src/capabilities/react-root.d.ts.map +1 -1
  26. package/dist/types/src/capabilities/toolkit.d.ts +21 -2
  27. package/dist/types/src/capabilities/toolkit.d.ts.map +1 -1
  28. package/dist/types/src/components/DeckLayout/DeckLayout.stories.d.ts.map +1 -1
  29. package/dist/types/src/components/DeckLayout/DeckMain.d.ts.map +1 -1
  30. package/dist/types/src/components/DeckLayout/Popover.d.ts.map +1 -1
  31. package/dist/types/src/components/Plank/Plank.d.ts.map +1 -1
  32. package/dist/types/src/components/Plank/PlankControls.d.ts.map +1 -1
  33. package/dist/types/src/components/Plank/PlankHeading.d.ts.map +1 -1
  34. package/dist/types/src/components/Sidebar/ComplementarySidebar.d.ts.map +1 -1
  35. package/dist/types/src/components/Sidebar/SidebarButton.d.ts.map +1 -1
  36. package/dist/types/src/hooks/useDeckCompanions.d.ts.map +1 -1
  37. package/dist/types/src/hooks/useHoistStatusbar.d.ts.map +1 -1
  38. package/dist/types/src/meta.d.ts.map +1 -1
  39. package/dist/types/tsconfig.tsbuildinfo +1 -1
  40. package/package.json +33 -33
  41. package/src/capabilities/app-graph-builder.ts +19 -19
  42. package/src/capabilities/react-root.tsx +2 -1
  43. package/src/capabilities/toolkit.ts +23 -14
  44. package/src/components/DeckLayout/ActiveNode.tsx +1 -1
  45. package/src/components/DeckLayout/Banner.tsx +1 -1
  46. package/src/components/DeckLayout/ContentEmpty.tsx +1 -1
  47. package/src/components/DeckLayout/DeckLayout.stories.tsx +7 -8
  48. package/src/components/DeckLayout/DeckLayout.tsx +1 -1
  49. package/src/components/DeckLayout/DeckMain.tsx +6 -10
  50. package/src/components/DeckLayout/Dialog.tsx +1 -1
  51. package/src/components/DeckLayout/Popover.tsx +2 -11
  52. package/src/components/DeckLayout/StatusBar.tsx +1 -1
  53. package/src/components/DeckLayout/Toast.tsx +1 -1
  54. package/src/components/Plank/Plank.tsx +51 -35
  55. package/src/components/Plank/PlankControls.tsx +3 -2
  56. package/src/components/Plank/PlankHeading.tsx +5 -4
  57. package/src/components/Sidebar/ComplementarySidebar.tsx +2 -2
  58. package/src/components/Sidebar/Sidebar.tsx +1 -1
  59. package/src/components/Sidebar/SidebarButton.tsx +7 -6
  60. package/src/hooks/useCompanions.ts +1 -1
  61. package/src/hooks/useDeckCompanions.ts +2 -1
  62. package/src/hooks/useHoistStatusbar.ts +2 -1
  63. package/src/meta.ts +5 -0
  64. package/dist/lib/browser/app-graph-builder-YYP67JHW.mjs.map +0 -7
  65. package/dist/lib/browser/chunk-JQKOS2HB.mjs.map +0 -7
  66. package/dist/lib/browser/chunk-MHP4GPX5.mjs +0 -11
  67. package/dist/lib/browser/chunk-MHP4GPX5.mjs.map +0 -7
  68. package/dist/lib/browser/chunk-RJP5R7PY.mjs.map +0 -7
  69. package/dist/lib/browser/react-root-OJEF7YCH.mjs.map +0 -7
  70. package/dist/lib/browser/state-6ZSDTF6Q.mjs +0 -12
  71. package/dist/lib/browser/toolkit-L7C3UAEU.mjs +0 -63
  72. package/dist/lib/browser/toolkit-L7C3UAEU.mjs.map +0 -7
  73. /package/dist/lib/browser/{check-app-scheme-GCOL6YDT.mjs.map → check-app-scheme-HIEVFAAX.mjs.map} +0 -0
  74. /package/dist/lib/browser/{chunk-VX7MMQOW.mjs.map → chunk-27I7DJUG.mjs.map} +0 -0
  75. /package/dist/lib/browser/{chunk-HUWUYTOI.mjs.map → chunk-5KMJPIQC.mjs.map} +0 -0
  76. /package/dist/lib/browser/{chunk-7I6H3N4Q.mjs.map → chunk-F3VCCHVL.mjs.map} +0 -0
  77. /package/dist/lib/browser/{intent-resolver-7XNOEPVN.mjs.map → intent-resolver-Q3KETDSS.mjs.map} +0 -0
  78. /package/dist/lib/browser/{react-surface-XN2NJYHO.mjs.map → react-surface-D5R4UUKV.mjs.map} +0 -0
  79. /package/dist/lib/browser/{settings-M3KSKRAP.mjs.map → settings-SDPTOCCM.mjs.map} +0 -0
  80. /package/dist/lib/browser/{state-6ZSDTF6Q.mjs.map → state-QTVNH7N6.mjs.map} +0 -0
  81. /package/dist/lib/browser/{url-handler-EHTLXZRR.mjs.map → url-handler-QEYGYE2H.mjs.map} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/plugin-deck",
3
- "version": "0.8.4-main.406dc2a",
3
+ "version": "0.8.4-main.548089c",
4
4
  "description": "DXOS Surface plugin for the main application layout.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -40,52 +40,52 @@
40
40
  "@preact/signals-core": "^1.12.1",
41
41
  "@radix-ui/react-context": "1.1.1",
42
42
  "immer": "^10.1.1",
43
- "@dxos/ai": "0.8.4-main.406dc2a",
44
- "@dxos/app-framework": "0.8.4-main.406dc2a",
45
- "@dxos/assistant": "0.8.4-main.406dc2a",
46
- "@dxos/async": "0.8.4-main.406dc2a",
47
- "@dxos/blueprints": "0.8.4-main.406dc2a",
48
- "@dxos/invariant": "0.8.4-main.406dc2a",
49
- "@dxos/live-object": "0.8.4-main.406dc2a",
50
- "@dxos/local-storage": "0.8.4-main.406dc2a",
51
- "@dxos/echo": "0.8.4-main.406dc2a",
52
- "@dxos/log": "0.8.4-main.406dc2a",
53
- "@dxos/plugin-attention": "0.8.4-main.406dc2a",
54
- "@dxos/plugin-graph": "0.8.4-main.406dc2a",
55
- "@dxos/keyboard": "0.8.4-main.406dc2a",
56
- "@dxos/plugin-observability": "0.8.4-main.406dc2a",
57
- "@dxos/debug": "0.8.4-main.406dc2a",
58
- "@dxos/react-ui-attention": "0.8.4-main.406dc2a",
59
- "@dxos/react-client": "0.8.4-main.406dc2a",
60
- "@dxos/plugin-theme": "0.8.4-main.406dc2a",
61
- "@dxos/react-ui-stack": "0.8.4-main.406dc2a",
62
- "@dxos/react-ui-form": "0.8.4-main.406dc2a",
63
- "@dxos/react-ui-tabs": "0.8.4-main.406dc2a",
64
- "@dxos/react-ui-text-tooltip": "0.8.4-main.406dc2a",
65
- "@dxos/util": "0.8.4-main.406dc2a",
66
- "@dxos/echo-signals": "0.8.4-main.406dc2a"
43
+ "@dxos/ai": "0.8.4-main.548089c",
44
+ "@dxos/assistant": "0.8.4-main.548089c",
45
+ "@dxos/app-framework": "0.8.4-main.548089c",
46
+ "@dxos/async": "0.8.4-main.548089c",
47
+ "@dxos/blueprints": "0.8.4-main.548089c",
48
+ "@dxos/debug": "0.8.4-main.548089c",
49
+ "@dxos/echo": "0.8.4-main.548089c",
50
+ "@dxos/echo-signals": "0.8.4-main.548089c",
51
+ "@dxos/invariant": "0.8.4-main.548089c",
52
+ "@dxos/keyboard": "0.8.4-main.548089c",
53
+ "@dxos/plugin-attention": "0.8.4-main.548089c",
54
+ "@dxos/plugin-graph": "0.8.4-main.548089c",
55
+ "@dxos/plugin-theme": "0.8.4-main.548089c",
56
+ "@dxos/plugin-observability": "0.8.4-main.548089c",
57
+ "@dxos/react-client": "0.8.4-main.548089c",
58
+ "@dxos/react-ui-attention": "0.8.4-main.548089c",
59
+ "@dxos/live-object": "0.8.4-main.548089c",
60
+ "@dxos/react-ui-form": "0.8.4-main.548089c",
61
+ "@dxos/local-storage": "0.8.4-main.548089c",
62
+ "@dxos/react-ui-stack": "0.8.4-main.548089c",
63
+ "@dxos/log": "0.8.4-main.548089c",
64
+ "@dxos/react-ui-tabs": "0.8.4-main.548089c",
65
+ "@dxos/react-ui-text-tooltip": "0.8.4-main.548089c",
66
+ "@dxos/util": "0.8.4-main.548089c"
67
67
  },
68
68
  "devDependencies": {
69
- "@effect-rx/rx-react": "0.42.4",
69
+ "@effect-atom/atom-react": "^0.3.4",
70
70
  "@effect/platform": "0.92.1",
71
71
  "@types/react": "~19.2.2",
72
- "@types/react-dom": "~19.2.1",
72
+ "@types/react-dom": "~19.2.2",
73
73
  "effect": "3.18.3",
74
74
  "react": "~19.2.0",
75
75
  "react-dom": "~19.2.0",
76
76
  "vite": "7.1.9",
77
- "@dxos/react-ui": "0.8.4-main.406dc2a",
78
- "@dxos/react-ui-theme": "0.8.4-main.406dc2a",
79
- "@dxos/storybook-utils": "0.8.4-main.406dc2a"
77
+ "@dxos/react-ui": "0.8.4-main.548089c",
78
+ "@dxos/react-ui-theme": "0.8.4-main.548089c",
79
+ "@dxos/storybook-utils": "0.8.4-main.548089c"
80
80
  },
81
81
  "peerDependencies": {
82
- "@effect-rx/rx-react": "^0.34.1",
82
+ "@effect-atom/atom-react": "^0.3.4",
83
83
  "@effect/platform": "^0.80.12",
84
84
  "effect": "^3.13.3",
85
85
  "react": "^19.0.0",
86
86
  "react-dom": "^19.0.0",
87
- "@dxos/react-ui": "0.8.4-main.406dc2a",
88
- "@dxos/react-ui-theme": "0.8.4-main.406dc2a"
87
+ "@dxos/react-ui": "0.8.4-main.548089c",
88
+ "@dxos/react-ui-theme": "0.8.4-main.548089c"
89
89
  },
90
90
  "publishConfig": {
91
91
  "access": "public"
@@ -2,7 +2,7 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { Rx } from '@effect-rx/rx-react';
5
+ import { Atom } from '@effect-atom/atom-react';
6
6
  import * as Function from 'effect/Function';
7
7
  import * as Option from 'effect/Option';
8
8
 
@@ -20,7 +20,7 @@ export default (context: PluginContext) =>
20
20
  createExtension({
21
21
  id: meta.id,
22
22
  actions: (node) =>
23
- Rx.make((get) =>
23
+ Atom.make((get) =>
24
24
  Function.pipe(
25
25
  get(node),
26
26
  Option.flatMap((node) => (node.id === ROOT_ID ? Option.some(node) : Option.none())),
@@ -29,23 +29,23 @@ export default (context: PluginContext) =>
29
29
 
30
30
  // NOTE(Zan): This is currently disabled.
31
31
  // TODO(Zan): Fullscreen needs to know the active node and provide that to the layout part.
32
- const _fullscreen = {
33
- id: `${LayoutAction.UpdateLayout._tag}/fullscreen`,
34
- data: async () => {
35
- const { dispatchPromise: dispatch } = context.getCapability(Capabilities.IntentDispatcher);
36
- await dispatch(
37
- createIntent(LayoutAction.SetLayoutMode, { part: 'mode', options: { mode: 'fullscreen' } }),
38
- );
39
- },
40
- properties: {
41
- label: ['toggle fullscreen label', { ns: meta.id }],
42
- icon: 'ph--arrows-out--regular',
43
- keyBinding: {
44
- macos: 'ctrl+meta+f',
45
- windows: 'shift+ctrl+f',
46
- },
47
- },
48
- };
32
+ // const _fullscreen = {
33
+ // id: `${LayoutAction.UpdateLayout._tag}/fullscreen`,
34
+ // data: async () => {
35
+ // const { dispatchPromise: dispatch } = context.getCapability(Capabilities.IntentDispatcher);
36
+ // await dispatch(
37
+ // createIntent(LayoutAction.SetLayoutMode, { part: 'mode', options: { mode: 'fullscreen' } }),
38
+ // );
39
+ // },
40
+ // properties: {
41
+ // label: ['toggle fullscreen label', { ns: meta.id }],
42
+ // icon: 'ph--arrows-out--regular',
43
+ // keyBinding: {
44
+ // macos: 'ctrl+meta+f',
45
+ // windows: 'shift+ctrl+f',
46
+ // },
47
+ // },
48
+ // };
49
49
 
50
50
  const closeCurrent = {
51
51
  id: `${LayoutAction.Close._tag}/current`,
@@ -4,7 +4,8 @@
4
4
 
5
5
  import React, { useCallback } from 'react';
6
6
 
7
- import { Capabilities, contributes, useCapability } from '@dxos/app-framework';
7
+ import { Capabilities, contributes } from '@dxos/app-framework';
8
+ import { useCapability } from '@dxos/app-framework/react';
8
9
 
9
10
  import { DeckLayout } from '../components';
10
11
  import { meta } from '../meta';
@@ -7,14 +7,22 @@ import * as Toolkit from '@effect/ai/Toolkit';
7
7
  import * as Effect from 'effect/Effect';
8
8
  import * as Schema from 'effect/Schema';
9
9
 
10
- import { Capabilities, LayoutAction, type PluginContext, contributes, createIntent } from '@dxos/app-framework';
10
+ import {
11
+ Capabilities,
12
+ type Capability,
13
+ LayoutAction,
14
+ type PluginContext,
15
+ contributes,
16
+ createIntent,
17
+ } from '@dxos/app-framework';
18
+ import { GenericToolkit } from '@dxos/assistant';
11
19
  import { ArtifactId } from '@dxos/assistant';
12
20
  import { type SpaceId } from '@dxos/keys';
13
21
  import { trim } from '@dxos/util';
14
22
 
15
23
  import { DeckCapabilities } from './capabilities';
16
24
 
17
- class DeckToolkit extends Toolkit.make(
25
+ const Toolkit$ = Toolkit.make(
18
26
  Tool.make('open-item', {
19
27
  description: trim`
20
28
  Opens an item in the application.
@@ -25,17 +33,19 @@ class DeckToolkit extends Toolkit.make(
25
33
  success: Schema.Any,
26
34
  failure: Schema.Never,
27
35
  }),
28
- ) {
29
- static layer = (context: PluginContext) =>
30
- DeckToolkit.toLayer({
36
+ );
37
+
38
+ export namespace DeckToolkit {
39
+ export const Toolkit = Toolkit$;
40
+
41
+ export const createLayer = (context: PluginContext) =>
42
+ Toolkit$.toLayer({
31
43
  'open-item': ({ id }) =>
32
44
  Effect.gen(function* () {
33
45
  const state = context.getCapability(DeckCapabilities.DeckState);
34
- const dxn = ArtifactId.toDXN(id, state.activeDeck as SpaceId);
35
-
36
- // TODO(wittjosiah): Support other variants.
37
- const echoDxn = dxn.asEchoDXN();
38
- if (!echoDxn) {
46
+ const dxn = ArtifactId.toDXN(id, state.activeDeck as SpaceId).asEchoDXN();
47
+ if (!dxn) {
48
+ // TODO(wittjosiah): Support other variants.
39
49
  throw new Error(`Invalid object ID: ${id}`);
40
50
  }
41
51
 
@@ -43,7 +53,7 @@ class DeckToolkit extends Toolkit.make(
43
53
  const { dispatch } = context.getCapability(Capabilities.IntentDispatcher);
44
54
  yield* dispatch(
45
55
  createIntent(LayoutAction.Open, {
46
- subject: [`${echoDxn.spaceId!}:${echoDxn.echoId}`],
56
+ subject: [`${dxn.spaceId!}:${dxn.echoId}`],
47
57
  part: 'main',
48
58
  }),
49
59
  );
@@ -51,7 +61,6 @@ class DeckToolkit extends Toolkit.make(
51
61
  });
52
62
  }
53
63
 
54
- export default (context: PluginContext) => [
55
- contributes(Capabilities.Toolkit, DeckToolkit),
56
- contributes(Capabilities.ToolkitHandler, DeckToolkit.layer(context)),
64
+ export default (context: PluginContext): Capability<any>[] => [
65
+ contributes(Capabilities.Toolkit, GenericToolkit.make(DeckToolkit.Toolkit, DeckToolkit.createLayer(context))),
57
66
  ];
@@ -4,7 +4,7 @@
4
4
 
5
5
  import React from 'react';
6
6
 
7
- import { Surface, useAppGraph } from '@dxos/app-framework';
7
+ import { Surface, useAppGraph } from '@dxos/app-framework/react';
8
8
  import { useNode } from '@dxos/plugin-graph';
9
9
  import { useAttended } from '@dxos/react-ui-attention';
10
10
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  import React from 'react';
6
6
 
7
- import { Surface } from '@dxos/app-framework';
7
+ import { Surface } from '@dxos/app-framework/react';
8
8
  import { type ThemedClassName, useTranslation } from '@dxos/react-ui';
9
9
  import { mx } from '@dxos/react-ui-theme';
10
10
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  import React from 'react';
6
6
 
7
- import { Surface, useCapability } from '@dxos/app-framework';
7
+ import { Surface, useCapability } from '@dxos/app-framework/react';
8
8
 
9
9
  import { DeckCapabilities } from '../../capabilities';
10
10
  import { useBreakpoints } from '../../hooks';
@@ -20,9 +20,7 @@ import { DeckLayout } from './DeckLayout';
20
20
  const meta = {
21
21
  title: 'plugins/plugin-deck/DeckLayout',
22
22
  component: DeckLayout,
23
- render: (args) => {
24
- return <DeckLayout {...args} />;
25
- },
23
+ render: (args) => <DeckLayout {...args} />,
26
24
  decorators: [
27
25
  withTheme,
28
26
  withPluginManager({
@@ -37,6 +35,11 @@ const meta = {
37
35
  name: 'Testing',
38
36
  },
39
37
  () => [
38
+ defineModule({
39
+ id: `${pluginMeta.id}/module/deck-state`,
40
+ activatesOn: Events.AppGraphReady,
41
+ activate: () => DeckStateFactory(),
42
+ }),
40
43
  defineModule({
41
44
  id: `${pluginMeta.id}/module/layout-intent-resolver`,
42
45
  activatesOn: Events.SetupIntentResolver,
@@ -45,8 +48,6 @@ const meta = {
45
48
  ],
46
49
  )(),
47
50
  ],
48
- // TODO(burdon): Remove?
49
- capabilities: () => DeckStateFactory(),
50
51
  }),
51
52
  ],
52
53
  parameters: {
@@ -59,6 +60,4 @@ export default meta;
59
60
 
60
61
  type Story = StoryObj<typeof meta>;
61
62
 
62
- export const Default: Story = {
63
- args: {},
64
- };
63
+ export const Default: Story = {};
@@ -4,7 +4,7 @@
4
4
 
5
5
  import React from 'react';
6
6
 
7
- import { useCapability } from '@dxos/app-framework';
7
+ import { useCapability } from '@dxos/app-framework/react';
8
8
 
9
9
  import { DeckCapabilities } from '../../capabilities';
10
10
 
@@ -5,14 +5,8 @@
5
5
  import { untracked } from '@preact/signals-core';
6
6
  import React, { Fragment, type UIEvent, useCallback, useEffect, useMemo, useRef } from 'react';
7
7
 
8
- import {
9
- Capabilities,
10
- LayoutAction,
11
- createIntent,
12
- useCapability,
13
- useIntentDispatcher,
14
- usePluginManager,
15
- } from '@dxos/app-framework';
8
+ import { Capabilities, LayoutAction, createIntent } from '@dxos/app-framework';
9
+ import { useCapability, useIntentDispatcher, usePluginManager } from '@dxos/app-framework/react';
16
10
  import { AttentionCapabilities } from '@dxos/plugin-attention';
17
11
  import { Main, type MainProps, useMediaQuery, useOnTransition } from '@dxos/react-ui';
18
12
  import { DEFAULT_HORIZONTAL_SIZE, Stack, StackContext } from '@dxos/react-ui-stack';
@@ -85,7 +79,7 @@ export const DeckMain = () => {
85
79
  // When deck is disabled in settings, set to solo mode if the current layout mode is deck.
86
80
  // TODO(thure): Applying this as an effect should be avoided over emitting the intent only when the setting changes.
87
81
  useEffect(() => {
88
- if (settings?.enableDeck && layoutMode === 'deck') {
82
+ if (!settings?.enableDeck && layoutMode === 'deck') {
89
83
  void dispatch(
90
84
  createIntent(LayoutAction.SetLayoutMode, { part: 'mode', subject: active[0], options: { mode: 'solo' } }),
91
85
  );
@@ -155,8 +149,8 @@ export const DeckMain = () => {
155
149
  return (
156
150
  <Main.Root
157
151
  navigationSidebarState={fullscreen ? 'closed' : context.sidebarState}
158
- onNavigationSidebarStateChange={(next) => (context.sidebarState = next)}
159
152
  complementarySidebarState={fullscreen ? 'closed' : context.complementarySidebarState}
153
+ onNavigationSidebarStateChange={(next) => (context.sidebarState = next)}
160
154
  onComplementarySidebarStateChange={(next) => (context.complementarySidebarState = next)}
161
155
  >
162
156
  {/* Left sidebar. */}
@@ -201,6 +195,7 @@ export const DeckMain = () => {
201
195
  } as MainProps['style']
202
196
  }
203
197
  >
198
+ {/* Deck mode. */}
204
199
  <div
205
200
  role='none'
206
201
  className={!solo ? 'relative bg-deckSurface overflow-hidden' : 'sr-only'}
@@ -238,6 +233,7 @@ export const DeckMain = () => {
238
233
  ))}
239
234
  </Stack>
240
235
  </div>
236
+ {/* Solo mode. */}
241
237
  <div
242
238
  role='none'
243
239
  className={solo ? 'relative overflow-hidden bg-deckSurface' : 'sr-only'}
@@ -4,7 +4,7 @@
4
4
 
5
5
  import React from 'react';
6
6
 
7
- import { Surface, useCapability } from '@dxos/app-framework';
7
+ import { Surface, useCapability } from '@dxos/app-framework/react';
8
8
  import { AlertDialog, Dialog as NaturalDialog } from '@dxos/react-ui';
9
9
 
10
10
  import { DeckCapabilities } from '../../capabilities';
@@ -3,9 +3,9 @@
3
3
  //
4
4
 
5
5
  import { createContext } from '@radix-ui/react-context';
6
- import React, { type PropsWithChildren, useCallback, useEffect, useMemo, useRef, useState } from 'react';
6
+ import React, { type PropsWithChildren, useCallback, useEffect, useRef, useState } from 'react';
7
7
 
8
- import { Surface, useCapability } from '@dxos/app-framework';
8
+ import { Surface, useCapability } from '@dxos/app-framework/react';
9
9
  import { Popover, type PopoverContentInteractOutsideEvent } from '@dxos/react-ui';
10
10
 
11
11
  import { DeckCapabilities } from '../../capabilities';
@@ -76,21 +76,12 @@ export const PopoverContent = () => {
76
76
  [setOpen],
77
77
  );
78
78
 
79
- const collisionBoundaries: HTMLElement[] = useMemo(() => {
80
- const closest = layout.popoverAnchor?.closest('[data-popover-collision-boundary]') as
81
- | HTMLElement
82
- | null
83
- | undefined;
84
- return closest ? [closest] : [];
85
- }, [layout.popoverAnchor]);
86
-
87
79
  return (
88
80
  <Popover.Portal>
89
81
  <Popover.Content
90
82
  side={layout.popoverSide}
91
83
  onInteractOutside={handleClose}
92
84
  onEscapeKeyDown={handleClose}
93
- collisionBoundary={collisionBoundaries}
94
85
  sticky='always'
95
86
  hideWhenDetached
96
87
  >
@@ -4,7 +4,7 @@
4
4
 
5
5
  import React from 'react';
6
6
 
7
- import { Surface } from '@dxos/app-framework';
7
+ import { Surface } from '@dxos/app-framework/react';
8
8
  import { useLandmarkMover } from '@dxos/react-ui';
9
9
 
10
10
  export const StatusBar = ({ showHints }: { showHints?: boolean }) => {
@@ -35,7 +35,7 @@ export const Toast = ({
35
35
  <NaturalToast.Root data-testid={id} defaultOpen duration={duration} onOpenChange={onOpenChange}>
36
36
  <NaturalToast.Body>
37
37
  <NaturalToast.Title classNames='items-center'>
38
- {icon && <Icon icon={icon} size={5} classNames='inline mr-1' />}
38
+ {icon && <Icon icon={icon} classNames='inline mr-1' />}
39
39
  {title && <span>{toLocalizedString(title, t)}</span>}
40
40
  </NaturalToast.Title>
41
41
  {description && (
@@ -2,6 +2,7 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
+ import { useFocusFinders } from '@fluentui/react-tabster';
5
6
  import React, {
6
7
  type KeyboardEvent,
7
8
  type PropsWithChildren,
@@ -12,14 +13,8 @@ import React, {
12
13
  useRef,
13
14
  } from 'react';
14
15
 
15
- import {
16
- LayoutAction,
17
- Surface,
18
- createIntent,
19
- useAppGraph,
20
- useCapability,
21
- useIntentDispatcher,
22
- } from '@dxos/app-framework';
16
+ import { LayoutAction, createIntent } from '@dxos/app-framework';
17
+ import { Surface, useAppGraph, useCapability, useIntentDispatcher } from '@dxos/app-framework/react';
23
18
  import { debounce } from '@dxos/async';
24
19
  import { type Node, useNode } from '@dxos/plugin-graph';
25
20
  import { ATTENDABLE_PATH_SEPARATOR, useAttentionAttributes } from '@dxos/react-ui-attention';
@@ -37,6 +32,10 @@ import { PlankLoading } from './PlankLoading';
37
32
 
38
33
  const UNKNOWN_ID = 'unknown_id';
39
34
 
35
+ //
36
+ // Plank
37
+ //
38
+
40
39
  export type PlankProps = Pick<PlankComponentProps, 'layoutMode' | 'part' | 'path' | 'order' | 'active' | 'settings'> & {
41
40
  id?: string;
42
41
  companionId?: string;
@@ -96,12 +95,13 @@ export const Plank = memo(({ id = UNKNOWN_ID, companionId, ...props }: PlankProp
96
95
  );
97
96
  });
98
97
 
99
- const PlankContainer = ({
100
- children,
101
- solo,
102
- companion,
103
- encapsulate,
104
- }: PropsWithChildren<{ solo: boolean; companion: boolean; encapsulate: boolean }>) => {
98
+ //
99
+ // PlankContainer
100
+ //
101
+
102
+ type PlankContainerProps = PropsWithChildren<{ solo: boolean; companion: boolean; encapsulate: boolean }>;
103
+
104
+ const PlankContainer = ({ children, solo, companion, encapsulate }: PlankContainerProps) => {
105
105
  const sizeAttrs = useMainSize();
106
106
  if (!solo) {
107
107
  return children;
@@ -111,10 +111,11 @@ const PlankContainer = ({
111
111
  return (
112
112
  <div
113
113
  role='none'
114
+ data-popover-collision-boundary={true}
114
115
  className={mx(
115
116
  'absolute inset-[--main-spacing] grid',
116
117
  encapsulate && 'border border-separator rounded overflow-hidden',
117
- companion && 'grid-cols-[6fr_4fr]',
118
+ companion && 'grid-cols-[6fr_4fr]', // TODO(burdon): Resize.
118
119
  railGridHorizontal,
119
120
  mainIntrinsicSize,
120
121
  )}
@@ -125,6 +126,10 @@ const PlankContainer = ({
125
126
  );
126
127
  };
127
128
 
129
+ //
130
+ // PlankComponent
131
+ //
132
+
128
133
  type PlankComponentProps = {
129
134
  layoutMode: LayoutMode;
130
135
  id: string;
@@ -132,7 +137,6 @@ type PlankComponentProps = {
132
137
  path?: string[];
133
138
  order?: number;
134
139
  active?: string[];
135
- // TODO(burdon): Change to role?
136
140
  companioned?: 'primary' | 'companion';
137
141
  node?: Node;
138
142
  primary?: Node;
@@ -156,6 +160,7 @@ const PlankComponent = memo(
156
160
  }: PlankComponentProps) => {
157
161
  const { dispatchPromise: dispatch } = useIntentDispatcher();
158
162
  const { deck, popoverAnchorId, scrollIntoView } = useCapability(DeckCapabilities.DeckState);
163
+ const { findFirstFocusable } = useFocusFinders();
159
164
  const canResize = layoutMode === 'deck';
160
165
 
161
166
  const attentionAttrs = useAttentionAttributes(primary?.id ?? id);
@@ -179,8 +184,15 @@ const PlankComponent = memo(
179
184
 
180
185
  // TODO(thure): Tabster’s focus group should handle moving focus to Main, but something is blocking it.
181
186
  const handleKeyDown = useCallback((event: KeyboardEvent) => {
182
- if (event.target === event.currentTarget && event.key === 'Escape') {
183
- rootElement.current?.closest('main')?.focus();
187
+ if (event.target === event.currentTarget) {
188
+ switch (event.key) {
189
+ case 'Escape':
190
+ rootElement.current?.closest('main')?.focus();
191
+ break;
192
+ case 'Enter':
193
+ rootElement.current && findFirstFocusable(rootElement.current)?.focus();
194
+ break;
195
+ }
184
196
  }
185
197
  }, []);
186
198
 
@@ -216,14 +228,16 @@ const PlankComponent = memo(
216
228
  const placeholder = useMemo(() => <PlankLoading />, []);
217
229
 
218
230
  const Root = part.startsWith('solo') ? 'article' : StackItem.Root;
231
+ const fullscreen = layoutMode === 'solo--fullscreen';
219
232
  const className = mx(
220
233
  'attention-surface relative dx-focus-ring-inset-over-all density-coarse',
221
- isSolo && mainIntrinsicSize,
222
- isSolo && railGridHorizontal,
223
234
  isSolo && 'absolute inset-0',
235
+ isSolo && mainIntrinsicSize,
236
+ railGridHorizontal,
224
237
  part.startsWith('solo') && 'grid',
238
+ part.startsWith('solo-') && 'grid-rows-subgrid row-span-2 min-is-0',
239
+ fullscreen && 'grid-rows-1',
225
240
  part === 'deck' && (companioned === 'companion' ? '!border-separator border-ie' : '!border-separator border-li'),
226
- part.startsWith('solo-') && 'row-span-2 grid-rows-subgrid min-is-0',
227
241
  part === 'solo-companion' && '!border-separator border-is',
228
242
  settings?.encapsulatedPlanks &&
229
243
  !part.startsWith('solo') &&
@@ -234,6 +248,7 @@ const PlankComponent = memo(
234
248
  <Root
235
249
  ref={rootElement}
236
250
  data-testid='deck.plank'
251
+ data-popover-collision-boundary={true}
237
252
  tabIndex={0}
238
253
  {...(part.startsWith('solo')
239
254
  ? ({ ...sizeAttrs, className } as any)
@@ -250,19 +265,21 @@ const PlankComponent = memo(
250
265
  >
251
266
  {node ? (
252
267
  <>
253
- <PlankHeading
254
- id={id}
255
- part={part.startsWith('solo-') ? 'solo' : part}
256
- node={node}
257
- layoutMode={layoutMode}
258
- deckEnabled={settings?.enableDeck}
259
- canIncrementStart={canIncrementStart}
260
- canIncrementEnd={canIncrementEnd}
261
- popoverAnchorId={popoverAnchorId}
262
- primaryId={primary?.id}
263
- companioned={companioned}
264
- companions={companions}
265
- />
268
+ {!fullscreen && (
269
+ <PlankHeading
270
+ id={id}
271
+ part={part.startsWith('solo-') ? 'solo' : part}
272
+ node={node}
273
+ layoutMode={layoutMode}
274
+ deckEnabled={settings?.enableDeck}
275
+ canIncrementStart={canIncrementStart}
276
+ canIncrementEnd={canIncrementEnd}
277
+ popoverAnchorId={popoverAnchorId}
278
+ primaryId={primary?.id}
279
+ companioned={companioned}
280
+ companions={companions}
281
+ />
282
+ )}
266
283
  <Surface
267
284
  key={node.id}
268
285
  role='article'
@@ -275,7 +292,6 @@ const PlankComponent = memo(
275
292
  ) : (
276
293
  <PlankError id={id} part={part} />
277
294
  )}
278
-
279
295
  {canResize && <StackItem.ResizeHandle />}
280
296
  </Root>
281
297
  );
@@ -4,7 +4,8 @@
4
4
 
5
5
  import React, { forwardRef, useCallback } from 'react';
6
6
 
7
- import { createIntent, useIntentDispatcher } from '@dxos/app-framework';
7
+ import { createIntent } from '@dxos/app-framework';
8
+ import { useIntentDispatcher } from '@dxos/app-framework/react';
8
9
  import { invariant } from '@dxos/invariant';
9
10
  import { ButtonGroup, type ButtonGroupProps, type ButtonProps, IconButton, useTranslation } from '@dxos/react-ui';
10
11
 
@@ -32,7 +33,7 @@ export type PlankControlsProps = Omit<ButtonGroupProps, 'onClick'> & {
32
33
  };
33
34
 
34
35
  const PlankControl = ({ icon, label, ...props }: Omit<ButtonProps, 'children'> & { label: string; icon: string }) => {
35
- return <IconButton iconOnly label={label} icon={icon} size={5} variant='ghost' tooltipSide='bottom' {...props} />;
36
+ return <IconButton label={label} icon={icon} iconOnly variant='ghost' tooltipSide='bottom' {...props} />;
36
37
  };
37
38
 
38
39
  const plankControlSpacing = 'pli-2';