@dxos/plugin-presenter 0.9.0 → 0.9.1-staging.ee54ba693a

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 (166) hide show
  1. package/PLUGIN.mdl +12 -12
  2. package/dist/lib/neutral/{CollectionPresenterArticle-DFREOQTG.mjs → CollectionArticle-7R4KJWDW.mjs} +10 -9
  3. package/dist/lib/neutral/CollectionArticle-7R4KJWDW.mjs.map +7 -0
  4. package/dist/lib/neutral/DocumentArticle-YZRKVEN7.mjs +32 -0
  5. package/dist/lib/neutral/DocumentArticle-YZRKVEN7.mjs.map +7 -0
  6. package/dist/lib/neutral/PresenterPlugin.mjs +11 -4
  7. package/dist/lib/neutral/PresenterPlugin.mjs.map +4 -4
  8. package/dist/lib/neutral/SlideArticle-FE2I6KBO.mjs +20 -0
  9. package/dist/lib/neutral/SlideArticle-FE2I6KBO.mjs.map +7 -0
  10. package/dist/lib/neutral/{app-graph-builder-DIEDSRPX.mjs → app-graph-builder-FNDFY5L3.mjs} +8 -24
  11. package/dist/lib/neutral/app-graph-builder-FNDFY5L3.mjs.map +7 -0
  12. package/dist/lib/neutral/capabilities/index.mjs +7 -3
  13. package/dist/lib/neutral/capabilities/index.mjs.map +3 -3
  14. package/dist/lib/neutral/chunk-63IF7OXT.mjs +19 -0
  15. package/dist/lib/neutral/chunk-63IF7OXT.mjs.map +7 -0
  16. package/dist/lib/neutral/chunk-MSQDHOPV.mjs +47 -0
  17. package/dist/lib/neutral/chunk-MSQDHOPV.mjs.map +7 -0
  18. package/dist/lib/neutral/{chunk-VVALMI52.mjs → chunk-NDZ6IIAL.mjs} +8 -4
  19. package/dist/lib/neutral/chunk-NDZ6IIAL.mjs.map +7 -0
  20. package/dist/lib/neutral/components/index.mjs +90 -29
  21. package/dist/lib/neutral/components/index.mjs.map +4 -4
  22. package/dist/lib/neutral/containers/index.mjs +6 -6
  23. package/dist/lib/neutral/containers/index.mjs.map +3 -3
  24. package/dist/lib/neutral/index.mjs +2 -2
  25. package/dist/lib/neutral/markdown-extension-HGLRVZDF.mjs +37 -0
  26. package/dist/lib/neutral/markdown-extension-HGLRVZDF.mjs.map +7 -0
  27. package/dist/lib/neutral/meta.json +1 -1
  28. package/dist/lib/neutral/meta.mjs +1 -1
  29. package/dist/lib/neutral/operation-handler-3ZESW5AK.mjs +13 -0
  30. package/dist/lib/neutral/operation-handler-3ZESW5AK.mjs.map +7 -0
  31. package/dist/lib/neutral/operations/index.mjs +9 -0
  32. package/dist/lib/neutral/operations/index.mjs.map +7 -0
  33. package/dist/lib/neutral/plugin.mjs +1 -1
  34. package/dist/lib/neutral/react-surface-VO4GPCLQ.mjs +42 -0
  35. package/dist/lib/neutral/react-surface-VO4GPCLQ.mjs.map +7 -0
  36. package/dist/lib/neutral/{settings-R6LRDAAK.mjs → settings-DBV7N5HT.mjs} +3 -3
  37. package/dist/lib/neutral/{settings-R6LRDAAK.mjs.map → settings-DBV7N5HT.mjs.map} +3 -3
  38. package/dist/lib/neutral/toggle-presentation-PH7ZJJDD.mjs +60 -0
  39. package/dist/lib/neutral/toggle-presentation-PH7ZJJDD.mjs.map +7 -0
  40. package/dist/lib/neutral/translations.mjs +1 -2
  41. package/dist/lib/neutral/translations.mjs.map +3 -3
  42. package/dist/lib/neutral/types/index.mjs +1 -1
  43. package/dist/types/dx.config.d.ts +28 -0
  44. package/dist/types/dx.config.d.ts.map +1 -0
  45. package/dist/types/src/PresenterPlugin.d.ts.map +1 -1
  46. package/dist/types/src/capabilities/app-graph-builder.d.ts +1 -2
  47. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
  48. package/dist/types/src/capabilities/index.d.ts +6 -3
  49. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  50. package/dist/types/src/capabilities/markdown-extension.d.ts +9 -0
  51. package/dist/types/src/capabilities/markdown-extension.d.ts.map +1 -0
  52. package/dist/types/src/capabilities/operation-handler.d.ts +6 -0
  53. package/dist/types/src/capabilities/operation-handler.d.ts.map +1 -0
  54. package/dist/types/src/capabilities/react-surface.d.ts +2 -2
  55. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  56. package/dist/types/src/capabilities/settings.d.ts +1 -3
  57. package/dist/types/src/capabilities/settings.d.ts.map +1 -1
  58. package/dist/types/src/components/Presenter/PresentationShell.d.ts +20 -0
  59. package/dist/types/src/components/Presenter/PresentationShell.d.ts.map +1 -0
  60. package/dist/types/src/components/Presenter/index.d.ts +1 -0
  61. package/dist/types/src/components/Presenter/index.d.ts.map +1 -1
  62. package/dist/types/src/components/RevealPlayer/RevealPlayer.d.ts.map +1 -1
  63. package/dist/types/src/components/RevealPlayer/RevealPlayer.stories.d.ts +0 -1
  64. package/dist/types/src/components/RevealPlayer/RevealPlayer.stories.d.ts.map +1 -1
  65. package/dist/types/src/components/index.d.ts +0 -2
  66. package/dist/types/src/components/index.d.ts.map +1 -1
  67. package/dist/types/src/containers/CollectionArticle/CollectionArticle.d.ts +6 -0
  68. package/dist/types/src/containers/CollectionArticle/CollectionArticle.d.ts.map +1 -0
  69. package/dist/types/src/containers/CollectionArticle/index.d.ts +2 -0
  70. package/dist/types/src/{components/PresenterSettings → containers/CollectionArticle}/index.d.ts.map +1 -1
  71. package/dist/types/src/containers/DocumentArticle/DocumentArticle.d.ts +6 -0
  72. package/dist/types/src/containers/DocumentArticle/DocumentArticle.d.ts.map +1 -0
  73. package/dist/types/src/containers/DocumentArticle/index.d.ts +2 -0
  74. package/dist/types/src/containers/DocumentArticle/index.d.ts.map +1 -0
  75. package/dist/types/src/containers/SlideArticle/SlideArticle.d.ts +6 -0
  76. package/dist/types/src/containers/SlideArticle/SlideArticle.d.ts.map +1 -0
  77. package/dist/types/src/containers/SlideArticle/index.d.ts +2 -0
  78. package/dist/types/src/containers/SlideArticle/index.d.ts.map +1 -0
  79. package/dist/types/src/containers/index.d.ts +3 -3
  80. package/dist/types/src/containers/index.d.ts.map +1 -1
  81. package/dist/types/src/meta.d.ts +32 -2
  82. package/dist/types/src/meta.d.ts.map +1 -1
  83. package/dist/types/src/operations/index.d.ts +3 -0
  84. package/dist/types/src/operations/index.d.ts.map +1 -0
  85. package/dist/types/src/operations/toggle-presentation.d.ts +10 -0
  86. package/dist/types/src/operations/toggle-presentation.d.ts.map +1 -0
  87. package/dist/types/src/paths.d.ts +3 -0
  88. package/dist/types/src/paths.d.ts.map +1 -0
  89. package/dist/types/src/translations.d.ts +0 -1
  90. package/dist/types/src/translations.d.ts.map +1 -1
  91. package/dist/types/src/types/PresenterCapabilities.d.ts.map +1 -1
  92. package/dist/types/src/types/PresenterOperation.d.ts +5 -13
  93. package/dist/types/src/types/PresenterOperation.d.ts.map +1 -1
  94. package/dist/types/src/useExitPresenter.d.ts +6 -1
  95. package/dist/types/src/useExitPresenter.d.ts.map +1 -1
  96. package/dist/types/tsconfig.tsbuildinfo +1 -1
  97. package/dx.config.ts +37 -0
  98. package/package.json +39 -31
  99. package/src/PresenterPlugin.test.ts +1 -1
  100. package/src/PresenterPlugin.tsx +9 -2
  101. package/src/capabilities/app-graph-builder.ts +9 -24
  102. package/src/capabilities/index.ts +6 -0
  103. package/src/capabilities/markdown-extension.ts +45 -0
  104. package/src/capabilities/operation-handler.ts +16 -0
  105. package/src/capabilities/react-surface.tsx +14 -23
  106. package/src/capabilities/settings.ts +2 -2
  107. package/src/components/Markdown/Panel.stories.tsx +1 -1
  108. package/src/components/Presenter/PresentationShell.tsx +99 -0
  109. package/src/components/Presenter/index.ts +1 -0
  110. package/src/components/RevealPlayer/RevealPlayer.tsx +11 -12
  111. package/src/components/index.ts +0 -4
  112. package/src/containers/CollectionArticle/CollectionArticle.tsx +44 -0
  113. package/src/containers/CollectionArticle/index.ts +5 -0
  114. package/src/containers/DocumentArticle/DocumentArticle.tsx +34 -0
  115. package/src/containers/DocumentArticle/index.ts +5 -0
  116. package/src/containers/{MarkdownSlide/MarkdownSlide.tsx → SlideArticle/SlideArticle.tsx} +4 -5
  117. package/src/containers/SlideArticle/index.ts +5 -0
  118. package/src/containers/index.ts +3 -3
  119. package/src/meta.ts +2 -30
  120. package/src/operations/index.ts +7 -0
  121. package/src/operations/toggle-presentation.ts +59 -0
  122. package/src/paths.ts +8 -0
  123. package/src/translations.ts +1 -2
  124. package/src/types/PresenterCapabilities.ts +3 -1
  125. package/src/types/PresenterOperation.ts +4 -3
  126. package/src/useExitPresenter.ts +13 -26
  127. package/dist/lib/neutral/CollectionPresenterArticle-DFREOQTG.mjs.map +0 -7
  128. package/dist/lib/neutral/DocumentPresenterContainer-KCDZ2O2C.mjs +0 -24
  129. package/dist/lib/neutral/DocumentPresenterContainer-KCDZ2O2C.mjs.map +0 -7
  130. package/dist/lib/neutral/MarkdownSlide-WXILOIBE.mjs +0 -18
  131. package/dist/lib/neutral/MarkdownSlide-WXILOIBE.mjs.map +0 -7
  132. package/dist/lib/neutral/PresenterSettings-2G4XD4QY.mjs +0 -25
  133. package/dist/lib/neutral/PresenterSettings-2G4XD4QY.mjs.map +0 -7
  134. package/dist/lib/neutral/app-graph-builder-DIEDSRPX.mjs.map +0 -7
  135. package/dist/lib/neutral/chunk-PPL2FF6R.mjs +0 -38
  136. package/dist/lib/neutral/chunk-PPL2FF6R.mjs.map +0 -7
  137. package/dist/lib/neutral/chunk-V323QBC3.mjs +0 -41
  138. package/dist/lib/neutral/chunk-V323QBC3.mjs.map +0 -7
  139. package/dist/lib/neutral/chunk-VVALMI52.mjs.map +0 -7
  140. package/dist/lib/neutral/react-surface-SPJGAJIF.mjs +0 -54
  141. package/dist/lib/neutral/react-surface-SPJGAJIF.mjs.map +0 -7
  142. package/dist/types/src/components/PresenterSettings/PresenterSettings.d.ts +0 -6
  143. package/dist/types/src/components/PresenterSettings/PresenterSettings.d.ts.map +0 -1
  144. package/dist/types/src/components/PresenterSettings/PresenterSettings.stories.d.ts +0 -23
  145. package/dist/types/src/components/PresenterSettings/PresenterSettings.stories.d.ts.map +0 -1
  146. package/dist/types/src/components/PresenterSettings/index.d.ts +0 -2
  147. package/dist/types/src/containers/CollectionPresenterArticle/CollectionPresenterArticle.d.ts +0 -6
  148. package/dist/types/src/containers/CollectionPresenterArticle/CollectionPresenterArticle.d.ts.map +0 -1
  149. package/dist/types/src/containers/CollectionPresenterArticle/index.d.ts +0 -2
  150. package/dist/types/src/containers/CollectionPresenterArticle/index.d.ts.map +0 -1
  151. package/dist/types/src/containers/DocumentPresenterContainer/DocumentPresenterContainer.d.ts +0 -6
  152. package/dist/types/src/containers/DocumentPresenterContainer/DocumentPresenterContainer.d.ts.map +0 -1
  153. package/dist/types/src/containers/DocumentPresenterContainer/index.d.ts +0 -2
  154. package/dist/types/src/containers/DocumentPresenterContainer/index.d.ts.map +0 -1
  155. package/dist/types/src/containers/MarkdownSlide/MarkdownSlide.d.ts +0 -8
  156. package/dist/types/src/containers/MarkdownSlide/MarkdownSlide.d.ts.map +0 -1
  157. package/dist/types/src/containers/MarkdownSlide/index.d.ts +0 -2
  158. package/dist/types/src/containers/MarkdownSlide/index.d.ts.map +0 -1
  159. package/src/components/PresenterSettings/PresenterSettings.stories.tsx +0 -32
  160. package/src/components/PresenterSettings/PresenterSettings.tsx +0 -31
  161. package/src/components/PresenterSettings/index.ts +0 -5
  162. package/src/containers/CollectionPresenterArticle/CollectionPresenterArticle.tsx +0 -50
  163. package/src/containers/CollectionPresenterArticle/index.ts +0 -5
  164. package/src/containers/DocumentPresenterContainer/DocumentPresenterContainer.tsx +0 -24
  165. package/src/containers/DocumentPresenterContainer/index.ts +0 -5
  166. package/src/containers/MarkdownSlide/index.ts +0 -5
