Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ out
.env
extension.js
extension.js.LICENSE.txt
local/
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@

Type `{{presentation}}` or `{{slides}}` in a block. Clicking the button will overlay a presentation directly from Roam! Exit the presentation by hitting 'ESC'.

An experimental native-renderer path is available alongside the current
renderer. Use `{{presentation2}}` or `{{slides2}}` to render slide content with
Roam's declarative React APIs while leaving `presentation` and `slides`
unchanged. The paired copy/paste baseline and native-component coverage deck
are in [`fixtures`](fixtures/README.md), and the two component trees are
documented in [`docs/native-renderer-architecture.md`](docs/native-renderer-architecture.md).

To specify what content is part of the presentation, create a child block for each slide. The text of each child will serve as the slide title. Each child block then in turn renders its children as the slide contents in a bulleted outline. For example, the Playground presentation below uses the following structure:

```
Expand Down
103 changes: 103 additions & 0 deletions src/components/NativeRoamContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import React from "react";

type BlockContent = {
kind: "block";
uid: string;
open?: boolean;
zoomPath?: boolean;
zoomStartAfterUid?: string;
};

type PageContent = {
kind: "page";
hideMentions?: boolean;
} & ({ uid: string; title?: never } | { uid?: never; title: string });

type StringContent = {
kind: "string";
string: string;
};

type SearchContent = {
kind: "search";
searchQueryStr: string;
closed?: boolean;
groupByPage?: boolean;
hidePaths?: boolean;
onConfigChange?: (config: {
closed?: boolean;
groupByPage?: boolean;
hidePaths?: boolean;
}) => void;
};

export type NativeRoamContentProps =
BlockContent | PageContent | StringContent | SearchContent;

type NativeReactComponents = {
Block: React.ComponentType<Omit<BlockContent, "kind">>;
Page: React.ComponentType<
| { uid: string; title?: never; hideMentions?: boolean }
| { uid?: never; title: string; hideMentions?: boolean }
>;
Search: React.ComponentType<Omit<SearchContent, "kind">>;
BlockString: React.ComponentType<Omit<StringContent, "kind">>;
};

const getNativeComponents = () => {
const components = (
window.roamAlphaAPI?.ui as typeof window.roamAlphaAPI.ui & {
react?: NativeReactComponents;
}
)?.react;
if (!components) {
throw new Error(
"This version of Roam does not expose roamAlphaAPI.ui.react.",
);
}
return components;
};

/**
* One typed entry point for Roam's native React renderers.
*
* Presentation2 currently uses `block` for slide trees and notes, and
* `string` for titles whose presentation directives have been removed.
* `page` and `search` are included here for page-oriented and search-result
* slides without introducing another rendering abstraction later.
*/
const NativeRoamContent = (props: NativeRoamContentProps) => {
const { Block, Page, Search, BlockString } = getNativeComponents();

switch (props.kind) {
case "block":
return (
<Block
uid={props.uid}
open={props.open}
zoomPath={props.zoomPath}
zoomStartAfterUid={props.zoomStartAfterUid}
/>
);
case "page":
return props.uid ? (
<Page uid={props.uid} hideMentions={props.hideMentions} />
) : (
<Page title={props.title as string} hideMentions={props.hideMentions} />
);
case "search":
return (
<Search
searchQueryStr={props.searchQueryStr}
closed={props.closed}
groupByPage={props.groupByPage}
hidePaths={props.hidePaths}
onConfigChange={props.onConfigChange}
/>
);
case "string":
return <BlockString string={props.string} />;
}
};

export default NativeRoamContent;
9 changes: 7 additions & 2 deletions src/components/Presentation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ const parseSolo = ({
viewType: "document",
children: [],
uid: "",
parents: [],
heading: 0,
open: true,
textAlign,
Expand Down Expand Up @@ -588,7 +589,7 @@ const ContentSlide = ({
__html: parseRoamBlocks({ content: bullets, viewType }),
}}
style={{
width: isImageLayout ? "50%" : "100%",
width: isSourceLayout && !isCenterLayout ? "50%" : "100%",
transformOrigin: "left top",
wordBreak: "break-word",
display: isCenterLayout ? "none" : "block",
Expand Down Expand Up @@ -838,7 +839,11 @@ const PresentationContent: React.FunctionComponent<{
}, [revealRef, initialized, startIndex, slides, mappedSlides]);
return (
<>
<div className="reveal" id="roamjs-reveal-root">
<div
className="reveal"
id="roamjs-reveal-root"
data-roamjs-show-notes={showNotes}
>
<div className="slides" ref={slidesRef}>
{mappedSlides.map((s: TreeNode & ContentSlideExtras, i) => (
<React.Fragment key={i}>
Expand Down
Loading
Loading