@dxos/plugin-presenter 0.8.4-main.c4373fc → 0.8.4-main.c85a9c8dae

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 (142) hide show
  1. package/dist/lib/browser/CollectionPresenterContainer-5RJIT3DA.mjs +52 -0
  2. package/dist/lib/browser/CollectionPresenterContainer-5RJIT3DA.mjs.map +7 -0
  3. package/dist/lib/browser/DocumentPresenterContainer-ISD6N5FM.mjs +28 -0
  4. package/dist/lib/browser/DocumentPresenterContainer-ISD6N5FM.mjs.map +7 -0
  5. package/dist/lib/browser/MarkdownSlide-Q2XLZTMW.mjs +23 -0
  6. package/dist/lib/browser/MarkdownSlide-Q2XLZTMW.mjs.map +7 -0
  7. package/dist/lib/browser/PresenterSettings-WGQMXH4I.mjs +31 -0
  8. package/dist/lib/browser/PresenterSettings-WGQMXH4I.mjs.map +7 -0
  9. package/dist/lib/browser/app-graph-builder-LNUGLW3H.mjs +113 -0
  10. package/dist/lib/browser/app-graph-builder-LNUGLW3H.mjs.map +7 -0
  11. package/dist/lib/browser/chunk-46CHA6Y5.mjs +41 -0
  12. package/dist/lib/browser/chunk-46CHA6Y5.mjs.map +7 -0
  13. package/dist/lib/browser/chunk-BHTOR7TG.mjs +485 -0
  14. package/dist/lib/browser/chunk-BHTOR7TG.mjs.map +7 -0
  15. package/dist/lib/browser/chunk-PSOOAW44.mjs +50 -0
  16. package/dist/lib/browser/chunk-PSOOAW44.mjs.map +7 -0
  17. package/dist/lib/browser/chunk-VQVZVXPJ.mjs +18 -0
  18. package/dist/lib/browser/chunk-VQVZVXPJ.mjs.map +7 -0
  19. package/dist/lib/browser/index.mjs +38 -38
  20. package/dist/lib/browser/index.mjs.map +4 -4
  21. package/dist/lib/browser/meta.json +1 -1
  22. package/dist/lib/browser/react-surface-UCM2KRSP.mjs +67 -0
  23. package/dist/lib/browser/react-surface-UCM2KRSP.mjs.map +7 -0
  24. package/dist/lib/browser/settings-GIQOCH6O.mjs +32 -0
  25. package/dist/lib/browser/settings-GIQOCH6O.mjs.map +7 -0
  26. package/dist/types/src/PresenterPlugin.d.ts +2 -1
  27. package/dist/types/src/PresenterPlugin.d.ts.map +1 -1
  28. package/dist/types/src/capabilities/app-graph-builder/app-graph-builder.d.ts +6 -0
  29. package/dist/types/src/capabilities/app-graph-builder/app-graph-builder.d.ts.map +1 -0
  30. package/dist/types/src/capabilities/app-graph-builder/index.d.ts +3 -0
  31. package/dist/types/src/capabilities/app-graph-builder/index.d.ts.map +1 -0
  32. package/dist/types/src/capabilities/index.d.ts +3 -3
  33. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  34. package/dist/types/src/capabilities/react-surface/index.d.ts +3 -0
  35. package/dist/types/src/capabilities/react-surface/index.d.ts.map +1 -0
  36. package/dist/types/src/capabilities/react-surface/react-surface.d.ts +5 -0
  37. package/dist/types/src/capabilities/react-surface/react-surface.d.ts.map +1 -0
  38. package/dist/types/src/capabilities/settings/index.d.ts +7 -0
  39. package/dist/types/src/capabilities/settings/index.d.ts.map +1 -0
  40. package/dist/types/src/capabilities/settings/settings.d.ts +10 -0
  41. package/dist/types/src/capabilities/settings/settings.d.ts.map +1 -0
  42. package/dist/types/src/components/Presenter/Pager.d.ts +1 -1
  43. package/dist/types/src/components/Presenter/Pager.d.ts.map +1 -1
  44. package/dist/types/src/components/RevealPlayer/RevealPlayer.d.ts.map +1 -1
  45. package/dist/types/src/components/RevealPlayer/RevealPlayer.stories.d.ts.map +1 -1
  46. package/dist/types/src/components/index.d.ts +3 -25
  47. package/dist/types/src/components/index.d.ts.map +1 -1
  48. package/dist/types/src/containers/CollectionPresenterContainer/CollectionPresenterContainer.d.ts +7 -0
  49. package/dist/types/src/containers/CollectionPresenterContainer/CollectionPresenterContainer.d.ts.map +1 -0
  50. package/dist/types/src/containers/CollectionPresenterContainer/index.d.ts +3 -0
  51. package/dist/types/src/containers/CollectionPresenterContainer/index.d.ts.map +1 -0
  52. package/dist/types/src/{components/MarkdownSlide.d.ts → containers/DocumentPresenterContainer/DocumentPresenterContainer.d.ts} +2 -3
  53. package/dist/types/src/containers/DocumentPresenterContainer/DocumentPresenterContainer.d.ts.map +1 -0
  54. package/dist/types/src/containers/DocumentPresenterContainer/index.d.ts +3 -0
  55. package/dist/types/src/containers/DocumentPresenterContainer/index.d.ts.map +1 -0
  56. package/dist/types/src/containers/MarkdownSlide/MarkdownSlide.d.ts +8 -0
  57. package/dist/types/src/containers/MarkdownSlide/MarkdownSlide.d.ts.map +1 -0
  58. package/dist/types/src/containers/MarkdownSlide/index.d.ts +3 -0
  59. package/dist/types/src/containers/MarkdownSlide/index.d.ts.map +1 -0
  60. package/dist/types/src/containers/PresenterSettings/PresenterSettings.d.ts +8 -0
  61. package/dist/types/src/containers/PresenterSettings/PresenterSettings.d.ts.map +1 -0
  62. package/dist/types/src/containers/PresenterSettings/index.d.ts +3 -0
  63. package/dist/types/src/containers/PresenterSettings/index.d.ts.map +1 -0
  64. package/dist/types/src/containers/index.d.ts +6 -0
  65. package/dist/types/src/containers/index.d.ts.map +1 -0
  66. package/dist/types/src/meta.d.ts +2 -2
  67. package/dist/types/src/meta.d.ts.map +1 -1
  68. package/dist/types/src/types.d.ts +35 -25
  69. package/dist/types/src/types.d.ts.map +1 -1
  70. package/dist/types/src/useExitPresenter.d.ts +2 -3
  71. package/dist/types/src/useExitPresenter.d.ts.map +1 -1
  72. package/dist/types/tsconfig.tsbuildinfo +1 -1
  73. package/package.json +47 -39
  74. package/src/PresenterPlugin.tsx +9 -23
  75. package/src/capabilities/app-graph-builder/app-graph-builder.ts +106 -0
  76. package/src/capabilities/app-graph-builder/index.ts +7 -0
  77. package/src/capabilities/index.ts +3 -5
  78. package/src/capabilities/react-surface/index.ts +7 -0
  79. package/src/capabilities/react-surface/react-surface.tsx +71 -0
  80. package/src/capabilities/settings/index.ts +7 -0
  81. package/src/capabilities/settings/settings.ts +31 -0
  82. package/src/components/Markdown/Container.stories.tsx +3 -3
  83. package/src/components/Markdown/Container.tsx +2 -2
  84. package/src/components/Markdown/Slide.stories.tsx +3 -3
  85. package/src/components/Markdown/theme.ts +5 -5
  86. package/src/components/Presenter/Layout.tsx +2 -2
  87. package/src/components/Presenter/Pager.stories.tsx +2 -2
  88. package/src/components/Presenter/Pager.tsx +53 -18
  89. package/src/components/RevealPlayer/RevealPlayer.stories.tsx +3 -3
  90. package/src/components/RevealPlayer/RevealPlayer.tsx +16 -6
  91. package/src/components/index.ts +3 -7
  92. package/src/containers/CollectionPresenterContainer/CollectionPresenterContainer.tsx +43 -0
  93. package/src/containers/CollectionPresenterContainer/index.ts +7 -0
  94. package/src/containers/DocumentPresenterContainer/DocumentPresenterContainer.tsx +23 -0
  95. package/src/containers/DocumentPresenterContainer/index.ts +7 -0
  96. package/src/{components → containers/MarkdownSlide}/MarkdownSlide.tsx +7 -5
  97. package/src/containers/MarkdownSlide/index.ts +7 -0
  98. package/src/containers/PresenterSettings/PresenterSettings.tsx +35 -0
  99. package/src/containers/PresenterSettings/index.ts +7 -0
  100. package/src/containers/index.ts +10 -0
  101. package/src/meta.ts +8 -3
  102. package/src/types.ts +16 -8
  103. package/src/useExitPresenter.ts +24 -24
  104. package/dist/lib/browser/CollectionPresenterContainer-LPJILYRF.mjs +0 -191
  105. package/dist/lib/browser/CollectionPresenterContainer-LPJILYRF.mjs.map +0 -7
  106. package/dist/lib/browser/DocumentPresenterContainer-F42V4KAL.mjs +0 -183
  107. package/dist/lib/browser/DocumentPresenterContainer-F42V4KAL.mjs.map +0 -7
  108. package/dist/lib/browser/MarkdownSlide-BLVWTH3U.mjs +0 -223
  109. package/dist/lib/browser/MarkdownSlide-BLVWTH3U.mjs.map +0 -7
  110. package/dist/lib/browser/app-graph-builder-RLGABE65.mjs +0 -106
  111. package/dist/lib/browser/app-graph-builder-RLGABE65.mjs.map +0 -7
  112. package/dist/lib/browser/chunk-6ZM323ED.mjs +0 -13
  113. package/dist/lib/browser/chunk-6ZM323ED.mjs.map +0 -7
  114. package/dist/lib/browser/chunk-7DV6S5XB.mjs +0 -39
  115. package/dist/lib/browser/chunk-7DV6S5XB.mjs.map +0 -7
  116. package/dist/lib/browser/chunk-QTSOWA2K.mjs +0 -41
  117. package/dist/lib/browser/chunk-QTSOWA2K.mjs.map +0 -7
  118. package/dist/lib/browser/chunk-UVGTHJUO.mjs +0 -36
  119. package/dist/lib/browser/chunk-UVGTHJUO.mjs.map +0 -7
  120. package/dist/lib/browser/react-surface-P7YJFHF3.mjs +0 -57
  121. package/dist/lib/browser/react-surface-P7YJFHF3.mjs.map +0 -7
  122. package/dist/lib/browser/settings-7A4A2H6X.mjs +0 -22
  123. package/dist/lib/browser/settings-7A4A2H6X.mjs.map +0 -7
  124. package/dist/types/src/capabilities/app-graph-builder.d.ts +0 -4
  125. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +0 -1
  126. package/dist/types/src/capabilities/react-surface.d.ts +0 -4
  127. package/dist/types/src/capabilities/react-surface.d.ts.map +0 -1
  128. package/dist/types/src/capabilities/settings.d.ts +0 -4
  129. package/dist/types/src/capabilities/settings.d.ts.map +0 -1
  130. package/dist/types/src/components/CollectionPresenterContainer.d.ts +0 -7
  131. package/dist/types/src/components/CollectionPresenterContainer.d.ts.map +0 -1
  132. package/dist/types/src/components/DocumentPresenterContainer.d.ts +0 -7
  133. package/dist/types/src/components/DocumentPresenterContainer.d.ts.map +0 -1
  134. package/dist/types/src/components/MarkdownSlide.d.ts.map +0 -1
  135. package/dist/types/src/components/PresenterSettings.d.ts +0 -6
  136. package/dist/types/src/components/PresenterSettings.d.ts.map +0 -1
  137. package/src/capabilities/app-graph-builder.ts +0 -113
  138. package/src/capabilities/react-surface.tsx +0 -63
  139. package/src/capabilities/settings.ts +0 -19
  140. package/src/components/CollectionPresenterContainer.tsx +0 -44
  141. package/src/components/DocumentPresenterContainer.tsx +0 -23
  142. package/src/components/PresenterSettings.tsx +0 -30
