@livepreso/content-react 0.3.4 → 0.3.6

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.
@@ -1,5 +1,5 @@
1
1
  {
2
- "../../content/content-react": "../../content/content-react:gIunKntbEKHWcVSt+h52eM+NioiBP31+ikW5HR9+F8o=:",
2
+ "../../content/content-react": "../../content/content-react:bddeBDvUeJPa+NT4hb6TbJCKyl7AZrKwScnaAaM2sGc=:",
3
3
  "/@babel/helper-annotate-as-pure/7.22.5": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==",
4
4
  "/@babel/helper-module-imports/7.22.15": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==",
5
5
  "/@babel/helper-plugin-utils/7.22.5": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==",
package/CHANGELOG.json CHANGED
@@ -1,6 +1,35 @@
1
1
  {
2
2
  "name": "@livepreso/content-react",
3
3
  "entries": [
4
+ {
5
+ "version": "0.3.6",
6
+ "tag": "@livepreso/content-react_v0.3.6",
7
+ "date": "Wed, 20 Mar 2024 01:31:57 GMT",
8
+ "comments": {
9
+ "patch": [
10
+ {
11
+ "comment": "Subslide functionaly accessible throughout slides"
12
+ }
13
+ ]
14
+ }
15
+ },
16
+ {
17
+ "version": "0.3.5",
18
+ "tag": "@livepreso/content-react_v0.3.5",
19
+ "date": "Sun, 03 Mar 2024 23:59:09 GMT",
20
+ "comments": {
21
+ "patch": [
22
+ {
23
+ "comment": "Hot reload improvements"
24
+ }
25
+ ],
26
+ "dependency": [
27
+ {
28
+ "comment": "Updating dependency \"@livepreso/content-base\" from `~1.1.2` to `~1.1.3`"
29
+ }
30
+ ]
31
+ }
32
+ },
4
33
  {
5
34
  "version": "0.3.4",
6
35
  "tag": "@livepreso/content-react_v0.3.4",
package/CHANGELOG.md CHANGED
@@ -1,6 +1,20 @@
1
1
  # Change Log - @livepreso/content-react
2
2
 
3
- This log was last generated on Sun, 14 Jan 2024 21:06:16 GMT and should not be manually modified.
3
+ This log was last generated on Wed, 20 Mar 2024 01:31:57 GMT and should not be manually modified.
4
+
5
+ ## 0.3.6
6
+ Wed, 20 Mar 2024 01:31:57 GMT
7
+
8
+ ### Patches
9
+
10
+ - Subslide functionaly accessible throughout slides
11
+
12
+ ## 0.3.5
13
+ Sun, 03 Mar 2024 23:59:09 GMT
14
+
15
+ ### Patches
16
+
17
+ - Hot reload improvements
4
18
 
5
19
  ## 0.3.4
6
20
  Sun, 14 Jan 2024 21:06:16 GMT
package/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import React, { useEffect } from "react";
2
2
 
3
3
  import { AppBase } from "@livepreso/content-base";
4
- import { createRoot } from "react-dom/client";
5
4
  import { CompanywideJSON } from "./lib/components/CompanywideJSON.js";
6
5
  import { SlideContext } from "./lib/contexts.js";
6
+ import { createRoot } from "react-dom/client";
7
7
  import errorFn from "@livepreso/content-base/error.js";
8
8
  import { useRootSlide } from "./lib/hooks/use-root-slide.js";
9
9
 
@@ -26,6 +26,10 @@ class ErrorBoundary extends React.Component {
26
26
  }
27
27
  }
28
28
 
29
+ if (module.hot && typeof window.__deck_roots__ === "undefined") {
30
+ window.__deck_roots__ = {};
31
+ }
32
+
29
33
  export class App extends AppBase {
30
34
  static run(rootApp = null) {
31
35
  const base = new App();
@@ -41,8 +45,17 @@ export class App extends AppBase {
41
45
 
42
46
  defaultRenderer(Slide, article) {
43
47
  const el = article.get(0);
48
+
49
+ if (module.hot && window.__deck_roots__[el.id]) {
50
+ this.unmountRoot(el.id);
51
+ }
52
+
44
53
  const root = createRoot(el);
45
54
 
55
+ if (module.hot) {
56
+ window.__deck_roots__[el.id] = root;
57
+ }
58
+
46
59
  const RootApp = this.rootApp(Slide);
47
60
 
48
61
  function App() {
@@ -52,10 +65,17 @@ export class App extends AppBase {
52
65
  useEffect(() => {
53
66
  function slideClosed() {
54
67
  root.unmount();
68
+ if (module.hot) {
69
+ delete window.__deck_roots__[el.id];
70
+ }
55
71
  }
56
72
 
57
73
  article.on("slide:closed", slideClosed);
58
- });
74
+
75
+ return () => {
76
+ article.off("slide:closed", slideClosed);
77
+ };
78
+ }, []);
59
79
 
60
80
  return (
61
81
  <SlideContext.Provider value={slideState}>
@@ -70,6 +90,25 @@ export class App extends AppBase {
70
90
 
71
91
  root.render(<App />);
72
92
  }
93
+
94
+ unmountRoot(key) {
95
+ if (!window.__deck_roots__[key]) {
96
+ return;
97
+ }
98
+ window.__deck_roots__[key].unmount();
99
+ delete window.__deck_roots__[key];
100
+ }
101
+
102
+ refresh() {
103
+ const keys = this.getActiveSlideKeys();
104
+ for (const key of keys) {
105
+ if (window.__deck_roots__?.[key]) {
106
+ this.unmountRoot(key);
107
+ }
108
+
109
+ this.renderSlide(key);
110
+ }
111
+ }
73
112
  }
74
113
 
75
114
  export * from "./lib/hooks";
@@ -4,108 +4,119 @@ import React, { useContext, useEffect, useRef, useState } from "react";
4
4
  import { SlideContext, SubslideContext } from "../contexts.js";
5
5
 
6
6
  const DEFAULT_TRANSITION_STATE = {
7
- entering: false,
8
- entered: false,
9
- exiting: false,
10
- exited: false,
7
+ entering: false,
8
+ entered: false,
9
+ exiting: false,
10
+ exited: false,
11
11
  };
12
12
 
13
13
  export function Subslide(props) {
14
- const {
15
- id,
16
- setSubslide,
17
- endAnimation,
18
- className,
19
- style,
20
- index,
21
- active,
22
- children,
23
- animateSpeed,
24
- } = props;
25
- const { isSlideReady } = useContext(SlideContext);
26
- const [transitions, setTransitions] = useState({
27
- ...DEFAULT_TRANSITION_STATE,
28
- entered: active,
29
- });
30
-
31
- // Poor mans classnames. Let's keep dependencies small.
32
- const classes = ["subslide"];
33
-
34
- if (typeof className === "string") {
35
- classes.push(className);
36
- }
37
-
38
- if (active) {
39
- classes.push("currentpage");
40
- }
41
-
42
- const subslide = useRef(null);
43
-
44
- function animateIn() {
45
- setSubslide(index);
46
- setTransitions({
47
- ...DEFAULT_TRANSITION_STATE,
48
- entering: true,
49
- });
50
-
51
- setTimeout(() => {
52
- subslide.current.ready = true;
53
- subslide.current.animating(false);
54
- setTransitions({
55
- ...DEFAULT_TRANSITION_STATE,
56
- entered: true,
57
- });
58
- endAnimation();
59
- }, animateSpeed);
60
- return subslide.current;
61
- }
62
-
63
- function animateOut() {
64
- setTransitions({
65
- ...DEFAULT_TRANSITION_STATE,
66
- exiting: true,
67
- });
68
- setTimeout(() => {
69
- subslide.current.ready = true;
70
- subslide.current.animating(false);
71
- setTransitions({
72
- ...DEFAULT_TRANSITION_STATE,
73
- exited: true,
74
- });
75
- endAnimation();
76
- }, animateSpeed);
77
- return subslide.current;
78
- }
79
-
80
- useEffect(() => {
81
- if (isSlideReady) {
82
- const bridgeSub = Bridge.Sub.get(`subslide-${index}`);
83
-
84
- subslide.current = bridgeSub;
85
-
86
- let transitions = {
87
- in: animateIn.bind(this),
88
- out: animateOut.bind(this),
89
- };
90
-
91
- // The hack
92
- subslide.current.transitions(transitions);
93
-
94
- subslide.current.ready = true;
95
- subslide.current.animating(false);
96
- }
97
- }, [isSlideReady]);
98
-
99
- return (
100
- <SubslideContext.Provider
101
- value={{
102
- isActive: active,
103
- transitions,
104
- }}
105
- >
106
- <div id={id} style={{ flex: 1, position: "relative", ...style || {} }} className={classes.join(" ")}>
107
- {children}
108
- </div>
109
- </SubslideContext.Provider>
110
- );
14
+ const {
15
+ id,
16
+ setSubslide,
17
+ endAnimation,
18
+ className,
19
+ style,
20
+ index,
21
+ active,
22
+ children,
23
+ animateSpeed,
24
+ } = props;
25
+ const { isSlideReady, registerSubslide, unregisterSubslide } =
26
+ useContext(SlideContext);
27
+ const [transitions, setTransitions] = useState({
28
+ ...DEFAULT_TRANSITION_STATE,
29
+ entered: active,
30
+ });
31
+
32
+ // Poor mans classnames. Let's keep dependencies small.
33
+ const classes = ["subslide"];
34
+
35
+ if (typeof className === "string") {
36
+ classes.push(className);
37
+ }
38
+
39
+ if (active) {
40
+ classes.push("currentpage");
41
+ }
42
+
43
+ const subslide = useRef(null);
44
+
45
+ function animateIn() {
46
+ setSubslide(index);
47
+ setTransitions({
48
+ ...DEFAULT_TRANSITION_STATE,
49
+ entering: true,
50
+ });
51
+
52
+ setTimeout(() => {
53
+ subslide.current.ready = true;
54
+ subslide.current.animating(false);
55
+ setTransitions({
56
+ ...DEFAULT_TRANSITION_STATE,
57
+ entered: true,
58
+ });
59
+ endAnimation();
60
+ }, animateSpeed);
61
+ return subslide.current;
62
+ }
63
+
64
+ function animateOut() {
65
+ setTransitions({
66
+ ...DEFAULT_TRANSITION_STATE,
67
+ exiting: true,
68
+ });
69
+ setTimeout(() => {
70
+ subslide.current.ready = true;
71
+ subslide.current.animating(false);
72
+ setTransitions({
73
+ ...DEFAULT_TRANSITION_STATE,
74
+ exited: true,
75
+ });
76
+ endAnimation();
77
+ }, animateSpeed);
78
+ return subslide.current;
79
+ }
80
+
81
+ useEffect(() => {
82
+ if (isSlideReady) {
83
+ const bridgeSub = Bridge.Sub.get(`subslide-${index}`);
84
+
85
+ subslide.current = bridgeSub;
86
+
87
+ let transitions = {
88
+ in: animateIn.bind(this),
89
+ out: animateOut.bind(this),
90
+ };
91
+
92
+ // The hack
93
+ subslide.current.transitions(transitions);
94
+
95
+ subslide.current.ready = true;
96
+ subslide.current.animating(false);
97
+ }
98
+ }, [isSlideReady]);
99
+
100
+ // Increase and decrease total count of subslides
101
+ useEffect(() => {
102
+ registerSubslide();
103
+ return () => unregisterSubslide();
104
+ }, []);
105
+
106
+ return (
107
+ <SubslideContext.Provider
108
+ value={{
109
+ isActive: active,
110
+ transitions,
111
+ }}
112
+ >
113
+ <div
114
+ id={id}
115
+ style={{ flex: 1, position: "relative", ...(style || {}) }}
116
+ className={classes.join(" ")}
117
+ >
118
+ {children}
119
+ </div>
120
+ </SubslideContext.Provider>
121
+ );
111
122
  }
@@ -1,71 +1,66 @@
1
1
  /* eslint-disable react/jsx-no-constructed-context-values */
2
2
  // TODO: Remove above
3
- import React, { useState } from "react";
3
+ import React, { useContext } from "react";
4
4
  import { ScrollableArea, Subslide } from "./index.js";
5
- import { useAsyncReference, useModes } from "../hooks";
5
+ import { SlideContext, SubslidesContext } from "../contexts.js";
6
6
 
7
- import { SubslidesContext } from "../contexts.js";
7
+ import { useModes } from "../hooks";
8
8
 
9
9
  export function Subslides({ children, animateSpeed }) {
10
- const [currentSubslide, setCurrentSubslide] = useAsyncReference(1);
11
- const [animating, setAnimating] = useState({
12
- up: false,
13
- down: false,
14
- });
15
- const { isScreenshot } = useModes();
10
+ const {
11
+ subslideAnimating: animating,
12
+ setSubslideAnimating: setAnimating,
13
+ currentSubslide,
14
+ setCurrentSubslide,
15
+ } = useContext(SlideContext);
16
+ const { isScreenshot } = useModes();
16
17
 
17
- let totalSubslides = 0;
18
+ function mapSubslide(child, index) {
19
+ return React.cloneElement(child, {
20
+ id: `subslide-${index + 1}`,
21
+ style: { height: "100%" },
22
+ setSubslide: (index) => {
23
+ setAnimating({
24
+ down: index > currentSubslide,
25
+ up: index < currentSubslide,
26
+ });
27
+ setCurrentSubslide(index);
28
+ },
29
+ endAnimation: () => {
30
+ setAnimating({ down: false, up: false });
31
+ },
32
+ animateSpeed: isScreenshot ? 0 : animateSpeed,
33
+ index: index + 1,
34
+ active: index + 1 === currentSubslide,
35
+ key: index,
36
+ });
37
+ }
18
38
 
19
- function mapSubslide(child, index) {
20
- totalSubslides++;
21
- return React.cloneElement(child, {
22
- id: `subslide-${index + 1}`,
23
- style: { height: "100%" },
24
- setSubslide: (index) => {
25
- setAnimating({
26
- down: index > currentSubslide.current,
27
- up: index < currentSubslide.current,
28
- });
29
- setCurrentSubslide(index);
30
- },
31
- endAnimation: () => {
32
- setAnimating({ down: false, up: false });
33
- },
34
- animateSpeed: isScreenshot ? 0 : animateSpeed,
35
- index: index + 1,
36
- active: index + 1 === currentSubslide.current,
37
- key: index,
38
- });
39
- }
39
+ const newChildren = React.Children.map(children, (child, index) => {
40
+ if (child.type === Subslide) {
41
+ return mapSubslide(child, index);
42
+ }
40
43
 
41
- const newChildren = React.Children.map(children, (child, index) => {
42
- if (child.type === Subslide) {
43
- return mapSubslide(child, index);
44
- }
44
+ if (child.type === ScrollableArea) {
45
+ return React.cloneElement(child, {
46
+ children: React.Children.map(child.props.children, mapSubslide),
47
+ });
48
+ }
45
49
 
46
- if (child.type === ScrollableArea) {
47
- return React.cloneElement(child, {
48
- children: React.Children.map(child.props.children, mapSubslide),
49
- });
50
- }
50
+ return child;
51
+ });
51
52
 
52
- return child;
53
- });
54
-
55
- return (
56
- <SubslidesContext.Provider
57
- value={{
58
- animating,
59
- currentSubslideIndex: currentSubslide.current,
60
- totalSubslides: totalSubslides,
61
- }}
62
- >
63
- {newChildren}
64
- </SubslidesContext.Provider>
65
- );
53
+ return (
54
+ <SubslidesContext.Provider
55
+ value={{
56
+ animating,
57
+ }}
58
+ >
59
+ {newChildren}
60
+ </SubslidesContext.Provider>
61
+ );
66
62
  }
67
63
 
68
64
  Subslides.defaultProps = {
69
- animateSpeed: 500,
65
+ animateSpeed: 500,
70
66
  };
71
-
@@ -1,9 +1,11 @@
1
+ export * from "./use-slide-ready.js";
1
2
  export * from "./use-shared-state.js";
2
3
  export * from "./use-async-reference.js";
3
4
  export * from "./use-modes.js";
4
- export * from "./use-context.js";
5
+ export * from "./use-slide-context.js";
5
6
  export * from "./use-companywide.js";
6
7
  export * from "./use-slide.js";
7
8
  export * from "./use-transitions.js";
8
9
  export * from "./use-subslides.js";
9
10
  export * from "./use-prep-editable.js";
11
+ export * from "./use-slide-done.js";
@@ -1,5 +1,5 @@
1
1
  import { useAsyncReference, useModes } from "./index.js";
2
- import { useEffect, useState } from "react";
2
+ import { useEffect, useRef, useState } from "react";
3
3
 
4
4
  import ulog from "ulog";
5
5
 
@@ -26,7 +26,16 @@ export function useRootSlide(article) {
26
26
  const isCurrent = article.closest(".presoSlide").hasClass("current");
27
27
  const [synced, setSynced] = useState(!isRemote);
28
28
  const [internalSlideState, setInternalSlideState] = useAsyncReference({});
29
+ const [totalSubslides, setTotalSubslides] = useAsyncReference(0);
30
+ const [currentSubslide, setCurrentSubslide] = useAsyncReference(
31
+ totalSubslides ? 1 : null,
32
+ );
33
+ const [subslideAnimating, setSubslideAnimating] = useAsyncReference({
34
+ up: false,
35
+ down: false,
36
+ });
29
37
  const [slideReady, setSlideReady] = useState(false);
38
+ const doneRegister = useRef({ promises: [] });
30
39
 
31
40
  const [transitions, setTransitions] = useState({
32
41
  ...DEFAULT_TRANSITION_STATE,
@@ -105,11 +114,19 @@ export function useRootSlide(article) {
105
114
  const slideExiting = updateState("exiting");
106
115
  const slideExited = updateState("exited");
107
116
 
117
+ article.off();
108
118
  article.on("slide:entering", slideEntering);
109
119
  article.on("slide:entered", slideEntered);
110
120
  article.on("slide:exiting", slideExiting);
111
121
  article.on("slide:exited", slideExited);
112
- article.on("slideready", (e) => {
122
+ article.on("slide:closed", () => {
123
+ doneRegister.current.promises = [];
124
+ });
125
+ article.on("slideready", (e, done) => {
126
+ Promise.all(doneRegister.current.promises).then(() => {
127
+ done();
128
+ });
129
+
113
130
  setSlideReady(true);
114
131
  slideEntered(e);
115
132
  });
@@ -124,8 +141,18 @@ export function useRootSlide(article) {
124
141
  transitions,
125
142
  slideKey: key,
126
143
  isCurrentSlide: isCurrent,
144
+ doneRegister,
127
145
  rootElement: article.get(0),
128
146
 
147
+ registerSubslide: () => setTotalSubslides(totalSubslides.current + 1),
148
+ unregisterSubslide: () => setTotalSubslides(totalSubslides.current - 1),
149
+
150
+ subslideAnimating: subslideAnimating.current,
151
+ setSubslideAnimating,
152
+ totalSubslides: totalSubslides.current,
153
+ currentSubslide: currentSubslide.current,
154
+ setCurrentSubslide,
155
+
129
156
  // For use by shared state
130
157
  internalSlideState,
131
158
  setInternalSlideState,
@@ -0,0 +1,62 @@
1
+ import isPlainObject from "lodash.isplainobject";
2
+ import { useEffect } from "react";
3
+ import { useSharedState } from "./index.js";
4
+
5
+ function getValueFromContext(context, path, defaultValue) {
6
+ if (path) {
7
+ return Bridge.Context.get(path, defaultValue);
8
+ }
9
+
10
+ return context;
11
+ }
12
+
13
+ export function useSlideContext(contextPath = null, defaultValue = null) {
14
+ let persist = false;
15
+ let path = contextPath;
16
+
17
+ const value = getValueFromContext(
18
+ window.Bridge.Context.getDict(),
19
+ path,
20
+ defaultValue
21
+ );
22
+ const [context, setContextState] = useSharedState(value);
23
+
24
+ // You could pass in an object, so that you can set whether
25
+ // the saves are persistent or not.
26
+ if (isPlainObject(contextPath)) {
27
+ path = contextPath.path || null;
28
+ persist = contextPath.save || false;
29
+ }
30
+
31
+ function setContext(key, data) {
32
+ let setPath = key;
33
+ let setData = data;
34
+
35
+ if (path) {
36
+ if (data) {
37
+ setPath = `${path}.${key}`;
38
+ } else {
39
+ setPath = path;
40
+ setData = key;
41
+ }
42
+ }
43
+
44
+ Bridge.Context.set(setPath, setData, persist);
45
+
46
+ const value = getValueFromContext(
47
+ Bridge.Context.getDict(),
48
+ path,
49
+ defaultValue
50
+ );
51
+ setContextState(value);
52
+ }
53
+
54
+ useEffect(() => {
55
+ if (context !== value) {
56
+ Bridge.Context.set(path, context, persist);
57
+ }
58
+ }, [context]);
59
+
60
+ return [context, setContext];
61
+ }
62
+
@@ -0,0 +1,27 @@
1
+ import { useEffect, useRef, useCallback } from "react";
2
+ import { useSlide } from "./use-slide";
3
+
4
+ export function useSlideDone() {
5
+ const { doneRegister } = useSlide();
6
+ const doneFn = useRef(null);
7
+
8
+ const callback = useCallback(() => {
9
+ if (!doneFn.current) {
10
+ console.warn(
11
+ "Attempted to call useSlideDone() callback before component mounted.",
12
+ );
13
+ return;
14
+ }
15
+ doneFn.current();
16
+ }, []);
17
+
18
+ useEffect(() => {
19
+ doneRegister.current.promises.push(
20
+ new Promise((resolve) => {
21
+ doneFn.current = resolve;
22
+ }),
23
+ );
24
+ }, []);
25
+
26
+ return callback;
27
+ }
@@ -0,0 +1,12 @@
1
+ import { useEffect } from "react";
2
+ import { useSlide } from "./use-slide";
3
+
4
+ export function useSlideReady(fn) {
5
+ const { isSlideReady } = useSlide();
6
+
7
+ useEffect(() => {
8
+ if (isSlideReady) {
9
+ fn();
10
+ }
11
+ }, [isSlideReady]);
12
+ }
@@ -2,5 +2,15 @@ import { SlideContext } from "../contexts.js";
2
2
  import { useContext } from "react";
3
3
 
4
4
  export function useSlide() {
5
- return useContext(SlideContext);
5
+ const {
6
+ slideKey,
7
+ isSlideReady,
8
+ doneRegister,
9
+ isCurrentSlide,
10
+ totalSubslides,
11
+ currentSubslide,
12
+ transitions
13
+ } = useContext(SlideContext);
14
+
15
+ return { slideKey, isSlideReady, doneRegister, isCurrentSlide, currentSubslide, totalSubslides, transitions };
6
16
  }
@@ -1,30 +1,51 @@
1
- import { SubslidesContext } from "../contexts.js";
1
+ import { SlideContext, SubslideContext } from "../contexts.js";
2
+
2
3
  import { useContext } from "react";
4
+ import { useSlide } from "./use-slide";
3
5
 
4
6
  export function useSubslides() {
5
- const context = useContext(SubslidesContext);
6
- const index = context.currentSubslideIndex;
7
+ const context = useContext(SubslideContext);
8
+ const { subslideAnimating: animating } = useContext(SlideContext);
9
+ const { currentSubslide: index, totalSubslides } = useSlide();
7
10
 
8
- const atTop = index === 1;
9
- const atBottom = index === context.totalSubslides;
10
- return {
11
- ...context,
12
- atTop,
13
- atBottom,
14
- navigateUp() {
15
- if (atTop) {
16
- return;
17
- }
11
+ const atTop = index === 1;
12
+ const atBottom = index === totalSubslides;
13
+ return {
14
+ ...context,
15
+ animating,
16
+ atTop,
17
+ atBottom,
18
+ totalSubslides,
19
+ currentSubslideIndex: index,
20
+ navigateTo(newIndex) {
21
+ if (newIndex === index) {
22
+ // It's the same index, no need to change
23
+ return;
24
+ }
18
25
 
19
- Bridge.Sub.show(`subslide-${index - 1}`);
20
- },
21
- navigateDown() {
22
- if (atBottom) {
23
- return;
24
- }
26
+ if (newIndex < 1 || newIndex > totalSubslides) {
27
+ /* eslint-disable-next-line no-console */
28
+ console.warn(
29
+ `Cannot navigate to subslide ${newIndex} as it does not exist.`,
30
+ );
31
+ return;
32
+ }
25
33
 
26
- Bridge.Sub.show(`subslide-${index + 1}`);
27
- }
28
- };
29
- }
34
+ window.Bridge.Sub.show(`subslide-${newIndex}`);
35
+ },
36
+ navigateUp() {
37
+ if (atTop) {
38
+ return;
39
+ }
30
40
 
41
+ window.Bridge.Sub.show(`subslide-${index - 1}`);
42
+ },
43
+ navigateDown() {
44
+ if (atBottom) {
45
+ return;
46
+ }
47
+
48
+ window.Bridge.Sub.show(`subslide-${index + 1}`);
49
+ },
50
+ };
51
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@livepreso/content-react",
3
- "version": "0.3.4",
3
+ "version": "0.3.6",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "publishConfig": {
@@ -17,7 +17,7 @@
17
17
  "dependencies": {
18
18
  "react": "~18.2.0",
19
19
  "react-dom": "~18.2.0",
20
- "@livepreso/content-base": "~1.1.2",
20
+ "@livepreso/content-base": "~1.1.3",
21
21
  "ulog": "~2.0.0-beta.18",
22
22
  "lodash.get": "~4.4.2",
23
23
  "lodash.isplainobject": "~4.0.6",
@@ -1,61 +0,0 @@
1
- import { useEffect, useState } from "react";
2
-
3
- import isPlainObject from "lodash.isplainobject";
4
-
5
- function getValueFromContext(context, path, defaultValue) {
6
- if (path) {
7
- return Bridge.Context.get(path, defaultValue);
8
- }
9
-
10
- return context;
11
- }
12
-
13
- export function useContext(contextPath = null, defaultValue = null) {
14
- let persist = false;
15
- let path = contextPath;
16
-
17
- const value = getValueFromContext(
18
- window.Bridge.Context.getDict(),
19
- path,
20
- defaultValue,
21
- );
22
- const [context, setContextState] = useState(value);
23
-
24
- // You could pass in an object, so that you can set whether
25
- // the saves are persistent or not.
26
- if (isPlainObject(contextPath)) {
27
- path = contextPath.path || null;
28
- persist = contextPath.save || false;
29
- }
30
-
31
- function setContext(key, data) {
32
- let setPath = key;
33
- let setData = data;
34
-
35
- if (path) {
36
- if (data) {
37
- setPath = `${path}.${key}`;
38
- } else {
39
- setPath = path;
40
- setData = key;
41
- }
42
- }
43
-
44
- Bridge.Context.set(setPath, setData, persist);
45
-
46
- const value = getValueFromContext(
47
- Bridge.Context.getDict(),
48
- path,
49
- defaultValue,
50
- );
51
- setContextState(value);
52
- }
53
-
54
- useEffect(() => {
55
- if (context !== value) {
56
- Bridge.Context.set(path, context, persist);
57
- }
58
- }, [context]);
59
-
60
- return [context, setContext];
61
- }