@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.
- package/.rush/temp/shrinkwrap-deps.json +1 -1
- package/CHANGELOG.json +29 -0
- package/CHANGELOG.md +15 -1
- package/index.js +41 -2
- package/lib/components/Subslide.js +112 -101
- package/lib/components/Subslides.js +51 -56
- package/lib/hooks/index.js +3 -1
- package/lib/hooks/use-root-slide.js +29 -2
- package/lib/hooks/use-slide-context.js +62 -0
- package/lib/hooks/use-slide-done.js +27 -0
- package/lib/hooks/use-slide-ready.js +12 -0
- package/lib/hooks/use-slide.js +11 -1
- package/lib/hooks/use-subslides.js +44 -23
- package/package.json +2 -2
- package/lib/hooks/use-context.js +0 -61
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"../../content/content-react": "../../content/content-react:
|
|
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
|
|
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
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
entering: false,
|
|
8
|
+
entered: false,
|
|
9
|
+
exiting: false,
|
|
10
|
+
exited: false,
|
|
11
11
|
};
|
|
12
12
|
|
|
13
13
|
export function Subslide(props) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
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, {
|
|
3
|
+
import React, { useContext } from "react";
|
|
4
4
|
import { ScrollableArea, Subslide } from "./index.js";
|
|
5
|
-
import {
|
|
5
|
+
import { SlideContext, SubslidesContext } from "../contexts.js";
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import { useModes } from "../hooks";
|
|
8
8
|
|
|
9
9
|
export function Subslides({ children, animateSpeed }) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
const {
|
|
11
|
+
subslideAnimating: animating,
|
|
12
|
+
setSubslideAnimating: setAnimating,
|
|
13
|
+
currentSubslide,
|
|
14
|
+
setCurrentSubslide,
|
|
15
|
+
} = useContext(SlideContext);
|
|
16
|
+
const { isScreenshot } = useModes();
|
|
16
17
|
|
|
17
|
-
|
|
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
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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
|
-
|
|
47
|
-
|
|
48
|
-
children: React.Children.map(child.props.children, mapSubslide),
|
|
49
|
-
});
|
|
50
|
-
}
|
|
50
|
+
return child;
|
|
51
|
+
});
|
|
51
52
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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
|
-
|
|
65
|
+
animateSpeed: 500,
|
|
70
66
|
};
|
|
71
|
-
|
package/lib/hooks/index.js
CHANGED
|
@@ -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("
|
|
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
|
+
}
|
package/lib/hooks/use-slide.js
CHANGED
|
@@ -2,5 +2,15 @@ import { SlideContext } from "../contexts.js";
|
|
|
2
2
|
import { useContext } from "react";
|
|
3
3
|
|
|
4
4
|
export function useSlide() {
|
|
5
|
-
|
|
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 {
|
|
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
|
-
|
|
6
|
-
|
|
7
|
+
const context = useContext(SubslideContext);
|
|
8
|
+
const { subslideAnimating: animating } = useContext(SlideContext);
|
|
9
|
+
const { currentSubslide: index, totalSubslides } = useSlide();
|
|
7
10
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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",
|
package/lib/hooks/use-context.js
DELETED
|
@@ -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
|
-
}
|