package/package.json CHANGED
@@ -1,9 +1,13 @@
1
1
  {
2
2
  "name": "@dxos/plugin-presenter",
3
- "version": "0.8.4-main.c4373fc",
3
+ "version": "0.8.4-main.c85a9c8dae",
4
4
  "description": "Braneframe presenter plugin",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/dxos/dxos"
10
+ },
7
11
  "license": "MIT",
8
12
  "author": "DXOS.org",
9
13
  "sideEffects": true,
@@ -11,8 +15,8 @@
11
15
  "exports": {
12
16
  ".": {
13
17
  "source": "./src/index.ts",
14
- "types": "./dist/types/src/index.d.ts",
15
- "browser": "./dist/lib/browser/index.mjs"
18
+ "browser": "./dist/lib/browser/index.mjs",
19
+ "types": "./dist/types/src/index.d.ts"
16
20
  }
17
21
  },
18
22
  "types": "dist/types/src/index.d.ts",
@@ -24,8 +28,8 @@
24
28
  "src"
25
29
  ],
26
30
  "dependencies": {
27
- "@preact-signals/safe-react": "^0.9.0",
28
- "@preact/signals-core": "^1.12.1",
31
+ "@effect-atom/atom": "^0.5.1",
32
+ "@effect-atom/atom-react": "^0.5.0",
29
33
  "hastscript": "^7.1.0",
30
34
  "highlight.js": "^11.9.0",
31
35
  "marked": "^12.0.2",
@@ -36,45 +40,49 @@
36
40
  "remark-frontmatter": "^5.0.0",
37
41
  "remark-parse-frontmatter": "^1.0.3",
38
42
  "reveal.js": "^5.1.0",
39
- "@dxos/app-framework": "0.8.4-main.c4373fc",
40
- "@dxos/echo": "0.8.4-main.c4373fc",
41
- "@dxos/async": "0.8.4-main.c4373fc",
42
- "@dxos/live-object": "0.8.4-main.c4373fc",
43
- "@dxos/local-storage": "0.8.4-main.c4373fc",
44
- "@dxos/log": "0.8.4-main.c4373fc",
45
- "@dxos/plugin-deck": "0.8.4-main.c4373fc",
46
- "@dxos/plugin-client": "0.8.4-main.c4373fc",
47
- "@dxos/plugin-graph": "0.8.4-main.c4373fc",
48
- "@dxos/plugin-markdown": "0.8.4-main.c4373fc",
49
- "@dxos/plugin-stack": "0.8.4-main.c4373fc",
50
- "@dxos/react-client": "0.8.4-main.c4373fc",
51
- "@dxos/react-ui-form": "0.8.4-main.c4373fc",
52
- "@dxos/schema": "0.8.4-main.c4373fc",
53
- "@dxos/react-ui-stack": "0.8.4-main.c4373fc"
43
+ "@dxos/app-toolkit": "0.8.4-main.c85a9c8dae",
44
+ "@dxos/effect": "0.8.4-main.c85a9c8dae",
45
+ "@dxos/app-framework": "0.8.4-main.c85a9c8dae",
46
+ "@dxos/echo": "0.8.4-main.c85a9c8dae",
47
+ "@dxos/log": "0.8.4-main.c85a9c8dae",
48
+ "@dxos/plugin-client": "0.8.4-main.c85a9c8dae",
49
+ "@dxos/plugin-deck": "0.8.4-main.c85a9c8dae",
50
+ "@dxos/operation": "0.8.4-main.c85a9c8dae",
51
+ "@dxos/plugin-graph": "0.8.4-main.c85a9c8dae",
52
+ "@dxos/plugin-markdown": "0.8.4-main.c85a9c8dae",
53
+ "@dxos/plugin-stack": "0.8.4-main.c85a9c8dae",
54
+ "@dxos/react-client": "0.8.4-main.c85a9c8dae",
55
+ "@dxos/async": "0.8.4-main.c85a9c8dae",
56
+ "@dxos/schema": "0.8.4-main.c85a9c8dae",
57
+ "@dxos/react-ui-form": "0.8.4-main.c85a9c8dae",
58
+ "@dxos/react-ui-stack": "0.8.4-main.c85a9c8dae",
59
+ "@dxos/util": "0.8.4-main.c85a9c8dae",
60
+ "@dxos/react-ui-mosaic": "0.8.4-main.c85a9c8dae",
61
+ "@dxos/types": "0.8.4-main.c85a9c8dae"
54
62
  },
