@livepreso/content-react 0.3.5 → 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,18 @@
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
+ },
4
16
  {
5
17
  "version": "0.3.5",
6
18
  "tag": "@livepreso/content-react_v0.3.5",
package/CHANGELOG.md CHANGED
@@ -1,6 +1,13 @@
1
1
  # Change Log - @livepreso/content-react
2
2
 
3
- This log was last generated on Sun, 03 Mar 2024 23:59:09 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
4
11
 
5
12
  ## 0.3.5
6
13
  Sun, 03 Mar 2024 23:59:09 GMT
@@ -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
-
@@ -26,6 +26,14 @@ 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);
30
38
  const doneRegister = useRef({ promises: [] });
31
39
 
@@ -115,9 +123,7 @@ export function useRootSlide(article) {
115
123
  doneRegister.current.promises = [];
116
124
  });
117
125
  article.on("slideready", (e, done) => {
118
- Promise.all(
119
- doneRegister.current.promises
120
- ).then(() => {
126
+ Promise.all(doneRegister.current.promises).then(() => {
121
127
  done();
122
128
  });
123
129
 
@@ -138,6 +144,15 @@ export function useRootSlide(article) {
138
144
  doneRegister,
139
145
  rootElement: article.get(0),
140
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
+
141
156
  // For use by shared state
142
157
  internalSlideState,
143
158
  setInternalSlideState,
@@ -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.5",
3
+ "version": "0.3.6",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "publishConfig": {