@@ -0,0 +1,34 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import React from 'react';
6
+
7
+ import { AppSurface, useLayout } from '@dxos/app-toolkit/ui';
8
+ import { type Markdown } from '@dxos/plugin-markdown';
9
+ import { Panel } from '@dxos/react-ui';
10
+
11
+ import { PresentationShell, RevealPlayer } from '#components';
12
+
13
+ import { useExitPresenter } from '../../useExitPresenter';
14
+
15
+ export type DocumentArticleProps = AppSurface.ObjectArticleProps<Markdown.Document>;
16
+
17
+ export const DocumentArticle = ({ role, subject: document }: DocumentArticleProps) => {
18
+ const handleExit = useExitPresenter(document);
19
+ const layout = useLayout();
20
+ const fullscreen = layout.mode === 'solo--fullscreen';
21
+ // RevealPlayer seeds its deck once from `content` (via a `defaultValue`); wait for the markdown ref to
22
+ // resolve so the presentation isn't initialized empty and left blank when the content arrives later.
23
+ const content = document.content.target?.content;
24
+
25
+ return (
26
+ <Panel.Root role={role} classNames='relative'>
27
+ <Panel.Content asChild>
28
+ <PresentationShell fullscreen={fullscreen} onExit={handleExit}>
29
+ {content !== undefined && <RevealPlayer fullscreen={fullscreen} content={content} />}
30
+ </PresentationShell>
31
+ </Panel.Content>
32
+ </Panel.Root>
33
+ );
34
+ };
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ export { DocumentArticle as default } from './DocumentArticle';
@@ -4,22 +4,21 @@
4
4
 
5
5
  import React from 'react';
6
6
 
7
+ import { AppSurface } from '@dxos/app-toolkit/ui';
7
8
  import { type Markdown } from '@dxos/plugin-markdown';
8
9
 
9
10
  import { Panel, Slide } from '#components';
10
11
 
11
- type MarkdownSlideProps = {
12
- document: Markdown.Document;
13
- };
12
+ export type SlideArticleProps = AppSurface.ObjectSectionProps<Markdown.Document>;
14
13
 