55
63
  "devDependencies": {
56
- "@effect-rx/rx-react": "0.42.4",
57
- "@effect/platform": "0.92.1",
58
- "@types/react": "~19.2.2",
59
- "@types/react-dom": "~19.2.1",
64
+ "@effect-atom/atom-react": "^0.5.0",
65
+ "@effect/platform": "0.94.4",
66
+ "@types/react": "~19.2.7",
67
+ "@types/react-dom": "~19.2.3",
60
68
  "@types/reveal.js": "^5.0.3",
61
- "effect": "3.18.3",
62
- "react": "~19.2.0",
63
- "react-dom": "~19.2.0",
64
- "vite": "7.1.9",
65
- "@dxos/react-ui": "0.8.4-main.c4373fc",
66
- "@dxos/react-ui-theme": "0.8.4-main.c4373fc",
67
- "@dxos/storybook-utils": "0.8.4-main.c4373fc",
68
- "@dxos/random": "0.8.4-main.c4373fc"
69
+ "effect": "3.19.16",
70
+ "react": "~19.2.3",
71
+ "react-dom": "~19.2.3",
72
+ "vite": "^7.1.11",
73
+ "@dxos/random": "0.8.4-main.c85a9c8dae",
74
+ "@dxos/storybook-utils": "0.8.4-main.c85a9c8dae",
75
+ "@dxos/react-ui": "0.8.4-main.c85a9c8dae",
76
+ "@dxos/ui-theme": "0.8.4-main.c85a9c8dae"
69
77
  },
