📦 @livepreso/content-react
App​
If you want to add a context manager (a Theming manager for example), you can add it here.
import React from "react";
import { App } from "@livepreso/content-react";
import { ThemeContext } from "your-library";
const app = App.run((Slide) => {
return (
<ThemeContext theme={{ yourTheme }}>
<Slide />
</ThemeContext>
);
});
export default app;
Hooks​
useSharedState(value)​
Like React's useState hook, but state is shared over remote preso automatically. Use is exactly the same.
import React from "react";
export default function () {
const [number, setNumber] = useSharedState(0);
return (
<>
<button onClick={() => setNumber(number - 1)}>-</button>
<button onClick={() => setNumber(number + 1)}>+</button>
<span>Number: {number}</span>
</>
);
}
useSlideContext(path[, defaultValue])​
Retrieve and set (if using a path) context.
import React from "react";
import { useSlideContext } from "@livepreso/content-react";
export default function () {
// Retrieve the whole context as json
const [context] = useSlideContext();
// Update and return a nested path
const [name, setName] = useSlideContext("form.name", "John Doe");
return <div onClick={() => setName("Jane Doe")}>{name}</div>;
}
Internally this uses useSharedState
, so will affect remote presos in the same way.
useCompanywide(cwePath[, defaultValue])​
import React from "react";
import { useCompanywide } from "@livepreso/content-react";
export default function () {
// Update and return a nested path
const [name, setName] = useCompanywide("form.name", "John Doe");
return (
<div
style={{ pointerEvents: "initial" }}
onClick={() => setName("Jane Doe")}
>
{name}
</div>
);
}
When in presomanager mode, elements that need to be interactive should have pointer-events: initial
set, otherwise it can't be clicked.
Companywide json not working? Make sure to set cweJson: true
on the slide, section or template in
your project.yaml
useEditableInitialState(key[, defaultValue])​
Retrieves the key and value of a requested slide CWE, PM template or user template field. Adjusts the field key as required for user and PM templates.
import React from 'react';
import { useEditableInitialState } from '@livepreso/content-react';
export default function () {
const [imageURL, imageKey] = useEditableInitialState('image-id', '');
const CWEKeys = Bridge.Companywide.getSlideKeys() || [];
const hasImageField = CWEKeys.includes(imageKey);
let bgStyle = {};
if (imageURL) {
bgStyle = { ...bgStyle, backgroundImage: `url(${imageURL})` };
}
return (
{hasImageField && <div style={bgStyle} />}
);
}
This hook is not tied to a state, as such it will not update when changes are made to the requested editable field. This hook will only return a new value when re-run.
usePrepEditableInfo(id)​
Used for checking the current value of a prep editable, whether the user has edited it, and the slide-specific key - useful when the chosen editable has been used on a user or PM template slide and the key has been modified by the LivePreso app.
import React from "react";
import { usePrepEditableInfo } from "@livepreso/content-react";
export default function () {
const { key, value, hasValue } = usePrepEditableInfo("my-id");
// key: modified if requested key is used in a user template or PM template
// value: null if not modified, else saved value
// hasValue: true or false (essentially checks `value === null`)
return (
<div>
<h1 data-editable="my-id">Hello world</h1>
<div>{hasValue ? <p>Readonly {value}</p> : <p>No ID saved</p>}</div>
</div>
);
}
This hook won't return the default value, it will return 'null' if not value has been saved. To get the original value you must get it from the DOM.
usePrepEditableValue(id[, defaultValue])​
Returns the current value of a prep editable.
Returns null
if no defaultValue
is supplied.
import React from "react";
import { usePrepEditableValue } from "@livepreso/content-react";
export default function () {
const value = usePrepEditableValue("my-id", "no saved value");
return (
<div>
<h1 data-editable="my-id">Hello world</h1>
<p>Readonly {value}</p>
</div>
);
}
useCWEEditableInfo(id)​
Returns the current value of a companywide or user template editable, whether the user has edited it, and the slide-specific key - useful when the chosen editable has been used on a user or PM template slide and the key has been modified by the LivePreso app.
When this hook is used in PresoManager, we have no way to watch for updates, and hence cannot update the state automatically. As secureHeapUsed, this hook also returns a function to get the latest value and force update the state - useful if you have a dynamic image in PresoManager that you want to refresh.
import React from "react";
import { useCWEEditableInfo } from "@livepreso/content-react";
export default function () {
const { key, value, hasValue, updateValue } = useCWEEditableInfo("my-id");
// key: modified if requested key is used in a user template or PM template
// value: null if not modified, else saved value
// hasValue: true or false (essentially checks `value === null`)
return (
<div>
<h1 data-companywide-editable="my-id">Hello world</h1>
<div>{hasValue ? <p>Readonly {value}</p> : <p>No ID saved</p>}</div>
</div>
);
}
The hook won't return the default value, it will return 'null' if it's not been sent. To get the original value you must get it from the DOM.
There is currently no way to watch for changes to CWE fields while in PresoManager.
As such, state will be ignored in PresoManager. To get the latest value in this mode,
the hook will either need to be re-rendered, or you can use the updateValue
function
to force a refetch and update of the state.
useCWEEditableValue(id[, defaultValue])​
Returns the current value of a companywide or user template editable.
Returns null
if no defaultValue
is supplied.
import React from "react";
import { useCWEEditableValue } from "@livepreso/content-react";
export default function () {
const value = useCWEEditableValue("my-id", "no saved value");
return (
<div>
<h1 data-companywide-editable="my-id">Hello world</h1>
<p>Readonly {value}</p>
</div>
);
}
Has the same PresoManager restrictions as useCWEEditableInfo()
.
useEditableFieldKey(id)​
Takes a base key, and returns a modified field key depending on the slide type (ie. standard, user template or presomanager template) and the current slide's unique identifying information - as is applied to the field key by the LivePreso app.
Useful when manually searching for a templated slide's CWE or prep data, or checking an old template slide's compatibility with a new update (see example below).
import React from "react";
import { useEditableFieldKey } from "@livepreso/content-react";
export default function () {
const imageKey = "welcome_image";
const key = useEditableFieldKey(imageKey);
// Checks if 'welcome_image' is a registered CWE key,
// useful when upgrading an existing template as new CWE keys
// cannot be registered to existing slides of an upgraded template.
const CWEKeys = Bridge.Companywide.getSlideKeys() || [];
const hasImageField = CWEKeys.includes(key);
if (!hasImageField) {
return null;
}
return <div data-companywide-dynamic-image={imageKey} />;
}
In most cases, usePrepEditableInfo(key)
or useCWEEditableInfo(key)
will be the function you want to use.
useSlideReady(fn)​
Helper function for checking when a slide is ready.
import React from "react";
import { useSlideReady } from "@livepreso/content-react";
export default function () {
useSlideReady(() => {
// Your functions here
initiateCharts();
});
// ...
}
useSlideDone()​
Gives access to the done method for asynchronous page loads, generally used for making sure the page is loaded before screenshots happen.
import React from "react";
import { useSlideDone } from "@livepreso/content-react";
export default function () {
const done = useSlideDone();
useEffect(() => {
// Call the done function whenever what you want is ready
setTimeout(() => {
done();
}, 1000);
}, []);
}
This uses done in the 'slideready' event.
useModes()​
Returns useful information about the presentation
import React from "react";
import { useModes } from "@livepreso/content-react";
export default function () {
const {
// Whether current app is master
isMaster,
// Whether current app is client
isClient,
// If app has a network connection
isOnline,
// If the presentation is being viewed in 'read-only' mode
isReadOnly,
// If app is in screenshot mode
isScreenshot,
// If app is in thumbnail screenshot mode
isThumbnailScreenshot,
// If app is in thumbnail pdf mode
isPdfScreenshot,
// If app is a share
isShareOnline,
// If presentation is in "prep" mode
isPreview,
// If presentation is in "present" mode
isPresent,
// If presentation is in "review" mode
isReview,
// If app is being shared remotely, controlled by the master.
isRemote,
// If the app is in the presomanager page, and not read-only
isPresomanager,
// If content is being previewed without an association to a preso (PresoManager, Presets)
isEmptyPreview,
} = useModes();
// ...
}
useSlide()​
Returns useful information about the current slide
import React from "react";
import { useSlide } from "@livepreso/content-react";
export default function () {
const {
transitions,
// The article ID. Generally only useful for working out
// paths for editables.
slideID,
// The key as was written in the project file.
slideKey,
// The key used by the presentation. This is the one you want
// to use if looking up a path.
presentationKey,
isCurrentSlide,
} = useSlide();
// See useTransitions() for a shortcut
const { entering, exiting, entered } = transitions;
//...
}
useSubslides()​
If slide contains subslides, contains information and actions for controlling and using them.
import React from "react";
import { useSubslides } from "@livepreso/content-react";
export default function () {
const {
// Total number of subslides
totalSubslides,
// Returns index of current active subslide
currentSubslideIndex,
// Returns true if we're on the first subslide
atTop,
// Returns true if we're on the last subslide
atBottom,
// Method to go up a subslide. No-op if at top.
navigateTo,
// Method to go directly to a subslide by index. No-op if out of bounds.
navigateUp,
// Method to go down a subslide. No-op if at bottom.
navigateDown,
// Object containing current animation states. See below.
animating,
} = useSubslides();
const {
// True if currently animating up
up,
// True if currently animating down
down,
} = animating;
// ...
}
useTransitions()​
Access states of transition for the current slide. Useful for animation.
import React from "react";
import { useTransitions } from "@livepreso/content-react";
export default function () {
const { entering, exiting, entered } = useTransitions();
// ...
}
If in screenshot mode, the transitions will always be set to entered
as true,
and exiting
, entering
will always be false.
Contexts​
SlideContext​
Contains information about the current slide.
See useSlide
import { useContext }, React from "react";
import { SlideContext } from "@livepreso/content-react";
export default function() {
const context = useContext(SlideContext);
const {
// The article ID. Generally only useful for working out
// paths for editables.
slideID,
// The key as was written in the project file.
slideKey,
// The key used by the presentation. This is the one you want
// to use if looking up a path.
presentationKey,
// Whether this slide is being viewed currently
isCurrentSlide,
// Object of current transition properties. See below.
transitions
} = context;
const {
// True if currently entering the view
entering,
// True if entered the view (stopped animating)
entered,
// True if exiting the view
exiting,
// True if slide has been removed
exited
} = transitions
// ...
}
SubslidesContext​
Contains information about the current subslides.
See useSubslides
import { useContext }, React from "react";
import { SubslidesContext } from "@livepreso/content-react";
export default function() {
const context = useContext(SubslidesContext);
const {
// Object containing animation transitions. See below.
animating
} = context;
const {
// True if currently animating up
up,
// True if currently animating down
down
} = animating;
// ...
}
SubslideContext​
Contains information about the current subslide. This should be used on
a component inside the Subslide
component or it will not work.
See useSubslides
import { useContext }, React from "react";
import { SubslideContext } from "@livepreso/content-react";
export default function() {
const context = useContext(SubslideContext);
const {
// True if the current active subslide
isActive,
// Object of current transition properties. See below.
transitions
} = context;
const {
// True if currently entering the view
entering,
// True if entered the view (stopped animating)
entered,
// True if exiting the view
exiting,
// True if slide has been removed
exited
} = transitions
// ...
}
Components​
Subslides​
There are three separate components that can be used for subslides, Subslides, Subslide and ScrollableArea.
import React from "react";
import { Subslides, Subslide, ScrollableArea } from "@livepreso/content-react";
export default function () {
return (
<Subslides>
<ScrollableArea>
<Subslide>Your subslide here</Subslide>
<Subslide>Your subslide here</Subslide>
<Subslide>Your subslide here</Subslide>
</ScrollableArea>
{/* Your navigation could go here */}
</Subslides>
);
}
Subslides not working? Currently you need to specify the number of subslides
in the project.yaml for the slide containing subslides, just add subslides: 3
to the
slide object.
Subslide​
See above.
ScrollableArea​
See above.