@applicaster/zapp-react-native-ui-components 16.0.0-alpha.9235607812 → 16.0.0-alpha.9338540010
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/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +12 -3
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/ActionButton.tsx +1 -1
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/PressableView.test.tsx +4 -2
- package/Components/MasterCell/SharedUI/CollapsibleTextContainer/__tests__/factory.test.ts +2 -2
- package/Components/MasterCell/SharedUI/CollapsibleTextContainer/index.ts +2 -1
- package/Components/MasterCell/__tests__/masterCell.test.js +60 -0
- package/Components/MasterCell/index.tsx +28 -4
- package/Components/MasterCell/utils/__tests__/withoutFocusedState.test.js +20 -0
- package/Components/MasterCell/utils/index.ts +18 -0
- package/Components/ModalComponent/AudioPlayer/Components/Item.tsx +22 -1
- package/Components/ModalComponent/AudioPlayer/Components/__tests__/Item.test.tsx +52 -1
- package/Components/ModalComponent/AudioPlayer/utils/__tests__/mergeStyles.test.ts +77 -0
- package/Components/ModalComponent/AudioPlayer/utils/mergeStyles.ts +58 -16
- package/Components/ModalComponent/BottomSheetModalContent.tsx +9 -74
- package/Components/ModalComponent/__tests__/showTextInput.test.ts +25 -0
- package/Components/ModalComponent/showTextInput.ts +2 -0
- package/Components/River/ComponentsMap/ComponentsMap.tsx +4 -1
- package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +2 -0
- package/Components/Transitioner/AnimationManager.js +1 -1
- package/Components/Transitioner/Scene.tsx +4 -3
- package/Components/Transitioner/Transitioner.tsx +69 -30
- package/Components/Transitioner/__tests__/transitioner.test.js +308 -20
- package/Components/VideoModal/PlayerWrapper.tsx +4 -1
- package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +1 -0
- package/Components/VideoModal/__tests__/playerWrapperStyle.test.ts +58 -0
- package/Components/VideoModal/__tests__/playerWrapperUtils.test.ts +16 -0
- package/Components/VideoModal/playerWrapperStyle.ts +21 -3
- package/Components/VideoModal/playerWrapperUtils.ts +7 -1
- package/Decorators/ZappPipesDataConnector/__tests__/screenToolbox.test.ts +347 -0
- package/Decorators/ZappPipesDataConnector/__tests__/screenToolboxUnavailable.test.ts +53 -0
- package/Decorators/ZappPipesDataConnector/index.tsx +19 -4
- package/Decorators/ZappPipesDataConnector/screenToolbox.ts +384 -0
- package/package.json +5 -5
|
@@ -90,6 +90,7 @@ type ModalComponentProps = {
|
|
|
90
90
|
/** Optional body that replaces the items list (header stays DefaultModalHeader). */
|
|
91
91
|
contentComponent?: React.ComponentType<any>;
|
|
92
92
|
contentComponentProps?: Record<string, any>;
|
|
93
|
+
themePluginId?: string;
|
|
93
94
|
styleOverrides?: ModalBlocksConfig | Record<string, any>;
|
|
94
95
|
measurementPhase?: boolean;
|
|
95
96
|
/** Copy under Next Up when the queue has no upcoming items. */
|
|
@@ -115,7 +116,7 @@ function _BottomSheetModalContent(props: ModalComponentProps) {
|
|
|
115
116
|
iconPlacement,
|
|
116
117
|
contentComponent: ContentComponent,
|
|
117
118
|
contentComponentProps = {},
|
|
118
|
-
|
|
119
|
+
themePluginId: themePluginIdProp,
|
|
119
120
|
measurementPhase = false,
|
|
120
121
|
emptyMessage,
|
|
121
122
|
} = props;
|
|
@@ -140,12 +141,14 @@ function _BottomSheetModalContent(props: ModalComponentProps) {
|
|
|
140
141
|
role,
|
|
141
142
|
behavior,
|
|
142
143
|
editableCollection,
|
|
143
|
-
themePluginId,
|
|
144
|
+
themePluginId: themePluginIdFromSheet,
|
|
144
145
|
} = useBottomSheetContent({
|
|
145
146
|
onPress,
|
|
146
147
|
viewModel,
|
|
147
148
|
});
|
|
148
149
|
|
|
150
|
+
const themePluginId = themePluginIdFromSheet || themePluginIdProp;
|
|
151
|
+
|
|
149
152
|
const plugins = usePlugins();
|
|
150
153
|
|
|
151
154
|
const plugin = useMemo(
|
|
@@ -157,78 +160,10 @@ function _BottomSheetModalContent(props: ModalComponentProps) {
|
|
|
157
160
|
const configuration =
|
|
158
161
|
plugin?.configuration || (plugin as any)?.configuration_json;
|
|
159
162
|
|
|
160
|
-
|
|
161
|
-
configuration
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
if (!propStyleOverrides) {
|
|
166
|
-
return parsed;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// hydrate(QueueStyles) only emits sectionHeader after the plugin class
|
|
170
|
-
// includes it. Until then, Studio/local keys in configuration_json still
|
|
171
|
-
// apply via the parser.
|
|
172
|
-
const hydratedSection = propStyleOverrides.sectionHeader;
|
|
173
|
-
|
|
174
|
-
const hasTitleStyle = (style?: Record<string, any>) =>
|
|
175
|
-
Boolean(
|
|
176
|
-
style &&
|
|
177
|
-
(style.fontColor ||
|
|
178
|
-
style.fontSize !== undefined ||
|
|
179
|
-
style.lineHeight !== undefined ||
|
|
180
|
-
style.fontFamily ||
|
|
181
|
-
style.iosFontFamily ||
|
|
182
|
-
style.androidFontFamily ||
|
|
183
|
-
style.letterSpacing !== undefined ||
|
|
184
|
-
style.iosLetterSpacing !== undefined ||
|
|
185
|
-
style.androidLetterSpacing !== undefined ||
|
|
186
|
-
style.textTransform ||
|
|
187
|
-
style.alignment)
|
|
188
|
-
);
|
|
189
|
-
|
|
190
|
-
const hasActionStyle = (style?: Record<string, any>) =>
|
|
191
|
-
Boolean(
|
|
192
|
-
style &&
|
|
193
|
-
(style.backgroundColor ||
|
|
194
|
-
style.fontColor ||
|
|
195
|
-
style.fontSize !== undefined ||
|
|
196
|
-
style.lineHeight !== undefined ||
|
|
197
|
-
style.fontFamily ||
|
|
198
|
-
style.iosFontFamily ||
|
|
199
|
-
style.androidFontFamily ||
|
|
200
|
-
style.letterSpacing !== undefined ||
|
|
201
|
-
style.iosLetterSpacing !== undefined ||
|
|
202
|
-
style.androidLetterSpacing !== undefined ||
|
|
203
|
-
style.textTransform ||
|
|
204
|
-
style.borderRadius !== undefined ||
|
|
205
|
-
style.cornerRadius !== undefined ||
|
|
206
|
-
style.paddingTop !== undefined ||
|
|
207
|
-
style.paddingRight !== undefined ||
|
|
208
|
-
style.paddingBottom !== undefined ||
|
|
209
|
-
style.paddingLeft !== undefined)
|
|
210
|
-
);
|
|
211
|
-
|
|
212
|
-
const actionNode = hydratedSection?.actionButtons;
|
|
213
|
-
|
|
214
|
-
// An empty `default: {}` is truthy and would hide fields set on the flat
|
|
215
|
-
// object or on the focused bucket.
|
|
216
|
-
const hasHydratedSection =
|
|
217
|
-
hasTitleStyle(hydratedSection?.title?.default) ||
|
|
218
|
-
hasTitleStyle(hydratedSection?.title) ||
|
|
219
|
-
hasActionStyle(actionNode?.default) ||
|
|
220
|
-
hasActionStyle(actionNode?.focused) ||
|
|
221
|
-
hasActionStyle(actionNode?.focus) ||
|
|
222
|
-
hasActionStyle(actionNode);
|
|
223
|
-
|
|
224
|
-
return {
|
|
225
|
-
...parsed,
|
|
226
|
-
...propStyleOverrides,
|
|
227
|
-
sectionHeader: hasHydratedSection
|
|
228
|
-
? hydratedSection
|
|
229
|
-
: parsed?.sectionHeader,
|
|
230
|
-
};
|
|
231
|
-
}, [propStyleOverrides, plugin, themePluginId]);
|
|
163
|
+
return configuration && themePluginId
|
|
164
|
+
? parseModalBlocksConfiguration(configuration, themePluginId)
|
|
165
|
+
: null;
|
|
166
|
+
}, [plugin, themePluginId]);
|
|
232
167
|
|
|
233
168
|
const pluginLocalizations = useLocalizedStrings({
|
|
234
169
|
localizations:
|
|
@@ -92,4 +92,29 @@ describe("showTextInputAction", () => {
|
|
|
92
92
|
expect(result).toBe(ActionResult.Error);
|
|
93
93
|
expect(actionExecutor.handleAction).not.toHaveBeenCalled();
|
|
94
94
|
});
|
|
95
|
+
|
|
96
|
+
it("forwards themePluginId so the sheet can read plugin button styles", async () => {
|
|
97
|
+
const action = {
|
|
98
|
+
type: "showTextInput",
|
|
99
|
+
options: {
|
|
100
|
+
headerTitle: "Create New Playlist",
|
|
101
|
+
inputLabel: "Name your playlist",
|
|
102
|
+
buttonLabel: "Create",
|
|
103
|
+
themePluginId: "playlist-experience",
|
|
104
|
+
actions: [{ type: "sendCloudEvent", options: {} }],
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
await showTextInputAction(action as any);
|
|
109
|
+
|
|
110
|
+
expect(actionExecutor.handleAction).toHaveBeenCalledWith(
|
|
111
|
+
expect.objectContaining({
|
|
112
|
+
type: "openBottomSheet",
|
|
113
|
+
options: expect.objectContaining({
|
|
114
|
+
themePluginId: "playlist-experience",
|
|
115
|
+
}),
|
|
116
|
+
}),
|
|
117
|
+
undefined
|
|
118
|
+
);
|
|
119
|
+
});
|
|
95
120
|
});
|
|
@@ -21,6 +21,7 @@ export async function showTextInputAction(
|
|
|
21
21
|
validationLabel,
|
|
22
22
|
actions,
|
|
23
23
|
maxLength,
|
|
24
|
+
themePluginId,
|
|
24
25
|
} = action.options || {};
|
|
25
26
|
|
|
26
27
|
if (!headerTitle || !buttonLabel || !actions || !actions.length) {
|
|
@@ -34,6 +35,7 @@ export async function showTextInputAction(
|
|
|
34
35
|
header: {
|
|
35
36
|
title: headerTitle,
|
|
36
37
|
},
|
|
38
|
+
...(themePluginId ? { themePluginId } : {}),
|
|
37
39
|
content: {
|
|
38
40
|
component: TextInputContent,
|
|
39
41
|
props: {
|
|
@@ -118,7 +118,10 @@ function ComponentsMapComponent(props: Props) {
|
|
|
118
118
|
};
|
|
119
119
|
|
|
120
120
|
return (
|
|
121
|
-
<ScreenLoadingMeasurementsListItemWrapper
|
|
121
|
+
<ScreenLoadingMeasurementsListItemWrapper
|
|
122
|
+
index={index}
|
|
123
|
+
testID={`component-${item.id}`}
|
|
124
|
+
>
|
|
122
125
|
<RiverItem {...riverItemProps} />
|
|
123
126
|
</ScreenLoadingMeasurementsListItemWrapper>
|
|
124
127
|
);
|
|
@@ -213,6 +213,7 @@ exports[`componentsMap renders renders components map correctly 1`] = `
|
|
|
213
213
|
<View
|
|
214
214
|
onLayout={[Function]}
|
|
215
215
|
style={{}}
|
|
216
|
+
testID="component-A1"
|
|
216
217
|
>
|
|
217
218
|
<View />
|
|
218
219
|
</View>
|
|
@@ -225,6 +226,7 @@ exports[`componentsMap renders renders components map correctly 1`] = `
|
|
|
225
226
|
<View
|
|
226
227
|
onLayout={[Function]}
|
|
227
228
|
style={{}}
|
|
229
|
+
testID="component-A2"
|
|
228
230
|
/>
|
|
229
231
|
</View>
|
|
230
232
|
<View
|
|
@@ -66,7 +66,7 @@ export class AnimationManager {
|
|
|
66
66
|
*
|
|
67
67
|
* @param {object} to contains style to animate and scenes index
|
|
68
68
|
* @param {string} action push|back
|
|
69
|
-
* @param {number} stepsBack number of steps back
|
|
69
|
+
* @param {number} [stepsBack] number of steps back, used by the back action only
|
|
70
70
|
*/
|
|
71
71
|
stateForAction({ to, scenes }, action, stepsBack) {
|
|
72
72
|
let rootIndex = to.index;
|
|
@@ -17,13 +17,14 @@ const fullWidthDimensions = {
|
|
|
17
17
|
type Props = {
|
|
18
18
|
children: any;
|
|
19
19
|
style: any;
|
|
20
|
-
pointerEvents
|
|
21
|
-
overlayStyle
|
|
22
|
-
animating
|
|
20
|
+
pointerEvents?: ViewProps["pointerEvents"];
|
|
21
|
+
overlayStyle?: ViewStyle;
|
|
22
|
+
animating?: boolean;
|
|
23
23
|
contentStyle: ViewStyle;
|
|
24
24
|
pathname: string;
|
|
25
25
|
isActive: boolean;
|
|
26
26
|
screenData: NavigationScreenData;
|
|
27
|
+
screenUniqueId?: string;
|
|
27
28
|
};
|
|
28
29
|
|
|
29
30
|
export function CurrentScreenContextProvider({
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { View } from "react-native";
|
|
3
|
-
import { append, compose, identity, tail,
|
|
3
|
+
import { append, compose, identity, tail, update } from "ramda";
|
|
4
4
|
|
|
5
5
|
import { AnimationManager } from "./AnimationManager";
|
|
6
6
|
import { Scene } from "./Scene";
|
|
@@ -18,11 +18,23 @@ export const NAV_ACTION_REPLACE = "REPLACE";
|
|
|
18
18
|
|
|
19
19
|
export const NAV_ACTION_BACK = "POP";
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
const RIVER_SEGMENT_REGEX = /river\//g;
|
|
22
|
+
|
|
23
|
+
// Number of "river/" segments in the route, i.e. its depth in the navigation stack
|
|
24
|
+
function countRiverSegments(route?: string): number {
|
|
25
|
+
return (route?.match(RIVER_SEGMENT_REGEX) || []).length;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// The screen element rendered for the current route
|
|
29
|
+
type SceneChild = React.ReactElement<{
|
|
30
|
+
pathname: string;
|
|
31
|
+
screenData: NavigationScreenData;
|
|
32
|
+
}>;
|
|
33
|
+
|
|
34
|
+
type TransitionerScene = {
|
|
35
|
+
children: SceneChild;
|
|
36
|
+
key: string;
|
|
37
|
+
screenUniqueId: string;
|
|
26
38
|
};
|
|
27
39
|
|
|
28
40
|
/**
|
|
@@ -31,7 +43,7 @@ type SceneProps = {
|
|
|
31
43
|
* @param {Object} children
|
|
32
44
|
* @returns { children: Object, key: string }
|
|
33
45
|
*/
|
|
34
|
-
function prepareScene(children) {
|
|
46
|
+
function prepareScene(children: SceneChild): TransitionerScene {
|
|
35
47
|
return {
|
|
36
48
|
children,
|
|
37
49
|
key: children.props.pathname,
|
|
@@ -45,7 +57,10 @@ function prepareScene(children) {
|
|
|
45
57
|
* @param {any} props Component's props
|
|
46
58
|
* @param {any} state Component's state
|
|
47
59
|
*/
|
|
48
|
-
function scenesForBackTransition(
|
|
60
|
+
function scenesForBackTransition(
|
|
61
|
+
props: Pick<Props, "children">,
|
|
62
|
+
{ scenes }: Pick<State, "scenes">
|
|
63
|
+
): TransitionerScene[] {
|
|
49
64
|
return scenes.length > 1
|
|
50
65
|
? identity(scenes)
|
|
51
66
|
: [prepareScene(props.children), scenes[0]];
|
|
@@ -53,7 +68,8 @@ function scenesForBackTransition(props: SceneProps, { scenes }) {
|
|
|
53
68
|
|
|
54
69
|
type Props = {
|
|
55
70
|
transitionConfig: any;
|
|
56
|
-
|
|
71
|
+
isRTL?: boolean;
|
|
72
|
+
children: SceneChild;
|
|
57
73
|
navigator: {
|
|
58
74
|
previousAction: string;
|
|
59
75
|
currentRoute: string;
|
|
@@ -78,13 +94,12 @@ type Props = {
|
|
|
78
94
|
};
|
|
79
95
|
|
|
80
96
|
type State = {
|
|
81
|
-
animatedValue: any;
|
|
82
97
|
animating: boolean;
|
|
83
98
|
duration: number;
|
|
84
99
|
easing: any;
|
|
85
100
|
from: any;
|
|
86
101
|
to: any;
|
|
87
|
-
scenes:
|
|
102
|
+
scenes: TransitionerScene[];
|
|
88
103
|
};
|
|
89
104
|
|
|
90
105
|
const styles = {
|
|
@@ -92,11 +107,18 @@ const styles = {
|
|
|
92
107
|
} as const;
|
|
93
108
|
|
|
94
109
|
export class TransitionerComponent extends React.PureComponent<Props, State> {
|
|
110
|
+
private animationManager: AnimationManager;
|
|
111
|
+
|
|
112
|
+
private transitionId: number;
|
|
113
|
+
|
|
95
114
|
constructor(props: Props) {
|
|
96
115
|
super(props);
|
|
97
116
|
|
|
98
117
|
this.animationManager = new AnimationManager(props);
|
|
99
118
|
|
|
119
|
+
// Bumped by every animated transition; end callbacks of older ones are ignored
|
|
120
|
+
this.transitionId = 0;
|
|
121
|
+
|
|
100
122
|
this.state = {
|
|
101
123
|
scenes: [prepareScene(props.children)], // starting with index: 0
|
|
102
124
|
...this.animationManager.initialState(),
|
|
@@ -113,28 +135,36 @@ export class TransitionerComponent extends React.PureComponent<Props, State> {
|
|
|
113
135
|
* and trigger push animation with callbacks.
|
|
114
136
|
*/
|
|
115
137
|
pushTransitionStart() {
|
|
138
|
+
const transitionId = ++this.transitionId;
|
|
139
|
+
|
|
116
140
|
this.setState(
|
|
117
141
|
{
|
|
118
|
-
|
|
142
|
+
// Append right after the visible scene: stateForAction(PUSH) animates to.index + 1
|
|
143
|
+
scenes: [
|
|
144
|
+
...this.state.scenes.slice(0, this.state.to.index + 1),
|
|
145
|
+
prepareScene(this.props.children),
|
|
146
|
+
],
|
|
119
147
|
...this.animationManager.stateForAction(this.state, NAV_ACTION_PUSH),
|
|
120
148
|
},
|
|
121
149
|
() => {
|
|
122
|
-
this.animationManager.animate(this.state,
|
|
150
|
+
this.animationManager.animate(this.state, () =>
|
|
151
|
+
this.pushTransitionEnd(transitionId)
|
|
152
|
+
);
|
|
123
153
|
}
|
|
124
154
|
);
|
|
125
155
|
}
|
|
126
156
|
|
|
127
157
|
/**
|
|
128
158
|
* Trigger back animation.
|
|
129
|
-
* The
|
|
159
|
+
* The scenes after the target one are removed in the "backTransitionEnd" callback,
|
|
130
160
|
* only after the animation is complete.
|
|
131
161
|
*/
|
|
132
162
|
backTransitionStart(previousRoute: string) {
|
|
163
|
+
const transitionId = ++this.transitionId;
|
|
133
164
|
const currentRoute = this.props.navigator?.currentRoute;
|
|
134
165
|
|
|
135
166
|
const diffLengthRoutes =
|
|
136
|
-
(previousRoute
|
|
137
|
-
(currentRoute?.match(/river\//g) || []).length;
|
|
167
|
+
countRiverSegments(previousRoute) - countRiverSegments(currentRoute);
|
|
138
168
|
|
|
139
169
|
const stepsBack =
|
|
140
170
|
diffLengthRoutes && diffLengthRoutes > 0 ? diffLengthRoutes : 1;
|
|
@@ -150,30 +180,32 @@ export class TransitionerComponent extends React.PureComponent<Props, State> {
|
|
|
150
180
|
},
|
|
151
181
|
() => {
|
|
152
182
|
this.animationManager.animate(this.state, () =>
|
|
153
|
-
this.backTransitionEnd(
|
|
183
|
+
this.backTransitionEnd(transitionId)
|
|
154
184
|
);
|
|
155
185
|
}
|
|
156
186
|
);
|
|
157
187
|
}
|
|
158
188
|
|
|
159
|
-
shouldSkipAnimationForRoute(route) {
|
|
189
|
+
shouldSkipAnimationForRoute(route: string) {
|
|
160
190
|
// We are skipping animations for some routes, likes hooks & the player mainly
|
|
161
191
|
|
|
162
192
|
return route.includes("/playable") || route.includes("/hook");
|
|
163
193
|
}
|
|
164
194
|
|
|
165
|
-
shouldResetStateForRoute(route) {
|
|
195
|
+
shouldResetStateForRoute(route: string) {
|
|
166
196
|
// We are resetting the transitioner state for root routes
|
|
167
197
|
|
|
168
|
-
return (route
|
|
198
|
+
return countRiverSegments(route) === 1;
|
|
169
199
|
}
|
|
170
200
|
|
|
171
|
-
transitionWithoutAnimation(resetState) {
|
|
172
|
-
|
|
201
|
+
transitionWithoutAnimation(resetState?: boolean) {
|
|
202
|
+
// Scenes after the visible one are only leaving (back animation in flight),
|
|
203
|
+
// so the new scene replaces the one being backed to
|
|
204
|
+
const scenes = this.state.scenes.slice(0, this.state.to.index + 1);
|
|
173
205
|
const newScene = prepareScene(this.props.children);
|
|
174
206
|
const isLastSceneHook = scenes[scenes.length - 1].key.startsWith("/hook");
|
|
175
207
|
|
|
176
|
-
let newState
|
|
208
|
+
let newState: Pick<State, "scenes"> | Pick<State, "scenes" | "to">;
|
|
177
209
|
|
|
178
210
|
if (resetState) {
|
|
179
211
|
newState = {
|
|
@@ -263,20 +295,27 @@ export class TransitionerComponent extends React.PureComponent<Props, State> {
|
|
|
263
295
|
}
|
|
264
296
|
}
|
|
265
297
|
|
|
266
|
-
// Sets state.animating to false
|
|
267
|
-
|
|
298
|
+
// Sets state.animating to false,
|
|
299
|
+
// unless a newer transition has started since this one
|
|
300
|
+
pushTransitionEnd(transitionId: number) {
|
|
301
|
+
if (transitionId !== this.transitionId) return;
|
|
302
|
+
|
|
268
303
|
this.setState({
|
|
269
304
|
animating: false,
|
|
270
305
|
});
|
|
271
306
|
}
|
|
272
307
|
|
|
273
308
|
// Sets state.animating to false
|
|
274
|
-
// and
|
|
275
|
-
|
|
276
|
-
|
|
309
|
+
// and drops every scene after the target one. Reads the latest state,
|
|
310
|
+
// so it's correct however many backs were merged into this animation.
|
|
311
|
+
// Ignored if a newer transition has started since this one
|
|
312
|
+
backTransitionEnd(transitionId: number) {
|
|
313
|
+
if (transitionId !== this.transitionId) return;
|
|
314
|
+
|
|
315
|
+
this.setState(({ scenes, to }) => ({
|
|
277
316
|
animating: false,
|
|
278
|
-
scenes:
|
|
279
|
-
});
|
|
317
|
+
scenes: scenes.slice(0, to.index + 1),
|
|
318
|
+
}));
|
|
280
319
|
}
|
|
281
320
|
|
|
282
321
|
// On initial state, both "to" and "from" point to a single scene
|