15
- export const MarkdownSlide = ({ document }: MarkdownSlideProps) => {
14
+ export const SlideArticle = ({ subject: document }: SlideArticleProps) => {
16
15
  const content = document.content.target?.content;
17
16
  if (!content) {
18
17
  return null;
19
18
  }
20
19
 
21
20
  return (
22
- <Panel>
21
+ <Panel classNames='border'>
23
22
  <Slide content={content} />
24
23
  </Panel>
25
24
  );
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ export { SlideArticle as default } from './SlideArticle';
@@ -4,6 +4,6 @@
4
4
 
5
5
  import { type ComponentType, lazy } from 'react';
6
6
 
7
- export const CollectionPresenterArticle: ComponentType<any> = lazy(() => import('./CollectionPresenterArticle'));
8
- export const DocumentPresenterContainer: ComponentType<any> = lazy(() => import('./DocumentPresenterContainer'));
9
- export const MarkdownSlide: ComponentType<any> = lazy(() => import('./MarkdownSlide'));
7
+ export const CollectionArticle: ComponentType<any> = lazy(() => import('./CollectionArticle'));
8
+ export const DocumentArticle: ComponentType<any> = lazy(() => import('./DocumentArticle'));
9
+ export const SlideArticle: ComponentType<any> = lazy(() => import('./SlideArticle'));
package/src/meta.ts CHANGED
@@ -3,35 +3,7 @@
3
3
  //
4
4
 
5
5
  import { Plugin } from '@dxos/app-framework';
6
- import { DXN } from '@dxos/keys';
7
- import { trim } from '@dxos/util';
8
6
 
9
- export const meta = Plugin.makeMeta({
10
- key: DXN.make('org.dxos.plugin.presenter'),
11
- name: 'Presenter',
12
- author: 'DXOS',
13
- description: trim`
14
- Transform existing workspace objects into interactive presentation slideshows without
15
- duplicating content. Markdown documents are split into slides on horizontal \`---\`
16
- separators and rendered with Reveal.js, giving authors a familiar authoring surface
17
- with full Markdown syntax. Collections can optionally be presented slide-by-slide,
18
- with each member object rendered by its own plugin surface.
7
+ import config from '../dx.config';
19
8
 
20
- Activate presentation mode for any supported object via the action menu or the
21
- Shift+Cmd+P (macOS) / Shift+Alt+P (Windows/Linux) keyboard shortcut. The presenter
22
- opens in a solo fullscreen layout managed by the Deck plugin, keeping the rest of the
23
- workspace undisturbed.
24
-
25
- Navigation controls and a page-number indicator are shown during collection
26
- slideshows. Pressing Escape exits fullscreen and returns to the originating document
27
- or collection view. All navigation is keyboard-accessible.
28
-
29
- Collaboration is inherent: because slides are backed by live ECHO objects, edits made
30
- by any peer in the workspace are immediately reflected in an open presentation without
31
- any manual refresh.
32
- `,
33
- icon: 'ph--presentation--regular',
34
- iconHue: 'indigo',
35
- source: 'https://github.com/dxos/dxos/tree/main/packages/plugins/plugin-presenter',
36
- spec: 'PLUGIN.mdl',
37
- });
9
+ export const meta = Plugin.getMetaFromConfig(config);
@@ -0,0 +1,7 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { OperationHandlerSet } from '@dxos/compute';
6
+
7
+ export const PresenterOperationHandlerSet = OperationHandlerSet.lazy(() => import('./toggle-presentation'));
@@ -0,0 +1,59 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+
7
+ import { Capabilities } from '@dxos/app-framework';
8
+ import { LayoutOperation, Paths } from '@dxos/app-toolkit';
9
+ import { Operation } from '@dxos/compute';
10
+ import { Obj } from '@dxos/echo';
11
+ import { DeckCapabilities, DeckOperation } from '@dxos/plugin-deck';
12
+
13
+ import { PresenterOperation } from '#types';
14
+
15
+ import { getPresentationPath } from '../paths';
16
+
17
+ /**
18
+ * Enters or exits presentation for the given object. When `state` is omitted the
19
+ * current presentation state is toggled. Entering fullscreens the presenter companion;
20
+ * exiting reverts fullscreen and re-opens the source object.
21
+ */
22
+ const handler: Operation.WithHandler<typeof PresenterOperation.TogglePresentation> =
23
+ PresenterOperation.TogglePresentation.pipe(
24
+ Operation.withHandler(
25
+ Effect.fnUntraced(function* ({ object, state }) {
26
+ const db = Obj.getDatabase(object);
27
+ if (!db) {
28
+ return;
29
+ }
30
+
31
+ const objectPath = Paths.getObjectPathFromObject(object);
32
+ const presenterId = getPresentationPath(objectPath);
33
+ const deckState = yield* Capabilities.getAtomValue(DeckCapabilities.State);
34
+ const deck = deckState.decks[deckState.activeDeck];
35
+ const presenting = Boolean(deck?.fullscreen && deck?.solo === presenterId);
36
+ const next = state ?? !presenting;
37
+
38
+ if (next) {
39
+ if (!deck?.fullscreen) {
40
+ yield* Operation.invoke(DeckOperation.Adjust, { type: 'solo--fullscreen' as const, id: presenterId });
41
+ }
42
+ yield* Operation.invoke(LayoutOperation.Open, {
43
+ subject: [presenterId],
44
+ workspace: Paths.getSpacePath(db.spaceId),
45
+ });
46
+ } else {
47
+ if (deck?.fullscreen) {
48
+ yield* Operation.invoke(DeckOperation.Adjust, { type: 'solo--fullscreen' as const, id: objectPath });
49
+ }
50
+ yield* Operation.invoke(LayoutOperation.Open, {
51
+ subject: [objectPath],
52
+ workspace: Paths.getSpacePath(db.spaceId),
53
+ });
54
+ }
55
+ }),
56
+ ),
57
+ );
58
+
59
+ export default handler;
package/src/paths.ts ADDED
@@ -0,0 +1,8 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { linkedSegment } from '@dxos/react-ui-attention';
6
+
7
+ /** Canonical qualified path to the presentation companion node for an object. */
8
+ export const getPresentationPath = (objectPath: string): string => `${objectPath}/${linkedSegment('presenter')}`;
@@ -9,9 +9,8 @@ import { meta } from '#meta';
9
9
  export const translations = [
10
10
  {
11
11
  'en-US': {
12
- [meta.id]: {
12
+ [meta.profile.key]: {
13
13
  'plugin.name': 'Presenter',
14
- 'settings.title': 'Presenter settings',
15
14
  'toggle-presentation.label': 'Present',
16
15
  },
17
16
  },
@@ -12,4 +12,6 @@ import { meta } from '#meta';
12
12
 
13
13
  // Inline import to avoid `Settings` namespace alias colliding with the
14
14
  // `Settings` capability export below.
15
- export const Settings = Capability.make<Atom.Writable<import('./Settings').Settings>>(`${meta.id}.capability.settings`);
15
+ export const Settings = Capability.make<Atom.Writable<import('./Settings').Settings>>(
16
+ `${meta.profile.key}.capability.settings`,
17
+ );
@@ -6,21 +6,22 @@
6
6
 
7
7
  import * as Schema from 'effect/Schema';
8
8
 
9
+ import { Capability } from '@dxos/app-framework';
9
10
  import { Operation } from '@dxos/compute';
10
- import { Collection, Type, DXN } from '@dxos/echo';
11
+ import { Collection, DXN, Type } from '@dxos/echo';
11
12
  import { Markdown } from '@dxos/plugin-markdown';
12
13
 
13
14
  import { meta } from '#meta';
14
15
 
15
- const makeKey = (name: string) => DXN.make(`${meta.id}.operation.${name}`);
16
+ const makeKey = (name: string) => DXN.make(`${meta.profile.key}.operation.${name}`);
16
17
 
17
- // TODO(wittjosiah): This appears to be unused.
18
18
  export const TogglePresentation = Operation.make({
19
19
  meta: {
20
20
  key: makeKey('togglePresentation'),
21
21
  name: 'Toggle Presentation',
22
22
  icon: 'ph--presentation--regular',
23
23
  },
24
+ services: [Capability.Service],
24
25
  input: Schema.Struct({
25
26
  object: Schema.Union(Type.getSchema(Markdown.Document), Type.getSchema(Collection.Collection)),
26
27
  state: Schema.optional(Schema.Boolean),
@@ -2,35 +2,22 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { useAtomValue } from '@effect-atom/atom-react';
6
- import { useCallback, useMemo } from 'react';
5
+ import { useCallback } from 'react';
7
6
 
8
- import { useCapability, useOperationInvoker } from '@dxos/app-framework/ui';
9
- import { LayoutOperation, getObjectPathFromObject, getSpacePath } from '@dxos/app-toolkit';
10
- import { Obj } from '@dxos/echo';
11
- import { DeckCapabilities, DeckOperation } from '@dxos/plugin-deck';
7
+ import { useOperationInvoker } from '@dxos/app-framework/ui';
12
8
 
9
+ import { PresenterOperation } from '#types';
10
+
11
+ /**
12
+ * Exits presentation for the given object. Delegates to the toggle operation so the
13
+ * fullscreen-revert and re-open run sequentially in a single handler — invoking them
14
+ * separately races, leaving the deck stuck in fullscreen.
15
+ */
13
16
  export const useExitPresenter = (object: any) => {
14
17
  const { invokePromise } = useOperationInvoker();
15
- const stateAtom = useCapability(DeckCapabilities.State);
16
- const state = useAtomValue(stateAtom);
17
-
18
- // Compute deck from decks[activeDeck] since the getter doesn't survive spread operations.
19
- const deck = useMemo(() => state.decks[state.activeDeck], [state.decks, state.activeDeck]);
20
-
21
- return useCallback(() => {
22
- const objectPath = getObjectPathFromObject(object);
23
- const db = Obj.getDatabase(object);
24
- if (deck?.fullscreen) {
25
- void invokePromise(DeckOperation.Adjust, {
26
- type: 'solo--fullscreen' as const,
27
- id: objectPath,
28
- });
29
- }
30
18
 
31
- return invokePromise(LayoutOperation.Open, {
32
- subject: [objectPath],
33
- workspace: db ? getSpacePath(db.spaceId) : undefined,
34
- });
35
- }, [invokePromise, object, deck]);
19
+ return useCallback(
20
+ () => invokePromise(PresenterOperation.TogglePresentation, { object, state: false }),
21
+ [invokePromise, object],
22
+ );
36
23
  };
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/containers/CollectionPresenterArticle/CollectionPresenterArticle.tsx"],
4
- "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport React, { useContext, useState } from 'react';\n\nimport { Surface } from '@dxos/app-framework/ui';\nimport { AppSurface } from '@dxos/app-toolkit/ui';\nimport { type Collection, Obj } from '@dxos/echo';\nimport { Panel } from '@dxos/react-ui';\n\nimport { PageNumber, Pager, Layout as PresenterLayout } from '#components';\nimport { PresenterContext } from '#types';\n\nimport { useExitPresenter } from '../../useExitPresenter';\n\nexport type CollectionPresenterArticleProps = AppSurface.ObjectArticleProps<Collection.Collection>;\n\nexport const CollectionPresenterArticle = ({ role, subject: collection }: CollectionPresenterArticleProps) => {\n const [slide, setSlide] = useState(0);\n const { running } = useContext(PresenterContext);\n const handleExit = useExitPresenter(collection);\n\n return (\n <Panel.Root role={role} classNames='relative'>\n <Panel.Content asChild>\n <PresenterLayout\n bottomRight={<PageNumber index={slide} count={collection.objects.length} />}\n bottomLeft={\n <Pager\n index={slide}\n count={collection.objects.length}\n keys={running}\n onChange={setSlide}\n onExit={handleExit}\n />\n }\n >\n <Surface.Surface\n type={AppSurface.Slide}\n data={{\n subject: collection.objects[slide],\n attendableId: Obj.getURI(collection),\n }}\n />\n </PresenterLayout>\n </Panel.Content>\n </Panel.Root>\n );\n};\n"],
5
- "mappings": ";;;;;;AAIA,OAAOA,SAASC,YAAYC,gBAAgB;AAE5C,SAASC,eAAe;AACxB,SAASC,kBAAkB;AAC3B,SAA0BC,WAAW;AACrC,SAASC,aAAa;AAEtB,SAASC,YAAYC,OAAOC,UAAUC,uBAAuB;AAC7D,SAASC,wBAAwB;AAM1B,IAAMC,6BAA6B,CAAC,EAAEC,MAAMC,SAASC,WAAU,MAAmC;AACvG,QAAM,CAACC,OAAOC,QAAAA,IAAYC,SAAS,CAAA;AACnC,QAAM,EAAEC,QAAO,IAAKC,WAAWC,gBAAAA;AAC/B,QAAMC,aAAaC,iBAAiBR,UAAAA;AAEpC,SACE,sBAAA,cAACS,MAAMC,MAAI;IAACZ;IAAYa,YAAW;KACjC,sBAAA,cAACF,MAAMG,SAAO;IAACC,SAAAA;KACb,sBAAA,cAACC,iBAAAA;IACCC,aAAa,sBAAA,cAACC,YAAAA;MAAWC,OAAOhB;MAAOiB,OAAOlB,WAAWmB,QAAQC;;IACjEC,YACE,sBAAA,cAACC,OAAAA;MACCL,OAAOhB;MACPiB,OAAOlB,WAAWmB,QAAQC;MAC1BG,MAAMnB;MACNoB,UAAUtB;MACVuB,QAAQlB;;KAIZ,sBAAA,cAACmB,QAAQA,SAAO;IACdC,MAAMC,WAAWC;IACjBC,MAAM;MACJ/B,SAASC,WAAWmB,QAAQlB,KAAAA;MAC5B8B,cAAcC,IAAIC,OAAOjC,UAAAA;IAC3B;;AAMZ;",
6
- "names": ["React", "useContext", "useState", "Surface", "AppSurface", "Obj", "Panel", "PageNumber", "Pager", "Layout", "PresenterLayout", "PresenterContext", "CollectionPresenterArticle", "role", "subject", "collection", "slide", "setSlide", "useState", "running", "useContext", "PresenterContext", "handleExit", "useExitPresenter", "Panel", "Root", "classNames", "Content", "asChild", "PresenterLayout", "bottomRight", "PageNumber", "index", "count", "objects", "length", "bottomLeft", "Pager", "keys", "onChange", "onExit", "Surface", "type", "AppSurface", "Slide", "data", "attendableId", "Obj", "getURI"]
7
- }
@@ -1,24 +0,0 @@
1
- import {
2
- useExitPresenter
3
- } from "./chunk-V323QBC3.mjs";
4
- import "./chunk-J5LGTIGS.mjs";
5
-
6
- // src/containers/DocumentPresenterContainer/DocumentPresenterContainer.tsx
7
- import React from "react";
8
- import { Panel } from "@dxos/react-ui";
9
- import { RevealPlayer } from "#components";
10
- var DocumentPresenterContainer = ({ document }) => {
11
- const handleExit = useExitPresenter(document);
12
- return /* @__PURE__ */ React.createElement(Panel.Root, {
13
- classNames: "relative"
14
- }, /* @__PURE__ */ React.createElement(Panel.Content, {
15
- asChild: true
16
- }, /* @__PURE__ */ React.createElement(RevealPlayer, {
17
- content: document.content.target?.content ?? "",
18
- onExit: handleExit
19
- })));
20
- };
21
- export {
22
- DocumentPresenterContainer as default
23
- };
24
- //# sourceMappingURL=DocumentPresenterContainer-KCDZ2O2C.mjs.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/containers/DocumentPresenterContainer/DocumentPresenterContainer.tsx"],
4
- "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport React, { type FC } from 'react';\n\nimport { type Markdown } from '@dxos/plugin-markdown';\nimport { Panel } from '@dxos/react-ui';\n\nimport { RevealPlayer } from '#components';\n\nimport { useExitPresenter } from '../../useExitPresenter';\n\nexport const DocumentPresenterContainer: FC<{ document: Markdown.Document }> = ({ document }) => {\n const handleExit = useExitPresenter(document);\n\n return (\n <Panel.Root classNames='relative'>\n <Panel.Content asChild>\n <RevealPlayer content={document.content.target?.content ?? ''} onExit={handleExit} />\n </Panel.Content>\n </Panel.Root>\n );\n};\n"],
5
- "mappings": ";;;;;;AAIA,OAAOA,WAAwB;AAG/B,SAASC,aAAa;AAEtB,SAASC,oBAAoB;AAItB,IAAMC,6BAAkE,CAAC,EAAEC,SAAQ,MAAE;AAC1F,QAAMC,aAAaC,iBAAiBF,QAAAA;AAEpC,SACE,sBAAA,cAACG,MAAMC,MAAI;IAACC,YAAW;KACrB,sBAAA,cAACF,MAAMG,SAAO;IAACC,SAAAA;KACb,sBAAA,cAACC,cAAAA;IAAaC,SAAST,SAASS,QAAQC,QAAQD,WAAW;IAAIE,QAAQV;;AAI/E;",
6
- "names": ["React", "Panel", "RevealPlayer", "DocumentPresenterContainer", "document", "handleExit", "useExitPresenter", "Panel", "Root", "classNames", "Content", "asChild", "RevealPlayer", "content", "target", "onExit"]
7
- }
@@ -1,18 +0,0 @@
1
- import "./chunk-J5LGTIGS.mjs";
2
-
3
- // src/containers/MarkdownSlide/MarkdownSlide.tsx
4
- import React from "react";
5
- import { Panel, Slide } from "#components";
6
- var MarkdownSlide = ({ document }) => {
7
- const content = document.content.target?.content;
8
- if (!content) {
9
- return null;
10
- }
11
- return /* @__PURE__ */ React.createElement(Panel, null, /* @__PURE__ */ React.createElement(Slide, {
12
- content
13
- }));
14
- };
15
- export {
16
- MarkdownSlide as default
17
- };
18
- //# sourceMappingURL=MarkdownSlide-WXILOIBE.mjs.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/containers/MarkdownSlide/MarkdownSlide.tsx"],
4
- "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport React from 'react';\n\nimport { type Markdown } from '@dxos/plugin-markdown';\n\nimport { Panel, Slide } from '#components';\n\ntype MarkdownSlideProps = {\n document: Markdown.Document;\n};\n\nexport const MarkdownSlide = ({ document }: MarkdownSlideProps) => {\n const content = document.content.target?.content;\n if (!content) {\n return null;\n }\n\n return (\n <Panel>\n <Slide content={content} />\n </Panel>\n );\n};\n"],
5
- "mappings": ";;;AAIA,OAAOA,WAAW;AAIlB,SAASC,OAAOC,aAAa;AAMtB,IAAMC,gBAAgB,CAAC,EAAEC,SAAQ,MAAsB;AAC5D,QAAMC,UAAUD,SAASC,QAAQC,QAAQD;AACzC,MAAI,CAACA,SAAS;AACZ,WAAO;EACT;AAEA,SACE,sBAAA,cAACJ,OAAAA,MACC,sBAAA,cAACC,OAAAA;IAAMG;;AAGb;",
6
- "names": ["React", "Panel", "Slide", "MarkdownSlide", "document", "content", "target"]
7
- }
@@ -1,25 +0,0 @@
1
- import "./chunk-J5LGTIGS.mjs";
2
-
3
- // src/components/PresenterSettings/PresenterSettings.tsx
4
- import React from "react";
5
- import { useTranslation } from "@dxos/react-ui";
6
- import { Settings as SettingsForm } from "@dxos/react-ui-form";
7
- import { meta } from "#meta";
8
- import { Settings } from "#types";
9
- var PresenterSettings = ({ settings, onSettingsChange }) => {
10
- const { t } = useTranslation(meta.id);
11
- return /* @__PURE__ */ React.createElement(SettingsForm.Viewport, null, /* @__PURE__ */ React.createElement(SettingsForm.Section, {
12
- title: t("settings.title", {
13
- ns: meta.id
14
- })
15
- }, /* @__PURE__ */ React.createElement(SettingsForm.FieldSet, {
16
- readonly: !onSettingsChange,
17
- schema: Settings.Settings,
18
- values: settings,
19
- onValuesChanged: (values) => onSettingsChange?.(() => values)
20
- })));
21
- };
22
- export {
23
- PresenterSettings as default
24
- };
25
- //# sourceMappingURL=PresenterSettings-2G4XD4QY.mjs.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/components/PresenterSettings/PresenterSettings.tsx"],
4
- "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport React from 'react';\n\nimport { type AppSurface } from '@dxos/app-toolkit/ui';\nimport { useTranslation } from '@dxos/react-ui';\nimport { Settings as SettingsForm } from '@dxos/react-ui-form';\n\nimport { meta } from '#meta';\nimport { Settings } from '#types';\n\nexport type PresenterSettingsProps = AppSurface.SettingsArticleProps<Settings.Settings>;\n\nexport const PresenterSettings = ({ settings, onSettingsChange }: PresenterSettingsProps) => {\n const { t } = useTranslation(meta.id);\n\n return (\n <SettingsForm.Viewport>\n <SettingsForm.Section title={t('settings.title', { ns: meta.id })}>\n <SettingsForm.FieldSet\n readonly={!onSettingsChange}\n schema={Settings.Settings}\n values={settings}\n onValuesChanged={(values) => onSettingsChange?.(() => values)}\n />\n </SettingsForm.Section>\n </SettingsForm.Viewport>\n );\n};\n"],
5
- "mappings": ";;;AAIA,OAAOA,WAAW;AAGlB,SAASC,sBAAsB;AAC/B,SAASC,YAAYC,oBAAoB;AAEzC,SAASC,YAAY;AACrB,SAASF,gBAAgB;AAIlB,IAAMG,oBAAoB,CAAC,EAAEC,UAAUC,iBAAgB,MAA0B;AACtF,QAAM,EAAEC,EAAC,IAAKP,eAAeG,KAAKK,EAAE;AAEpC,SACE,sBAAA,cAACN,aAAaO,UAAQ,MACpB,sBAAA,cAACP,aAAaQ,SAAO;IAACC,OAAOJ,EAAE,kBAAkB;MAAEK,IAAIT,KAAKK;IAAG,CAAA;KAC7D,sBAAA,cAACN,aAAaW,UAAQ;IACpBC,UAAU,CAACR;IACXS,QAAQd,SAASA;IACjBe,QAAQX;IACRY,iBAAiB,CAACD,WAAWV,mBAAmB,MAAMU,MAAAA;;AAKhE;",
6
- "names": ["React", "useTranslation", "Settings", "SettingsForm", "meta", "PresenterSettings", "settings", "onSettingsChange", "t", "id", "Viewport", "Section", "title", "ns", "FieldSet", "readonly", "schema", "values", "onValuesChanged"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/capabilities/app-graph-builder.ts"],
4
- "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\nimport * as Option from 'effect/Option';\n\nimport { Capabilities, Capability } from '@dxos/app-framework';\nimport { AppCapabilities, AppNode, LayoutOperation, getObjectPathFromObject, getSpacePath } from '@dxos/app-toolkit';\nimport { Operation } from '@dxos/compute';\nimport { Collection, Obj } from '@dxos/echo';\nimport { DeckCapabilities, DeckOperation } from '@dxos/plugin-deck';\nimport { GraphBuilder, type Node, NodeMatcher } from '@dxos/plugin-graph';\nimport { Markdown } from '@dxos/plugin-markdown';\nimport { linkedSegment } from '@dxos/react-ui-attention';\n\nimport { meta } from '#meta';\nimport { PresenterOperation } from '#types';\nimport { PresenterCapabilities } from '#types';\n\n/** Match nodes that can be presented (Collection or Document). */\nconst whenPresentable = (node: Node.Node) =>\n Option.orElse(NodeMatcher.whenEchoType(Collection.Collection)(node), () =>\n NodeMatcher.whenEchoType(Markdown.Document)(node),\n );\n\nexport default Capability.makeModule(\n Effect.fnUntraced(function* () {\n const capabilities = yield* Capability.Service;\n\n const extensions = yield* GraphBuilder.createExtension({\n id: 'root',\n // TODO(wittjosiah): This is a hack to work around presenter previously relying on \"variant\". Remove.\n match: whenPresentable,\n connector: (object, get) => {\n const settingsAtom = capabilities.get(PresenterCapabilities.Settings);\n const settings = get(settingsAtom);\n const isPresentable = settings?.presentCollections\n ? Obj.instanceOf(Collection.Collection, object) || Obj.instanceOf(Markdown.Document, object)\n : Obj.instanceOf(Markdown.Document, object);\n if (!isPresentable) {\n return Effect.succeed([]);\n }\n\n return Effect.succeed([\n AppNode.makeCompanion({\n id: linkedSegment('presenter'),\n label: 'Presenter',\n icon: 'ph--presentation--regular',\n data: { type: meta.id, object },\n }),\n ]);\n },\n actions: (object, get) => {\n const settingsAtom = capabilities.get(PresenterCapabilities.Settings);\n const settings = get(settingsAtom);\n const isPresentable = settings?.presentCollections\n ? Obj.instanceOf(Collection.Collection, object) || Obj.instanceOf(Markdown.Document, object)\n : Obj.instanceOf(Markdown.Document, object);\n const db = Obj.getDatabase(object);\n if (!isPresentable || !db) {\n return Effect.succeed([]);\n }\n const objectPath = getObjectPathFromObject(object);\n\n return Effect.succeed([\n {\n id: PresenterOperation.TogglePresentation.meta.key,\n // TODO(burdon): Allow function so can generate state when activated.\n // So can set explicit fullscreen state coordinated with current presenter state.\n data: Effect.fnUntraced(function* () {\n const deckState = yield* Capabilities.getAtomValue(DeckCapabilities.State);\n const deck = deckState.decks[deckState.activeDeck];\n const presenterId = `${objectPath}/${linkedSegment('presenter')}`;\n if (!deck?.fullscreen) {\n yield* Operation.invoke(DeckOperation.Adjust, {\n type: 'solo--fullscreen' as const,\n id: presenterId,\n });\n }\n yield* Operation.invoke(LayoutOperation.Open, {\n subject: [presenterId],\n workspace: getSpacePath(db.spaceId),\n });\n }),\n properties: {\n label: ['toggle-presentation.label', { ns: meta.id }],\n icon: 'ph--presentation--regular',\n disposition: 'list-item',\n keyBinding: {\n macos: 'shift+meta+p',\n windows: 'shift+alt+p',\n },\n },\n },\n ]);\n },\n });\n\n return Capability.contributes(AppCapabilities.AppGraphBuilder, extensions);\n }),\n);\n"],
5
- "mappings": ";;;AAIA,YAAYA,YAAY;AACxB,YAAYC,YAAY;AAExB,SAASC,cAAcC,kBAAkB;AACzC,SAASC,iBAAiBC,SAASC,iBAAiBC,yBAAyBC,oBAAoB;AACjG,SAASC,iBAAiB;AAC1B,SAASC,YAAYC,WAAW;AAChC,SAASC,kBAAkBC,qBAAqB;AAChD,SAASC,cAAyBC,mBAAmB;AACrD,SAASC,gBAAgB;AACzB,SAASC,qBAAqB;AAE9B,SAASC,YAAY;AACrB,SAASC,0BAA0B;AACnC,SAASC,6BAA6B;AAGtC,IAAMC,kBAAkB,CAACC,SAChBC,cAAOR,YAAYS,aAAad,WAAWA,UAAU,EAAEY,IAAAA,GAAO,MACnEP,YAAYS,aAAaR,SAASS,QAAQ,EAAEH,IAAAA,CAAAA;AAGhD,IAAA,4BAAenB,WAAWuB,WACjBC,kBAAW,aAAA;AAChB,QAAMC,eAAe,OAAOzB,WAAW0B;AAEvC,QAAMC,aAAa,OAAOhB,aAAaiB,gBAAgB;IACrDC,IAAI;;IAEJC,OAAOZ;IACPa,WAAW,CAACC,QAAQC,QAAAA;AAClB,YAAMC,eAAeT,aAAaQ,IAAIhB,sBAAsBkB,QAAQ;AACpE,YAAMC,WAAWH,IAAIC,YAAAA;AACrB,YAAMG,gBAAgBD,UAAUE,qBAC5B9B,IAAI+B,WAAWhC,WAAWA,YAAYyB,MAAAA,KAAWxB,IAAI+B,WAAW1B,SAASS,UAAUU,MAAAA,IACnFxB,IAAI+B,WAAW1B,SAASS,UAAUU,MAAAA;AACtC,UAAI,CAACK,eAAe;AAClB,eAAcG,eAAQ,CAAA,CAAE;MAC1B;AAEA,aAAcA,eAAQ;QACpBtC,QAAQuC,cAAc;UACpBZ,IAAIf,cAAc,WAAA;UAClB4B,OAAO;UACPC,MAAM;UACNC,MAAM;YAAEC,MAAM9B,KAAKc;YAAIG;UAAO;QAChC,CAAA;OACD;IACH;IACAc,SAAS,CAACd,QAAQC,QAAAA;AAChB,YAAMC,eAAeT,aAAaQ,IAAIhB,sBAAsBkB,QAAQ;AACpE,YAAMC,WAAWH,IAAIC,YAAAA;AACrB,YAAMG,gBAAgBD,UAAUE,qBAC5B9B,IAAI+B,WAAWhC,WAAWA,YAAYyB,MAAAA,KAAWxB,IAAI+B,WAAW1B,SAASS,UAAUU,MAAAA,IACnFxB,IAAI+B,WAAW1B,SAASS,UAAUU,MAAAA;AACtC,YAAMe,KAAKvC,IAAIwC,YAAYhB,MAAAA;AAC3B,UAAI,CAACK,iBAAiB,CAACU,IAAI;AACzB,eAAcP,eAAQ,CAAA,CAAE;MAC1B;AACA,YAAMS,aAAa7C,wBAAwB4B,MAAAA;AAE3C,aAAcQ,eAAQ;QACpB;UACEX,IAAIb,mBAAmBkC,mBAAmBnC,KAAKoC;;;UAG/CP,MAAapB,kBAAW,aAAA;AACtB,kBAAM4B,YAAY,OAAOrD,aAAasD,aAAa5C,iBAAiB6C,KAAK;AACzE,kBAAMC,OAAOH,UAAUI,MAAMJ,UAAUK,UAAU;AACjD,kBAAMC,cAAc,GAAGT,UAAAA,IAAcnC,cAAc,WAAA,CAAA;AACnD,gBAAI,CAACyC,MAAMI,YAAY;AACrB,qBAAOrD,UAAUsD,OAAOlD,cAAcmD,QAAQ;gBAC5ChB,MAAM;gBACNhB,IAAI6B;cACN,CAAA;YACF;AACA,mBAAOpD,UAAUsD,OAAOzD,gBAAgB2D,MAAM;cAC5CC,SAAS;gBAACL;;cACVM,WAAW3D,aAAa0C,GAAGkB,OAAO;YACpC,CAAA;UACF,CAAA;UACAC,YAAY;YACVxB,OAAO;cAAC;cAA6B;gBAAEyB,IAAIpD,KAAKc;cAAG;;YACnDc,MAAM;YACNyB,aAAa;YACbC,YAAY;cACVC,OAAO;cACPC,SAAS;YACX;UACF;QACF;OACD;IACH;EACF,CAAA;AAEA,SAAOvE,WAAWwE,YAAYvE,gBAAgBwE,iBAAiB9C,UAAAA;AACjE,CAAA,CAAA;",
6
- "names": ["Effect", "Option", "Capabilities", "Capability", "AppCapabilities", "AppNode", "LayoutOperation", "getObjectPathFromObject", "getSpacePath", "Operation", "Collection", "Obj", "DeckCapabilities", "DeckOperation", "GraphBuilder", "NodeMatcher", "Markdown", "linkedSegment", "meta", "PresenterOperation", "PresenterCapabilities", "whenPresentable", "node", "orElse", "whenEchoType", "Document", "makeModule", "fnUntraced", "capabilities", "Service", "extensions", "createExtension", "id", "match", "connector", "object", "get", "settingsAtom", "Settings", "settings", "isPresentable", "presentCollections", "instanceOf", "succeed", "makeCompanion", "label", "icon", "data", "type", "actions", "db", "getDatabase", "objectPath", "TogglePresentation", "key", "deckState", "getAtomValue", "State", "deck", "decks", "activeDeck", "presenterId", "fullscreen", "invoke", "Adjust", "Open", "subject", "workspace", "spaceId", "properties", "ns", "disposition", "keyBinding", "macos", "windows", "contributes", "AppGraphBuilder"]
7
- }
@@ -1,38 +0,0 @@
1
- // src/meta.ts
2
- import { Plugin } from "@dxos/app-framework";
3
- import { DXN } from "@dxos/keys";
4
- import { trim } from "@dxos/util";
5
- var meta = Plugin.makeMeta({
6
- key: DXN.make("org.dxos.plugin.presenter"),
7
- name: "Presenter",
8
- author: "DXOS",
9
- description: trim`
10
- Transform existing workspace objects into interactive presentation slideshows without
11
- duplicating content. Markdown documents are split into slides on horizontal \`---\`
12
- separators and rendered with Reveal.js, giving authors a familiar authoring surface
13
- with full Markdown syntax. Collections can optionally be presented slide-by-slide,
14
- with each member object rendered by its own plugin surface.
15
-
16
- Activate presentation mode for any supported object via the action menu or the
17
- Shift+Cmd+P (macOS) / Shift+Alt+P (Windows/Linux) keyboard shortcut. The presenter
18
- opens in a solo fullscreen layout managed by the Deck plugin, keeping the rest of the
19
- workspace undisturbed.
20
-
21
- Navigation controls and a page-number indicator are shown during collection
22
- slideshows. Pressing Escape exits fullscreen and returns to the originating document
23
- or collection view. All navigation is keyboard-accessible.
24
-
25
- Collaboration is inherent: because slides are backed by live ECHO objects, edits made
26
- by any peer in the workspace are immediately reflected in an open presentation without
27
- any manual refresh.
28
- `,
29
- icon: "ph--presentation--regular",
30
- iconHue: "indigo",
31
- source: "https://github.com/dxos/dxos/tree/main/packages/plugins/plugin-presenter",
32
- spec: "PLUGIN.mdl"
33
- });
34
-
35
- export {
36
- meta
37
- };
38
- //# sourceMappingURL=chunk-PPL2FF6R.mjs.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/meta.ts"],
4
- "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { Plugin } from '@dxos/app-framework';\nimport { DXN } from '@dxos/keys';\nimport { trim } from '@dxos/util';\n\nexport const meta = Plugin.makeMeta({\n key: DXN.make('org.dxos.plugin.presenter'),\n name: 'Presenter',\n author: 'DXOS',\n description: trim`\n Transform existing workspace objects into interactive presentation slideshows without\n duplicating content. Markdown documents are split into slides on horizontal \\`---\\`\n separators and rendered with Reveal.js, giving authors a familiar authoring surface\n with full Markdown syntax. Collections can optionally be presented slide-by-slide,\n with each member object rendered by its own plugin surface.\n\n Activate presentation mode for any supported object via the action menu or the\n Shift+Cmd+P (macOS) / Shift+Alt+P (Windows/Linux) keyboard shortcut. The presenter\n opens in a solo fullscreen layout managed by the Deck plugin, keeping the rest of the\n workspace undisturbed.\n\n Navigation controls and a page-number indicator are shown during collection\n slideshows. Pressing Escape exits fullscreen and returns to the originating document\n or collection view. All navigation is keyboard-accessible.\n\n Collaboration is inherent: because slides are backed by live ECHO objects, edits made\n by any peer in the workspace are immediately reflected in an open presentation without\n any manual refresh.\n `,\n icon: 'ph--presentation--regular',\n iconHue: 'indigo',\n source: 'https://github.com/dxos/dxos/tree/main/packages/plugins/plugin-presenter',\n spec: 'PLUGIN.mdl',\n});\n"],
5
- "mappings": ";AAIA,SAASA,cAAc;AACvB,SAASC,WAAW;AACpB,SAASC,YAAY;AAEd,IAAMC,OAAOH,OAAOI,SAAS;EAClCC,KAAKJ,IAAIK,KAAK,2BAAA;EACdC,MAAM;EACNC,QAAQ;EACRC,aAAaP;;;;;;;;;;;;;;;;;;;;EAoBbQ,MAAM;EACNC,SAAS;EACTC,QAAQ;EACRC,MAAM;AACR,CAAA;",
6
- "names": ["Plugin", "DXN", "trim", "meta", "makeMeta", "key", "make", "name", "author", "description", "icon", "iconHue", "source", "spec"]
7
- }
@@ -1,41 +0,0 @@
1
- // src/useExitPresenter.ts
2
- import { useAtomValue } from "@effect-atom/atom-react";
3
- import { useCallback, useMemo } from "react";
4
- import { useCapability, useOperationInvoker } from "@dxos/app-framework/ui";
5
- import { LayoutOperation, getObjectPathFromObject, getSpacePath } from "@dxos/app-toolkit";
6
- import { Obj } from "@dxos/echo";
7
- import { DeckCapabilities, DeckOperation } from "@dxos/plugin-deck";
8
- var useExitPresenter = (object) => {
9
- const { invokePromise } = useOperationInvoker();
10
- const stateAtom = useCapability(DeckCapabilities.State);
11
- const state = useAtomValue(stateAtom);
12
- const deck = useMemo(() => state.decks[state.activeDeck], [
13
- state.decks,
14
- state.activeDeck
15
- ]);
16
- return useCallback(() => {
17
- const objectPath = getObjectPathFromObject(object);
18
- const db = Obj.getDatabase(object);
19
- if (deck?.fullscreen) {
20
- void invokePromise(DeckOperation.Adjust, {
21
- type: "solo--fullscreen",
22
- id: objectPath
23
- });
24
- }
25
- return invokePromise(LayoutOperation.Open, {
26
- subject: [
27
- objectPath
28
- ],
29
- workspace: db ? getSpacePath(db.spaceId) : void 0
30
- });
31
- }, [
32
- invokePromise,
33
- object,
34
- deck
35
- ]);
36
- };
37
-
38
- export {
39
- useExitPresenter
40
- };
41
- //# sourceMappingURL=chunk-V323QBC3.mjs.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/useExitPresenter.ts"],
4
- "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport { useAtomValue } from '@effect-atom/atom-react';\nimport { useCallback, useMemo } from 'react';\n\nimport { useCapability, useOperationInvoker } from '@dxos/app-framework/ui';\nimport { LayoutOperation, getObjectPathFromObject, getSpacePath } from '@dxos/app-toolkit';\nimport { Obj } from '@dxos/echo';\nimport { DeckCapabilities, DeckOperation } from '@dxos/plugin-deck';\n\nexport const useExitPresenter = (object: any) => {\n const { invokePromise } = useOperationInvoker();\n const stateAtom = useCapability(DeckCapabilities.State);\n const state = useAtomValue(stateAtom);\n\n // Compute deck from decks[activeDeck] since the getter doesn't survive spread operations.\n const deck = useMemo(() => state.decks[state.activeDeck], [state.decks, state.activeDeck]);\n\n return useCallback(() => {\n const objectPath = getObjectPathFromObject(object);\n const db = Obj.getDatabase(object);\n if (deck?.fullscreen) {\n void invokePromise(DeckOperation.Adjust, {\n type: 'solo--fullscreen' as const,\n id: objectPath,\n });\n }\n\n return invokePromise(LayoutOperation.Open, {\n subject: [objectPath],\n workspace: db ? getSpacePath(db.spaceId) : undefined,\n });\n }, [invokePromise, object, deck]);\n};\n"],
5
- "mappings": ";AAIA,SAASA,oBAAoB;AAC7B,SAASC,aAAaC,eAAe;AAErC,SAASC,eAAeC,2BAA2B;AACnD,SAASC,iBAAiBC,yBAAyBC,oBAAoB;AACvE,SAASC,WAAW;AACpB,SAASC,kBAAkBC,qBAAqB;AAEzC,IAAMC,mBAAmB,CAACC,WAAAA;AAC/B,QAAM,EAAEC,cAAa,IAAKT,oBAAAA;AAC1B,QAAMU,YAAYX,cAAcM,iBAAiBM,KAAK;AACtD,QAAMC,QAAQhB,aAAac,SAAAA;AAG3B,QAAMG,OAAOf,QAAQ,MAAMc,MAAME,MAAMF,MAAMG,UAAU,GAAG;IAACH,MAAME;IAAOF,MAAMG;GAAW;AAEzF,SAAOlB,YAAY,MAAA;AACjB,UAAMmB,aAAad,wBAAwBM,MAAAA;AAC3C,UAAMS,KAAKb,IAAIc,YAAYV,MAAAA;AAC3B,QAAIK,MAAMM,YAAY;AACpB,WAAKV,cAAcH,cAAcc,QAAQ;QACvCC,MAAM;QACNC,IAAIN;MACN,CAAA;IACF;AAEA,WAAOP,cAAcR,gBAAgBsB,MAAM;MACzCC,SAAS;QAACR;;MACVS,WAAWR,KAAKd,aAAac,GAAGS,OAAO,IAAIC;IAC7C,CAAA;EACF,GAAG;IAAClB;IAAeD;IAAQK;GAAK;AAClC;",
6
- "names": ["useAtomValue", "useCallback", "useMemo", "useCapability", "useOperationInvoker", "LayoutOperation", "getObjectPathFromObject", "getSpacePath", "Obj", "DeckCapabilities", "DeckOperation", "useExitPresenter", "object", "invokePromise", "stateAtom", "State", "state", "deck", "decks", "activeDeck", "objectPath", "db", "getDatabase", "fullscreen", "Adjust", "type", "id", "Open", "subject", "workspace", "spaceId", "undefined"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/types/index.ts", "../../../src/types/PresenterCapabilities.ts", "../../../src/types/PresenterOperation.ts", "../../../src/types/Settings.ts"],
4
- "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Context, createContext } from 'react';\n\nexport type PresenterContextType = {\n running: boolean;\n start: () => void;\n stop: () => void;\n};\n\nexport const PresenterContext: Context<PresenterContextType> = createContext<PresenterContextType>({\n running: false,\n start: () => {},\n stop: () => {},\n});\n\nexport * as PresenterCapabilities from './PresenterCapabilities';\nexport * as PresenterOperation from './PresenterOperation';\nexport * as Settings from './Settings';\n", "//\n// Copyright 2025 DXOS.org\n//\n\n// @import-as-namespace\n\nimport { type Atom } from '@effect-atom/atom-react';\n\nimport { Capability } from '@dxos/app-framework';\n\nimport { meta } from '#meta';\n\n// Inline import to avoid `Settings` namespace alias colliding with the\n// `Settings` capability export below.\nexport const Settings = Capability.make<Atom.Writable<import('./Settings').Settings>>(`${meta.id}.capability.settings`);\n", "//\n// Copyright 2025 DXOS.org\n//\n\n// @import-as-namespace\n\nimport * as Schema from 'effect/Schema';\n\nimport { Operation } from '@dxos/compute';\nimport { Collection, Type, DXN } from '@dxos/echo';\nimport { Markdown } from '@dxos/plugin-markdown';\n\nimport { meta } from '#meta';\n\nconst makeKey = (name: string) => DXN.make(`${meta.id}.operation.${name}`);\n\n// TODO(wittjosiah): This appears to be unused.\nexport const TogglePresentation = Operation.make({\n meta: {\n key: makeKey('togglePresentation'),\n name: 'Toggle Presentation',\n icon: 'ph--presentation--regular',\n },\n input: Schema.Struct({\n object: Schema.Union(Type.getSchema(Markdown.Document), Type.getSchema(Collection.Collection)),\n state: Schema.optional(Schema.Boolean),\n }),\n output: Schema.Void,\n});\n", "//\n// Copyright 2023 DXOS.org\n//\n\n// @import-as-namespace\n\nimport * as Schema from 'effect/Schema';\n\nexport const Settings = Schema.mutable(\n Schema.Struct({\n presentCollections: Schema.optional(\n Schema.Boolean.annotations({\n title: 'Present collections (experimental)',\n description: 'Enable presenting collections of documents as a slideshow.',\n }),\n ),\n }),\n);\n\nexport interface Settings extends Schema.Schema.Type<typeof Settings> {}\n"],
5
- "mappings": ";;;;;AAIA,SAAuBA,qBAAqB;;;ACJ5C;;;;AAQA,SAASC,kBAAkB;AAE3B,SAASC,YAAY;AAId,IAAMC,WAAWF,WAAWG,KAAmD,GAAGF,KAAKG,EAAE,sBAAsB;;;ACdtH;;;;AAMA,YAAYC,YAAY;AAExB,SAASC,iBAAiB;AAC1B,SAASC,YAAYC,MAAMC,WAAW;AACtC,SAASC,gBAAgB;AAEzB,SAASC,QAAAA,aAAY;AAErB,IAAMC,UAAU,CAACC,SAAiBJ,IAAIK,KAAK,GAAGH,MAAKI,EAAE,cAAcF,IAAAA,EAAM;AAGlE,IAAMG,qBAAqBV,UAAUQ,KAAK;EAC/CH,MAAM;IACJM,KAAKL,QAAQ,oBAAA;IACbC,MAAM;IACNK,MAAM;EACR;EACAC,OAAcC,cAAO;IACnBC,QAAeC,aAAMd,KAAKe,UAAUb,SAASc,QAAQ,GAAGhB,KAAKe,UAAUhB,WAAWA,UAAU,CAAA;IAC5FkB,OAAcC,gBAAgBC,cAAO;EACvC,CAAA;EACAC,QAAeC;AACjB,CAAA;;;AC5BA;;kBAAAC;;AAMA,YAAYC,aAAY;AAEjB,IAAMD,YAAkBE,gBACtBC,eAAO;EACZC,oBAA2BC,iBAClBC,gBAAQC,YAAY;IACzBC,OAAO;IACPC,aAAa;EACf,CAAA,CAAA;AAEJ,CAAA,CAAA;;;AHJK,IAAMC,mBAAkDC,cAAoC;EACjGC,SAAS;EACTC,OAAO,MAAA;EAAO;EACdC,MAAM,MAAA;EAAO;AACf,CAAA;",
6
- "names": ["createContext", "Capability", "meta", "Settings", "make", "id", "Schema", "Operation", "Collection", "Type", "DXN", "Markdown", "meta", "makeKey", "name", "make", "id", "TogglePresentation", "key", "icon", "input", "Struct", "object", "Union", "getSchema", "Document", "state", "optional", "Boolean", "output", "Void", "Settings", "Schema", "mutable", "Struct", "presentCollections", "optional", "Boolean", "annotations", "title", "description", "PresenterContext", "createContext", "running", "start", "stop"]
7
- }
@@ -1,54 +0,0 @@
1
- import "./chunk-J5LGTIGS.mjs";
2
-
3
- // src/capabilities/react-surface.tsx
4
- import * as Effect from "effect/Effect";
5
- import React from "react";
6
- import { Capabilities, Capability } from "@dxos/app-framework";
7
- import { Surface, useSettingsState } from "@dxos/app-framework/ui";
8
- import { AppSurface } from "@dxos/app-toolkit/ui";
9
- import { Collection, Obj } from "@dxos/echo";
10
- import { Markdown } from "@dxos/plugin-markdown";
11
- import { PresenterSettings } from "#components";
12
- import { CollectionPresenterArticle, DocumentPresenterContainer, MarkdownSlide } from "#containers";
13
- import { meta } from "#meta";
14
- var react_surface_default = Capability.makeModule(() => Effect.succeed(Capability.contributes(Capabilities.ReactSurface, [
15
- Surface.create({
16
- id: "document",
17
- position: "first",
18
- filter: AppSurface.predicate(AppSurface.Article, (data) => !!data.subject && typeof data.subject === "object" && "type" in data.subject && "object" in data.subject && data.subject.type === meta.id && Obj.instanceOf(Markdown.Document, data.subject.object)),
19
- component: ({ data }) => /* @__PURE__ */ React.createElement(DocumentPresenterContainer, {
20
- document: data.subject.object
21
- })
22
- }),
23
- Surface.create({
24
- id: "collection",
25
- position: "first",
26
- filter: AppSurface.predicate(AppSurface.Article, (data) => !!data.subject && typeof data.subject === "object" && "type" in data.subject && "object" in data.subject && data.subject.type === meta.id && Obj.instanceOf(Collection.Collection, data.subject.object)),
27
- component: ({ role, data }) => /* @__PURE__ */ React.createElement(CollectionPresenterArticle, {
28
- role,
29
- subject: data.subject.object
30
- })
31
- }),
32
- Surface.create({
33
- id: "slide",
34
- filter: AppSurface.object(AppSurface.Slide, Markdown.Document),
35
- component: ({ data }) => /* @__PURE__ */ React.createElement(MarkdownSlide, {
36
- document: data.subject
37
- })
38
- }),
39
- Surface.create({
40
- id: "pluginSettings",
41
- filter: AppSurface.settings(AppSurface.Article, meta.id),
42
- component: ({ data: { subject } }) => {
43
- const { settings, updateSettings } = useSettingsState(subject.atom);
44
- return /* @__PURE__ */ React.createElement(PresenterSettings, {
45
- settings,
46
- onSettingsChange: updateSettings
47
- });
48
- }
49
- })
50
- ])));
51
- export {
52
- react_surface_default as default
53
- };
54
- //# sourceMappingURL=react-surface-SPJGAJIF.mjs.map