70
78
  "peerDependencies": {
71
- "@effect-rx/rx-react": "^0.34.1",
72
- "@effect/platform": "^0.80.12",
73
- "effect": "^3.13.3",
74
- "react": "^19.0.0",
75
- "react-dom": "^19.0.0",
76
- "@dxos/react-ui": "0.8.4-main.c4373fc",
77
- "@dxos/react-ui-theme": "0.8.4-main.c4373fc"
79
+ "@effect-atom/atom-react": "^0.5.0",
80
+ "@effect/platform": "0.94.4",
81
+ "effect": "3.19.16",
82
+ "react": "~19.2.3",
83
+ "react-dom": "~19.2.3",
84
+ "@dxos/react-ui": "0.8.4-main.c85a9c8dae",
85
+ "@dxos/ui-theme": "0.8.4-main.c85a9c8dae"
78
86
  },
79
87
  "publishConfig": {
80
88
  "access": "public"
@@ -2,7 +2,8 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { Capabilities, Events, contributes, defineModule, definePlugin } from '@dxos/app-framework';
5
+ import { Plugin } from '@dxos/app-framework';
6
+ import { AppPlugin } from '@dxos/app-toolkit';
6
7
 
7
8
  import { AppGraphBuilder, PresenterSettings, ReactSurface } from './capabilities';
8
9
  import { meta } from './meta';
@@ -11,25 +12,10 @@ import { translations } from './translations';
11
12
  // TODO(burdon): Only scale markdown content.
12
13
  // TODO(burdon): Map stack content; Slide content type (e.g., markdown, sketch, IPFS image, table, etc.)
13
14
 
14
- export const PresenterPlugin = definePlugin(meta, () => [
15
- defineModule({
16
- id: `${meta.id}/module/settings`,
17
- activatesOn: Events.SetupSettings,
18
- activate: PresenterSettings,
19
- }),
20
- defineModule({
21
- id: `${meta.id}/module/translations`,
22
- activatesOn: Events.SetupTranslations,
23
- activate: () => contributes(Capabilities.Translations, translations),
24
- }),
25
- defineModule({
26
- id: `${meta.id}/module/react-surface`,
27
- activatesOn: Events.SetupReactSurface,
28
- activate: ReactSurface,
29
- }),
30
- defineModule({
31
- id: `${meta.id}/module/app-graph-builder`,
32
- activatesOn: Events.SetupAppGraph,
33
- activate: AppGraphBuilder,
34
- }),
35
- ]);
15
+ export const PresenterPlugin = Plugin.define(meta).pipe(
16
+ AppPlugin.addAppGraphModule({ activate: AppGraphBuilder }),
17
+ AppPlugin.addSettingsModule({ activate: PresenterSettings }),
18
+ AppPlugin.addSurfaceModule({ activate: ReactSurface }),
19
+ AppPlugin.addTranslationsModule({ translations }),
20
+ Plugin.make,
21
+ );
@@ -0,0 +1,106 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+ import * as Option from 'effect/Option';
7
+
8
+ import { Capabilities, Capability } from '@dxos/app-framework';
9
+ import { AppCapabilities, LayoutOperation } from '@dxos/app-toolkit';
10
+ import { Obj } from '@dxos/echo';
11
+ import { Collection } from '@dxos/echo';
12
+ import { Operation } from '@dxos/operation';
13
+ import { DeckCapabilities } from '@dxos/plugin-deck';
14
+ import { ATTENDABLE_PATH_SEPARATOR, DeckOperation } from '@dxos/plugin-deck/types';
15
+ import { GraphBuilder, type Node, NodeMatcher } from '@dxos/plugin-graph';
16
+ import { Markdown } from '@dxos/plugin-markdown/types';
17
+
18
+ import { meta } from '../../meta';
19
+ import { PresenterCapabilities, PresenterOperation } from '../../types';
20
+
21
+ /** Match nodes that can be presented (Collection or Document). */
22
+ const whenPresentable = (node: Node.Node) =>
23
+ Option.orElse(NodeMatcher.whenEchoType(Collection.Collection)(node), () =>
24
+ NodeMatcher.whenEchoType(Markdown.Document)(node),
25
+ );
26
+
27
+ export default Capability.makeModule(
28
+ Effect.fnUntraced(function* () {
29
+ const capabilities = yield* Capability.Service;
30
+
31
+ const extensions = yield* GraphBuilder.createExtension({
32
+ id: `${meta.id}/root`,
33
+ // TODO(wittjosiah): This is a hack to work around presenter previously relying on "variant". Remove.
34
+ match: whenPresentable,
35
+ connector: (object, get) => {
36
+ const settingsAtom = capabilities.get(PresenterCapabilities.Settings);
37
+ const settings = get(settingsAtom);
38
+ const isPresentable = settings?.presentCollections
39
+ ? Obj.instanceOf(Collection.Collection, object) || Obj.instanceOf(Markdown.Document, object)
40
+ : Obj.instanceOf(Markdown.Document, object);
41
+ if (!isPresentable) {
42
+ return Effect.succeed([]);
43
+ }
44
+ const id = Obj.getDXN(object).toString();
45
+ return Effect.succeed([
46
+ {
47
+ id: [id, 'presenter'].join(ATTENDABLE_PATH_SEPARATOR),
48
+ data: { type: meta.id, object },
49
+ type: meta.id,
50
+ properties: {
51
+ label: 'Presenter',
52
+ icon: 'ph--presentation--regular',
53
+ disposition: 'hidden',
54
+ },
55
+ },
56
+ ]);
57
+ },
58
+ actions: (object, get) => {
59
+ const settingsAtom = capabilities.get(PresenterCapabilities.Settings);
60
+ const settings = get(settingsAtom);
61
+ const isPresentable = settings?.presentCollections
62
+ ? Obj.instanceOf(Collection.Collection, object) || Obj.instanceOf(Markdown.Document, object)
63
+ : Obj.instanceOf(Markdown.Document, object);
64
+ if (!isPresentable) {
65
+ return Effect.succeed([]);
66
+ }
67
+ const dxn = Obj.getDXN(object);
68
+ const id = dxn.toString();
69
+ const { spaceId } = dxn.asEchoDXN()!;
70
+ return Effect.succeed([
71
+ {
72
+ id: `${PresenterOperation.TogglePresentation.meta.key}/${id}`,
73
+ // TODO(burdon): Allow function so can generate state when activated.
74
+ // So can set explicit fullscreen state coordinated with current presenter state.
75
+ data: Effect.fnUntraced(function* () {
76
+ const deckState = yield* Capabilities.getAtomValue(DeckCapabilities.State);
77
+ const deck = deckState.decks[deckState.activeDeck];
78
+ const presenterId = [id, 'presenter'].join(ATTENDABLE_PATH_SEPARATOR);
79
+ if (!deck?.fullscreen) {
80
+ yield* Operation.invoke(DeckOperation.Adjust, {
81
+ type: 'solo--fullscreen' as const,
82
+ id: presenterId,
83
+ });
84
+ }
85
+ yield* Operation.invoke(LayoutOperation.Open, {
86
+ subject: [presenterId],
87
+ workspace: spaceId,
88
+ });
89
+ }),
90
+ properties: {
91
+ label: ['toggle presentation label', { ns: meta.id }],
92
+ icon: 'ph--presentation--regular',
93
+ disposition: 'list-item',
94
+ keyBinding: {
95
+ macos: 'shift+meta+p',
96
+ windows: 'shift+alt+p',
97
+ },
98
+ },
99
+ },
100
+ ]);
101
+ },
102
+ });
103
+
104
+ return Capability.contributes(AppCapabilities.AppGraphBuilder, extensions);
105
+ }),
106
+ );
@@ -0,0 +1,7 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { Capability } from '@dxos/app-framework';
6
+
7
+ export const AppGraphBuilder = Capability.lazy('AppGraphBuilder', () => import('./app-graph-builder'));
@@ -2,8 +2,6 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { lazy } from '@dxos/app-framework';
6
-
7
- export const AppGraphBuilder = lazy(() => import('./app-graph-builder'));
8
- export const ReactSurface = lazy(() => import('./react-surface'));
9
- export const PresenterSettings = lazy(() => import('./settings'));
5
+ export * from './app-graph-builder';
6
+ export * from './react-surface';
7
+ export * from './settings';
@@ -0,0 +1,7 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { Capability } from '@dxos/app-framework';
6
+
7
+ export const ReactSurface = Capability.lazy('ReactSurface', () => import('./react-surface'));
@@ -0,0 +1,71 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+ import React from 'react';
7
+
8
+ import { Capabilities, Capability } from '@dxos/app-framework';
9
+ import { Surface, useSettingsState } from '@dxos/app-framework/ui';
10
+ import { AppCapabilities } from '@dxos/app-toolkit';
11
+ import { Obj } from '@dxos/echo';
12
+ import { Collection } from '@dxos/echo';
13
+ import { Markdown } from '@dxos/plugin-markdown/types';
14
+
15
+ import {
16
+ CollectionPresenterContainer,
17
+ DocumentPresenterContainer,
18
+ MarkdownSlide,
19
+ PresenterSettings,
20
+ } from '../../containers';
21
+ import { meta } from '../../meta';
22
+ import { type PresenterSettingsProps } from '../../types';
23
+
24
+ export default Capability.makeModule(() =>
25
+ Effect.succeed(
26
+ Capability.contributes(Capabilities.ReactSurface, [
27
+ Surface.create({
28
+ id: `${meta.id}/document`,
29
+ role: 'article',
30
+ position: 'hoist',
31
+ filter: (data): data is { subject: { type: typeof meta.id; object: Markdown.Document } } =>
32
+ !!data.subject &&
33
+ typeof data.subject === 'object' &&
34
+ 'type' in data.subject &&
35
+ 'object' in data.subject &&
36
+ data.subject.type === meta.id &&
37
+ Obj.instanceOf(Markdown.Document, data.subject.object),
38
+ component: ({ data }) => <DocumentPresenterContainer document={data.subject.object} />,
39
+ }),
40
+ Surface.create({
41
+ id: `${meta.id}/collection`,
42
+ role: 'article',
43
+ position: 'hoist',
44
+ filter: (data): data is { subject: { type: typeof meta.id; object: Collection.Collection } } =>
45
+ !!data.subject &&
46
+ typeof data.subject === 'object' &&
47
+ 'type' in data.subject &&
48
+ 'object' in data.subject &&
49
+ data.subject.type === meta.id &&
50
+ Obj.instanceOf(Collection.Collection, data.subject.object),
51
+ component: ({ role, data }) => <CollectionPresenterContainer role={role} subject={data.subject.object} />,
52
+ }),
53
+ Surface.create({
54
+ id: `${meta.id}/slide`,
55
+ role: 'slide',
56
+ filter: (data): data is { subject: Markdown.Document } => Obj.instanceOf(Markdown.Document, data.subject),
57
+ component: ({ data }) => <MarkdownSlide document={data.subject} />,
58
+ }),
59
+ Surface.create({
60
+ id: `${meta.id}/plugin-settings`,
61
+ role: 'article',
62
+ filter: (data): data is { subject: AppCapabilities.Settings } =>
63
+ AppCapabilities.isSettings(data.subject) && data.subject.prefix === meta.id,
64
+ component: ({ data: { subject } }) => {
65
+ const { settings, updateSettings } = useSettingsState<PresenterSettingsProps>(subject.atom);
66
+ return <PresenterSettings settings={settings} onSettingsChange={updateSettings} />;
67
+ },
68
+ }),
69
+ ]),
70
+ ),
71
+ );
@@ -0,0 +1,7 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { Capability } from '@dxos/app-framework';
6
+
7
+ export const PresenterSettings = Capability.lazy('PresenterSettings', () => import('./settings'));
@@ -0,0 +1,31 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+
7
+ import { Capability } from '@dxos/app-framework';
8
+ import { AppCapabilities } from '@dxos/app-toolkit';
9
+ import { createKvsStore } from '@dxos/effect';
10
+
11
+ import { meta } from '../../meta';
12
+ import { PresenterCapabilities, PresenterSettingsSchema } from '../../types';
13
+
14
+ export default Capability.makeModule(() =>
15
+ Effect.sync(() => {
16
+ const settingsAtom = createKvsStore({
17
+ key: meta.id,
18
+ schema: PresenterSettingsSchema,
19
+ defaultValue: () => ({}),
20
+ });
21
+
22
+ return [
23
+ Capability.contributes(PresenterCapabilities.Settings, settingsAtom),
24
+ Capability.contributes(AppCapabilities.Settings, {
25
+ prefix: meta.id,
26
+ schema: PresenterSettingsSchema,
27
+ atom: settingsAtom,
28
+ }),
29
+ ];
30
+ }),
31
+ );
@@ -5,7 +5,7 @@
5
5
  import { type Meta, type StoryObj } from '@storybook/react-vite';
6
6
  import React from 'react';
7
7
 
8
- import { withTheme } from '@dxos/react-ui/testing';
8
+ import { withLayout, withTheme } from '@dxos/react-ui/testing';
9
9
 
10
10
  import { createSlide } from '../../testing';
11
11
 
@@ -21,9 +21,9 @@ const DefaultStory = ({ content = '' }: SlideProps) => {
21
21
  };
22
22
 
23
23
  const meta = {
24
- title: 'plugins/plugin-presenter/Container',
24
+ title: 'plugins/plugin-presenter/components/Container',
25
25
  render: DefaultStory,
26
- decorators: [withTheme],
26
+ decorators: [withTheme(), withLayout({ layout: 'fullscreen' })],
27
27
  parameters: {
28
28
  layout: 'fullscreen',
29
29
  },
@@ -6,7 +6,7 @@ import React, { type PropsWithChildren, useState } from 'react';
6
6
  import { useResizeDetector } from 'react-resize-detector';
7
7
 
8
8
  import { type ThemedClassName } from '@dxos/react-ui';
9
- import { mx } from '@dxos/react-ui-theme';
9
+ import { mx } from '@dxos/ui-theme';
10
10
 
11
11
  export type ContainerProps = ThemedClassName<PropsWithChildren<{}>>;
12
12
 
@@ -35,7 +35,7 @@ export const Container = ({ children, classNames }: ContainerProps) => {
35
35
  // TODO(burdon): Reconcile highlight colors with markdown editor.
36
36
  // https://www.npmjs.com/package/react-markdown
37
37
  return (
38
- <div ref={containerRef} className={mx('flex grow relative overflow-hidden bg-attention', classNames)}>
38
+ <div ref={containerRef} className={mx('flex grow relative overflow-hidden bg-attention-surface', classNames)}>
39
39
  <div className={mx('flex w-full h-full overflow-hidden absolute')} style={props}>
40
40
  {width && height && children}
41
41
  </div>
@@ -4,16 +4,16 @@
4
4
 
5
5
  import { type Meta, type StoryObj } from '@storybook/react-vite';
6
6
 
7
- import { withTheme } from '@dxos/react-ui/testing';
7
+ import { withLayout, withTheme } from '@dxos/react-ui/testing';
8
8
 
9
9
  import { createSlide } from '../../testing';
10
10
 
11
11
  import { Slide } from './Slide';
12
12
 
13
13
  const meta = {
14
- title: 'plugins/plugin-presenter/Slide',
14
+ title: 'plugins/plugin-presenter/components/Slide',
15
15
  component: Slide,
16
- decorators: [withTheme],
16
+ decorators: [withTheme(), withLayout({ layout: 'fullscreen' })],
17
17
  parameters: {
18
18
  layout: 'fullscreen',
19
19
  },
@@ -5,14 +5,14 @@
5
5
  // TODO(burdon): Create theme type and picker.
6
6
 
7
7
  export const theme = {
8
- root: 'bg-attention leading-relaxed font-mono',
8
+ root: 'bg-attention-surface leading-relaxed font-mono',
9
9
 
10
10
  padding: 'px-40 py-16 gap-8',
11
11
 
12
12
  nodes: {
13
- h1: 'text-[80px] text-accentText',
14
- h2: 'text-[60px] text-accentText',
15
- h3: 'text-[48px] text-accentText',
13
+ h1: 'text-[80px] text-accent-text',
14
+ h2: 'text-[60px] text-accent-text',
15
+ h3: 'text-[48px] text-accent-text',
16
16
 
17
17
  p: 'text-[48px]',
18
18
 
@@ -20,7 +20,7 @@ export const theme = {
20
20
  ol: 'my-[16px] ml-24 leading-relaxed list-decimal',
21
21
  li: 'pl-6 text-[48px]',
22
22
 
23
- pre: 'w-full mx-0 my-[32px] p-0 __border-l-[16px] bg-inputSurface p-4 __whitespace-pre-line',
23
+ pre: 'w-full mx-0 my-[32px] p-4 bg-input-surface',
24
24
  code: 'p-0 text-[40px]',
25
25
  },
26
26
  };
@@ -5,7 +5,7 @@
5
5
  import React, { type PropsWithChildren, type ReactNode } from 'react';
6
6
 
7
7
  import { type ThemedClassName } from '@dxos/react-ui';
8
- import { mx } from '@dxos/react-ui-theme';
8
+ import { mx } from '@dxos/ui-theme';
9
9
 
10
10
  export type LayoutProps = ThemedClassName<
11
11
  PropsWithChildren<{
@@ -19,7 +19,7 @@ export type LayoutProps = ThemedClassName<
19
19
 
20
20
  export const Layout = ({ children, classNames, topLeft, topRight, bottomLeft, bottomRight }: LayoutProps) => {
21
21
  return (
22
- <div className={mx('flex grow relative overflow-hidden bg-attention', classNames)}>
22
+ <div className={mx('flex grow relative overflow-hidden bg-attention-surface', classNames)}>
23
23
  <div className={mx('flex flex-col grow overflow-hidden')}>{children}</div>
24
24
 
25
25
  <div className='z-[200]'>
@@ -23,9 +23,9 @@ const DefaultStory = ({ count = 20 }: PagerProps) => {
23
23
  };
24
24
 
25
25
  const meta = {
26
- title: 'plugins/plugin-presenter/Pager',
26
+ title: 'plugins/plugin-presenter/components/Pager',
27
27
  render: DefaultStory,
28
- decorators: [withTheme],
28
+ decorators: [withTheme()],
29
29
  parameters: {
30
30
  layout: 'centered',
31
31
  },
@@ -4,7 +4,7 @@
4
4
 
5
5
  import React, { useEffect } from 'react';
6
6
 
7
- import { Button, Icon, useControlledState } from '@dxos/react-ui';
7
+ import { IconButton, useControlledState } from '@dxos/react-ui';
8
8
 
9
9
  export type PagerProps = {
10
10
  index?: number;
@@ -14,8 +14,8 @@ export type PagerProps = {
14
14
  onExit?: () => void;
15
15
  };
16
16
 
17
- export const Pager = ({ index: indexParam = 0, count = 0, keys, onChange, onExit }: PagerProps) => {
18
- const [index, setIndex] = useControlledState(indexParam);
17
+ export const Pager = ({ index: indexProp = 0, count = 0, keys, onChange, onExit }: PagerProps) => {
18
+ const [index, setIndex] = useControlledState(indexProp);
19
19
  useEffect(() => {
20
20
  onChange?.(index);
21
21
  }, [index]);
@@ -76,18 +76,46 @@ export const Pager = ({ index: indexParam = 0, count = 0, keys, onChange, onExit
76
76
 
77
77
  return (
78
78
  <div className='flex items-center text-neutral-500'>
79
- <Button variant='ghost' classNames='p-0' onClick={() => onChange?.(0)}>
80
- <Icon icon='ph--caret-double-left--regular' size={6} />
81
- </Button>
82
- <Button variant='ghost' classNames='p-0' onClick={() => handleChangeIndex(-1)}>
83
- <Icon icon='ph--caret-left--regular' size={6} />
84
- </Button>
85
- <Button variant='ghost' classNames='p-0' onClick={() => handleChangeIndex(1)}>
86
- <Icon icon='ph--caret-right--regular' size={6} />
87
- </Button>
88
- <Button variant='ghost' classNames='p-0' onClick={() => onChange?.(count - 1)}>
89
- <Icon icon='ph--caret-double-right--regular' size={6} />
90
- </Button>
79
+ <IconButton
80
+ icon='ph--caret-double-left--regular'
81
+ size={6}
82
+ label='Jump to first'
83
+ iconOnly
84
+ noTooltip
85
+ variant='ghost'
86
+ classNames='p-0'
87
+ onClick={() => onChange?.(0)}
88
+ />
89
+ <IconButton
90
+ icon='ph--caret-left--regular'
91
+ size={6}
92
+ label='Previous'
93
+ iconOnly
94
+ noTooltip
95
+ variant='ghost'
96
+ classNames='p-0'
97
+ onClick={() => handleChangeIndex(-1)}
98
+ />
99
+ <IconButton
100
+ icon='ph--caret-right--regular'
101
+ size={6}
102
+ label='Next'
103
+ iconOnly
104
+ noTooltip
105
+ variant='ghost'
106
+ classNames='p-0'
107
+ onClick={() => handleChangeIndex(1)}
108
+ />
109
+ <IconButton
110
+ icon='ph--caret-double-right--regular'
111
+ size={6}
112
+ label='Jump to last'
113
+ iconOnly
114
+ noTooltip
115
+ variant='ghost'
116
+ classNames='p-0'
117
+ onClick={() => onChange?.(count - 1)}
118
+ />
91
119
  </div>
92
120
  );
93
121
  };
@@ -113,8 +141,15 @@ export const PageNumber = ({ index = 0, count = 1 }: PageNumberProps) => {
113
141
 
114
142
  export const StartButton = ({ running, onClick }: { running?: boolean; onClick?: (start: boolean) => void }) => {
115
143
  return (
116
- <Button variant='ghost' classNames='p-0' onClick={() => onClick?.(!running)}>
117
- {(running && <Icon icon='ph--x--regular' size={6} />) || <Icon icon='ph--play--regular' size={6} />}
118
- </Button>
144
+ <IconButton
145
+ icon={running ? 'ph--x--regular' : 'ph--play--regular'}
146
+ size={6}
147
+ label={running ? 'Stop' : 'Play'}
148
+ iconOnly
149
+ noTooltip
150
+ variant='ghost'
151
+ classNames='p-0'
152
+ onClick={() => onClick?.(!running)}
153
+ />
119
154
  );
120
155
  };
@@ -4,7 +4,7 @@
4
4
 
5
5
  import { type Meta } from '@storybook/react-vite';
6
6
 
7
- import { withTheme } from '@dxos/react-ui/testing';
7
+ import { withLayout, withTheme } from '@dxos/react-ui/testing';
8
8
 
9
9
  import CONTENT from '../../../testing/deck.md?raw';
10
10
  import { translations } from '../../translations';
@@ -20,9 +20,9 @@ import { RevealPlayer } from './RevealPlayer';
20
20
  // https://fonts.google.com
21
21
 
22
22
  const meta = {
23
- title: 'plugins/plugin-presenter/RevealPlayer',
23
+ title: 'plugins/plugin-presenter/components/RevealPlayer',
24
24
  component: RevealPlayer,
25
- decorators: [withTheme],
25
+ decorators: [withTheme(), withLayout({ layout: 'fullscreen' })],
26
26
  parameters: {
27
27
  layout: 'fullscreen',
28
28
  translations,