@remotion/transitions 4.0.177 → 4.0.179

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.
Files changed (31) hide show
  1. package/.rollup.cache/Users/jonathanburger/remotion/packages/transitions/dist/TransitionSeries.js +148 -0
  2. package/.rollup.cache/Users/jonathanburger/remotion/packages/transitions/dist/flatten-children.js +12 -0
  3. package/.rollup.cache/Users/jonathanburger/remotion/packages/transitions/dist/index.js +5 -0
  4. package/.rollup.cache/Users/jonathanburger/remotion/packages/transitions/dist/presentations/clock-wipe.js +42 -0
  5. package/.rollup.cache/Users/jonathanburger/remotion/packages/transitions/dist/presentations/fade.js +27 -0
  6. package/.rollup.cache/Users/jonathanburger/remotion/packages/transitions/dist/presentations/flip.js +45 -0
  7. package/.rollup.cache/Users/jonathanburger/remotion/packages/transitions/dist/presentations/slide.js +72 -0
  8. package/.rollup.cache/Users/jonathanburger/remotion/packages/transitions/dist/presentations/wipe.js +159 -0
  9. package/.rollup.cache/Users/jonathanburger/remotion/packages/transitions/dist/test/transitions.test.js +33 -0
  10. package/.rollup.cache/Users/jonathanburger/remotion/packages/transitions/dist/timings/linear-timing.js +15 -0
  11. package/.rollup.cache/Users/jonathanburger/remotion/packages/transitions/dist/timings/spring-timing.js +30 -0
  12. package/.rollup.cache/Users/jonathanburger/remotion/packages/transitions/dist/types.js +1 -0
  13. package/.rollup.cache/Users/jonathanburger/remotion/packages/transitions/dist/validate.js +3 -0
  14. package/README.md +18 -0
  15. package/bundle.ts +1 -1
  16. package/dist/TransitionSeries.js +4 -3
  17. package/dist/context.d.ts +8 -8
  18. package/dist/context.js +5 -26
  19. package/dist/esm/index.mjs +87 -25
  20. package/dist/esm/none.mjs +26 -0
  21. package/dist/index.d.ts +1 -0
  22. package/dist/index.js +4 -1
  23. package/dist/presentations/{context.d.ts → none.d.ts} +1 -1
  24. package/dist/presentations/{context.js → none.js} +3 -3
  25. package/dist/use-transition-progress.d.ts +9 -0
  26. package/dist/use-transition-progress.js +29 -0
  27. package/none.js +2 -0
  28. package/package.json +22 -19
  29. package/.prettierrc.js +0 -14
  30. package/dist/esm/context.mjs +0 -44
  31. package/vitest.config.mts +0 -11
@@ -0,0 +1,148 @@
1
+ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
2
+ import { Children, useMemo } from 'react';
3
+ import { Internals, Sequence, useCurrentFrame, useVideoConfig } from 'remotion';
4
+ import { flattenChildren } from './flatten-children.js';
5
+ import { slide } from './presentations/slide.js';
6
+ import { validateDurationInFrames } from './validate.js';
7
+ // eslint-disable-next-line react/function-component-definition
8
+ const TransitionSeriesTransition = function (
9
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
10
+ _props) {
11
+ return null;
12
+ };
13
+ const SeriesSequence = ({ children }) => {
14
+ // eslint-disable-next-line react/jsx-no-useless-fragment
15
+ return _jsx(_Fragment, { children: children });
16
+ };
17
+ const TransitionSeriesChildren = ({ children, }) => {
18
+ const { fps } = useVideoConfig();
19
+ const frame = useCurrentFrame();
20
+ const childrenValue = useMemo(() => {
21
+ let transitionOffsets = 0;
22
+ let startFrame = 0;
23
+ const flattedChildren = flattenChildren(children);
24
+ return Children.map(flattedChildren, (child, i) => {
25
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
26
+ const current = child;
27
+ if (typeof current === 'string') {
28
+ // Don't throw if it's just some accidential whitespace
29
+ if (current.trim() === '') {
30
+ return null;
31
+ }
32
+ throw new TypeError(`The <TransitionSeries /> component only accepts a list of <TransitionSeries.Sequence /> components as its children, but you passed a string "${current}"`);
33
+ }
34
+ const hasPrev = flattedChildren[i - 1];
35
+ const nextPrev = flattedChildren[i + 1];
36
+ const prev = typeof hasPrev === 'string' || typeof hasPrev === 'undefined'
37
+ ? null
38
+ : hasPrev.type === TransitionSeriesTransition
39
+ ? hasPrev
40
+ : null;
41
+ const next = typeof nextPrev === 'string' || typeof nextPrev === 'undefined'
42
+ ? null
43
+ : nextPrev.type === TransitionSeriesTransition
44
+ ? nextPrev
45
+ : null;
46
+ const prevIsTransition = typeof hasPrev === 'string' || typeof hasPrev === 'undefined'
47
+ ? false
48
+ : hasPrev.type === TransitionSeriesTransition;
49
+ if (current.type === TransitionSeriesTransition) {
50
+ if (prevIsTransition) {
51
+ throw new TypeError(`A <TransitionSeries.Transition /> component must not be followed by another <TransitionSeries.Transition /> component (nth children = ${i - 1} and ${i})`);
52
+ }
53
+ return null;
54
+ }
55
+ if (current.type !== SeriesSequence) {
56
+ throw new TypeError(`The <TransitionSeries /> component only accepts a list of <TransitionSeries.Sequence /> and <TransitionSeries.Transition /> components as its children, but got ${current} instead`);
57
+ }
58
+ const castedChildAgain = current;
59
+ const debugInfo = `index = ${i}, duration = ${castedChildAgain.props.durationInFrames}`;
60
+ if (!(castedChildAgain === null || castedChildAgain === void 0 ? void 0 : castedChildAgain.props.children)) {
61
+ throw new TypeError(`A <TransitionSeries.Sequence /> component (${debugInfo}) was detected to not have any children. Delete it to fix this error.`);
62
+ }
63
+ const durationInFramesProp = castedChildAgain.props.durationInFrames;
64
+ const { durationInFrames, children: _children, ...passedProps } = castedChildAgain.props;
65
+ validateDurationInFrames(durationInFramesProp, {
66
+ component: `of a <TransitionSeries.Sequence /> component`,
67
+ allowFloats: true,
68
+ });
69
+ const offset = (_a = castedChildAgain.props.offset) !== null && _a !== void 0 ? _a : 0;
70
+ if (Number.isNaN(offset)) {
71
+ throw new TypeError(`The "offset" property of a <TransitionSeries.Sequence /> must not be NaN, but got NaN (${debugInfo}).`);
72
+ }
73
+ if (!Number.isFinite(offset)) {
74
+ throw new TypeError(`The "offset" property of a <TransitionSeries.Sequence /> must be finite, but got ${offset} (${debugInfo}).`);
75
+ }
76
+ if (offset % 1 !== 0) {
77
+ throw new TypeError(`The "offset" property of a <TransitionSeries.Sequence /> must be finite, but got ${offset} (${debugInfo}).`);
78
+ }
79
+ const currentStartFrame = startFrame + offset;
80
+ let duration = 0;
81
+ if (prev) {
82
+ duration = prev.props.timing.getDurationInFrames({
83
+ fps,
84
+ });
85
+ transitionOffsets -= duration;
86
+ }
87
+ let actualStartFrame = currentStartFrame + transitionOffsets;
88
+ startFrame += durationInFramesProp + offset;
89
+ // Handle the case where the first item is a transition
90
+ if (actualStartFrame < 0) {
91
+ startFrame -= actualStartFrame;
92
+ actualStartFrame = 0;
93
+ }
94
+ const nextProgress = next
95
+ ? next.props.timing.getProgress({
96
+ frame: frame -
97
+ actualStartFrame -
98
+ durationInFrames +
99
+ next.props.timing.getDurationInFrames({ fps }),
100
+ fps,
101
+ })
102
+ : null;
103
+ const prevProgress = prev
104
+ ? prev.props.timing.getProgress({
105
+ frame: frame - actualStartFrame,
106
+ fps,
107
+ })
108
+ : null;
109
+ if (next &&
110
+ durationInFramesProp < next.props.timing.getDurationInFrames({ fps })) {
111
+ throw new Error(`The duration of a <TransitionSeries.Sequence /> must not be shorter than the duration of the next <TransitionSeries.Transition />. The transition is ${next.props.timing.getDurationInFrames({ fps })} frames long, but the sequence is only ${durationInFramesProp} frames long (${debugInfo})`);
112
+ }
113
+ if (prev &&
114
+ durationInFramesProp < prev.props.timing.getDurationInFrames({ fps })) {
115
+ throw new Error(`The duration of a <TransitionSeries.Sequence /> must not be shorter than the duration of the previous <TransitionSeries.Transition />. The transition is ${prev.props.timing.getDurationInFrames({ fps })} frames long, but the sequence is only ${durationInFramesProp} frames long (${debugInfo})`);
116
+ }
117
+ if (next && prev && nextProgress !== null && prevProgress !== null) {
118
+ const nextPresentation = (_b = next.props.presentation) !== null && _b !== void 0 ? _b : slide();
119
+ const prevPresentation = (_c = prev.props.presentation) !== null && _c !== void 0 ? _c : slide();
120
+ const UppercaseNextPresentation = nextPresentation.component;
121
+ const UppercasePrevPresentation = prevPresentation.component;
122
+ return (_jsx(Sequence, { name: passedProps.name || '<TS.Sequence>', from: Math.floor(actualStartFrame), durationInFrames: durationInFramesProp, layout: "none", stack: passedProps.stack, children: _jsx(UppercaseNextPresentation, { passedProps: (_d = nextPresentation.props) !== null && _d !== void 0 ? _d : {}, presentationDirection: "exiting", presentationProgress: nextProgress, children: _jsx(UppercasePrevPresentation, { passedProps: (_e = prevPresentation.props) !== null && _e !== void 0 ? _e : {}, presentationDirection: "entering", presentationProgress: prevProgress, children: _jsx(Sequence, { showInTimeline: false, ...passedProps, children: child }) }) }) }));
123
+ }
124
+ if (prevProgress !== null && prev) {
125
+ const prevPresentation = (_f = prev.props.presentation) !== null && _f !== void 0 ? _f : slide();
126
+ const UppercasePrevPresentation = prevPresentation.component;
127
+ return (_jsx(Sequence, { name: passedProps.name || '<TS.Sequence>', from: Math.floor(actualStartFrame), durationInFrames: durationInFramesProp, layout: "none", stack: passedProps.stack, children: _jsx(UppercasePrevPresentation, { passedProps: (_g = prevPresentation.props) !== null && _g !== void 0 ? _g : {}, presentationDirection: "entering", presentationProgress: prevProgress, children: _jsx(Sequence, { showInTimeline: false, ...passedProps, children: child }) }) }));
128
+ }
129
+ if (nextProgress !== null && next) {
130
+ const nextPresentation = (_h = next.props.presentation) !== null && _h !== void 0 ? _h : slide();
131
+ const UppercaseNextPresentation = nextPresentation.component;
132
+ return (_jsx(Sequence, { name: passedProps.name || '<TS.Sequence>', from: Math.floor(actualStartFrame), durationInFrames: durationInFramesProp, layout: "none", stack: passedProps.stack, children: _jsx(UppercaseNextPresentation, { passedProps: (_j = nextPresentation.props) !== null && _j !== void 0 ? _j : {}, presentationDirection: "exiting", presentationProgress: nextProgress, children: _jsx(Sequence, { showInTimeline: false, ...passedProps, children: child }) }) }));
133
+ }
134
+ return (_jsx(Sequence, { name: passedProps.name || '<TS.Sequence>', from: Math.floor(actualStartFrame), durationInFrames: durationInFramesProp, ...passedProps, children: child }));
135
+ });
136
+ }, [children, fps, frame]);
137
+ // eslint-disable-next-line react/jsx-no-useless-fragment
138
+ return _jsx(_Fragment, { children: childrenValue });
139
+ };
140
+ const TransitionSeries = ({ children, name, ...otherProps }) => {
141
+ const displayName = name !== null && name !== void 0 ? name : '<TransitionSeries>';
142
+ return (_jsx(Sequence, { name: displayName, ...otherProps, children: _jsx(TransitionSeriesChildren, { children: children }) }));
143
+ };
144
+ TransitionSeries.Sequence = SeriesSequence;
145
+ TransitionSeries.Transition = TransitionSeriesTransition;
146
+ export { TransitionSeries };
147
+ Internals.addSequenceStackTraces(TransitionSeries);
148
+ Internals.addSequenceStackTraces(SeriesSequence);
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ export const flattenChildren = (children) => {
3
+ const childrenArray = React.Children.toArray(children);
4
+ return childrenArray.reduce((flatChildren, child) => {
5
+ if (child.type === React.Fragment) {
6
+ return flatChildren.concat(flattenChildren(child.props
7
+ .children));
8
+ }
9
+ flatChildren.push(child);
10
+ return flatChildren;
11
+ }, []);
12
+ };
@@ -0,0 +1,5 @@
1
+ // Timings
2
+ export { linearTiming } from './timings/linear-timing.js';
3
+ export { springTiming } from './timings/spring-timing.js';
4
+ // Component
5
+ export { TransitionSeries } from './TransitionSeries.js';
@@ -0,0 +1,42 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { translatePath } from '@remotion/paths';
3
+ import { makePie } from '@remotion/shapes';
4
+ import { useMemo, useState } from 'react';
5
+ import { AbsoluteFill, random } from 'remotion';
6
+ const ClockWipePresentation = ({ children, presentationDirection, presentationProgress, passedProps }) => {
7
+ const finishedRadius = Math.sqrt(passedProps.width ** 2 + passedProps.height ** 2) / 2;
8
+ const { path } = makePie({
9
+ radius: finishedRadius,
10
+ progress: presentationProgress,
11
+ });
12
+ const translatedPath = translatePath(path, -(finishedRadius * 2 - passedProps.width) / 2, -(finishedRadius * 2 - passedProps.height) / 2);
13
+ const [clipId] = useState(() => String(random(null)));
14
+ const style = useMemo(() => {
15
+ return {
16
+ width: '100%',
17
+ height: '100%',
18
+ clipPath: presentationDirection === 'exiting' ? undefined : `url(#${clipId})`,
19
+ ...(presentationDirection === 'entering'
20
+ ? passedProps.innerEnterStyle
21
+ : passedProps.innerExitStyle),
22
+ };
23
+ }, [
24
+ clipId,
25
+ passedProps.innerEnterStyle,
26
+ passedProps.innerExitStyle,
27
+ presentationDirection,
28
+ ]);
29
+ const outerStyle = useMemo(() => {
30
+ return presentationDirection === 'entering'
31
+ ? passedProps.outerEnterStyle
32
+ : passedProps.outerExitStyle;
33
+ }, [
34
+ passedProps.outerEnterStyle,
35
+ passedProps.outerExitStyle,
36
+ presentationDirection,
37
+ ]);
38
+ return (_jsxs(AbsoluteFill, { style: outerStyle, children: [_jsx(AbsoluteFill, { style: style, children: children }), presentationDirection === 'exiting' ? null : (_jsx(AbsoluteFill, { children: _jsx("svg", { children: _jsx("defs", { children: _jsx("clipPath", { id: clipId, children: _jsx("path", { d: translatedPath, fill: "black" }) }) }) }) }))] }));
39
+ };
40
+ export const clockWipe = (props) => {
41
+ return { component: ClockWipePresentation, props: props !== null && props !== void 0 ? props : {} };
42
+ };
@@ -0,0 +1,27 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useMemo } from 'react';
3
+ import { AbsoluteFill } from 'remotion';
4
+ const FadePresentation = ({ children, presentationDirection, presentationProgress, passedProps }) => {
5
+ const isEntering = presentationDirection === 'entering';
6
+ const style = useMemo(() => {
7
+ return {
8
+ opacity: isEntering ? presentationProgress : 1,
9
+ ...(presentationDirection === 'entering'
10
+ ? passedProps.enterStyle
11
+ : passedProps.exitStyle),
12
+ };
13
+ }, [
14
+ isEntering,
15
+ passedProps.enterStyle,
16
+ passedProps.exitStyle,
17
+ presentationDirection,
18
+ presentationProgress,
19
+ ]);
20
+ return _jsx(AbsoluteFill, { style: style, children: children });
21
+ };
22
+ export const fade = (props) => {
23
+ return {
24
+ component: FadePresentation,
25
+ props: props !== null && props !== void 0 ? props : {},
26
+ };
27
+ };
@@ -0,0 +1,45 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useMemo } from 'react';
3
+ import { AbsoluteFill, interpolate } from 'remotion';
4
+ const Flip = ({ children, presentationDirection, presentationProgress, passedProps: { direction = 'from-left', perspective = 1000, innerEnterStyle, innerExitStyle, outerEnterStyle, outerExitStyle, }, }) => {
5
+ const style = useMemo(() => {
6
+ const startRotationEntering = direction === 'from-right' || direction === 'from-top' ? 180 : -180;
7
+ const endRotationEntering = direction === 'from-right' || direction === 'from-top' ? -180 : 180;
8
+ const rotation = presentationDirection === 'entering'
9
+ ? interpolate(presentationProgress, [0, 1], [startRotationEntering, 0])
10
+ : interpolate(presentationProgress, [0, 1], [0, endRotationEntering]);
11
+ const rotateProperty = direction === 'from-top' || direction === 'from-bottom'
12
+ ? 'rotateX'
13
+ : 'rotateY';
14
+ return {
15
+ width: '100%',
16
+ height: '100%',
17
+ transform: `${rotateProperty}(${rotation}deg)`,
18
+ backfaceVisibility: 'hidden',
19
+ WebkitBackfaceVisibility: 'hidden',
20
+ ...(presentationDirection === 'entering'
21
+ ? innerEnterStyle
22
+ : innerExitStyle),
23
+ };
24
+ }, [
25
+ direction,
26
+ innerEnterStyle,
27
+ innerExitStyle,
28
+ presentationDirection,
29
+ presentationProgress,
30
+ ]);
31
+ const outer = useMemo(() => {
32
+ return {
33
+ perspective,
34
+ // Make children also their backface hidden
35
+ transformStyle: 'preserve-3d',
36
+ ...(presentationDirection === 'entering'
37
+ ? outerEnterStyle
38
+ : outerExitStyle),
39
+ };
40
+ }, [outerEnterStyle, outerExitStyle, perspective, presentationDirection]);
41
+ return (_jsx(AbsoluteFill, { style: outer, children: _jsx(AbsoluteFill, { style: style, children: children }) }));
42
+ };
43
+ export const flip = (props) => {
44
+ return { component: Flip, props: props !== null && props !== void 0 ? props : {} };
45
+ };
@@ -0,0 +1,72 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useMemo } from 'react';
3
+ import { AbsoluteFill } from 'remotion';
4
+ const epsilon = 0.01;
5
+ const SlidePresentation = ({ children, presentationProgress, presentationDirection, passedProps: { direction = 'from-left', enterStyle, exitStyle }, }) => {
6
+ const directionStyle = useMemo(() => {
7
+ // Overlay the two slides barely to avoid a white line between them
8
+ // Remove the correction once the presentation progress is 1
9
+ const presentationProgressWithEpsilonCorrection = presentationProgress === 1
10
+ ? presentationProgress * 100
11
+ : presentationProgress * 100 - epsilon;
12
+ if (presentationDirection === 'exiting') {
13
+ switch (direction) {
14
+ case 'from-left':
15
+ return {
16
+ transform: `translateX(${presentationProgressWithEpsilonCorrection}%)`,
17
+ };
18
+ case 'from-right':
19
+ return {
20
+ transform: `translateX(-${presentationProgress * 100}%)`,
21
+ };
22
+ case 'from-top':
23
+ return {
24
+ transform: `translateY(${presentationProgressWithEpsilonCorrection}%)`,
25
+ };
26
+ case 'from-bottom':
27
+ return {
28
+ transform: `translateY(-${presentationProgress * 100}%)`,
29
+ };
30
+ default:
31
+ throw new Error(`Invalid direction: ${direction}`);
32
+ }
33
+ }
34
+ switch (direction) {
35
+ case 'from-left':
36
+ return {
37
+ transform: `translateX(${-100 + presentationProgress * 100}%)`,
38
+ };
39
+ case 'from-right':
40
+ return {
41
+ transform: `translateX(${100 - presentationProgressWithEpsilonCorrection}%)`,
42
+ };
43
+ case 'from-top':
44
+ return {
45
+ transform: `translateY(${-100 + presentationProgress * 100}%)`,
46
+ };
47
+ case 'from-bottom':
48
+ return {
49
+ transform: `translateY(${100 - presentationProgressWithEpsilonCorrection}%)`,
50
+ };
51
+ default:
52
+ throw new Error(`Invalid direction: ${direction}`);
53
+ }
54
+ }, [presentationDirection, presentationProgress, direction]);
55
+ const style = useMemo(() => {
56
+ return {
57
+ width: '100%',
58
+ height: '100%',
59
+ justifyContent: 'center',
60
+ alignItems: 'center',
61
+ ...directionStyle,
62
+ ...(presentationDirection === 'entering' ? enterStyle : exitStyle),
63
+ };
64
+ }, [directionStyle, enterStyle, exitStyle, presentationDirection]);
65
+ return _jsx(AbsoluteFill, { style: style, children: children });
66
+ };
67
+ export const slide = (props) => {
68
+ return {
69
+ component: SlidePresentation,
70
+ props: props !== null && props !== void 0 ? props : {},
71
+ };
72
+ };
@@ -0,0 +1,159 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useMemo, useState } from 'react';
3
+ import { AbsoluteFill, random } from 'remotion';
4
+ const makePathIn = (progress, direction) => {
5
+ switch (direction) {
6
+ case 'from-left':
7
+ return `
8
+ M 0 0
9
+ L ${progress} 0
10
+ L ${progress} 1
11
+ L 0 1
12
+ Z`;
13
+ case 'from-top-left':
14
+ return `
15
+ M 0 0
16
+ L ${progress * 2} 0
17
+ L 0 ${progress * 2}
18
+ Z`;
19
+ case 'from-top':
20
+ return `
21
+ M 0 0
22
+ L 1 0
23
+ L 1 ${progress}
24
+ L 0 ${progress}
25
+ Z`;
26
+ case 'from-top-right':
27
+ return `
28
+ M 1 0
29
+ L ${1 - progress * 2} 0
30
+ L 1 ${progress * 2}
31
+ Z`;
32
+ case 'from-right':
33
+ return `
34
+ M 1 0
35
+ L 1 1
36
+ L ${1 - progress} 1
37
+ L ${1 - progress} 0
38
+ Z`;
39
+ case 'from-bottom-right':
40
+ return `
41
+ M 1 1
42
+ L ${1 - progress * 2} 1
43
+ L 1 ${1 - progress * 2}
44
+ Z`;
45
+ case 'from-bottom':
46
+ return `
47
+ M 0 1
48
+ L 1 1
49
+ L 1 ${1 - progress}
50
+ L 0 ${1 - progress}
51
+ Z`;
52
+ case 'from-bottom-left':
53
+ return `
54
+ M 0 1
55
+ L 0 ${1 - progress * 2}
56
+ L ${progress * 2} 1
57
+ Z`;
58
+ default:
59
+ throw new Error(`Unknown direction ${JSON.stringify(direction)}`);
60
+ }
61
+ };
62
+ const makePathOut = (progress, direction) => {
63
+ switch (direction) {
64
+ case 'from-left':
65
+ return `
66
+ M 1 1
67
+ L ${1 - progress} 1
68
+ L ${1 - progress} 0
69
+ L 1 0
70
+ Z`;
71
+ case 'from-top-left':
72
+ return `
73
+ M 1 1
74
+ L ${1 - 2 * progress} 1
75
+ L 1 ${1 - 2 * progress}
76
+ Z`;
77
+ case 'from-top':
78
+ return `
79
+ M 1 1
80
+ L 0 1
81
+ L 0 ${1 - progress}
82
+ L 1 ${1 - progress}
83
+ Z`;
84
+ case 'from-top-right':
85
+ return `
86
+ M 0 1
87
+ L ${progress * 2} 1
88
+ L 0 ${1 - progress * 2}
89
+ Z`;
90
+ case 'from-right':
91
+ return `
92
+ M 0 0
93
+ L ${progress} 0
94
+ L ${progress} 1
95
+ L 0 1
96
+ Z`;
97
+ case 'from-bottom-right':
98
+ return `
99
+ M 0 0
100
+ L ${progress * 2} 0
101
+ L 0 ${progress * 2}
102
+ Z`;
103
+ case 'from-bottom':
104
+ return `
105
+ M 1 0
106
+ L 0 0
107
+ L 0 ${progress}
108
+ L 1 ${progress}
109
+ Z`;
110
+ case 'from-bottom-left':
111
+ return `
112
+ M 1 0
113
+ L ${1 - progress * 2} 0
114
+ L 1 ${progress * 2}
115
+ Z`;
116
+ default:
117
+ throw new Error(`Unknown direction ${JSON.stringify(direction)}`);
118
+ }
119
+ };
120
+ const WipePresentation = ({ children, presentationProgress, presentationDirection, passedProps: { direction = 'from-left', innerEnterStyle, innerExitStyle, outerEnterStyle, outerExitStyle, }, }) => {
121
+ const [clipId] = useState(() => String(random(null)));
122
+ const progressInDirection = presentationDirection === 'entering'
123
+ ? presentationProgress
124
+ : 1 - presentationProgress;
125
+ const path = presentationDirection === 'entering'
126
+ ? makePathIn(progressInDirection, direction)
127
+ : makePathOut(progressInDirection, direction);
128
+ const style = useMemo(() => {
129
+ return {
130
+ width: '100%',
131
+ height: '100%',
132
+ justifyContent: 'center',
133
+ alignItems: 'center',
134
+ clipPath: `url(#${clipId})`,
135
+ ...(presentationDirection === 'entering'
136
+ ? innerEnterStyle
137
+ : innerExitStyle),
138
+ };
139
+ }, [clipId, innerEnterStyle, innerExitStyle, presentationDirection]);
140
+ const outerStyle = useMemo(() => {
141
+ return presentationDirection === 'entering'
142
+ ? outerEnterStyle
143
+ : outerExitStyle;
144
+ }, [outerEnterStyle, outerExitStyle, presentationDirection]);
145
+ const svgStyle = useMemo(() => {
146
+ return {
147
+ width: '100%',
148
+ height: '100%',
149
+ pointerEvents: 'none',
150
+ };
151
+ }, []);
152
+ return (_jsxs(AbsoluteFill, { style: outerStyle, children: [_jsx(AbsoluteFill, { style: style, children: children }), _jsx(AbsoluteFill, { children: _jsx("svg", { viewBox: "0 0 1 1", style: svgStyle, children: _jsx("defs", { children: _jsx("clipPath", { id: clipId, clipPathUnits: "objectBoundingBox", children: _jsx("path", { d: path, fill: "black" }) }) }) }) })] }));
153
+ };
154
+ export const wipe = (props) => {
155
+ return {
156
+ component: WipePresentation,
157
+ props: props !== null && props !== void 0 ? props : {},
158
+ };
159
+ };
@@ -0,0 +1,33 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * @vitest-environment jsdom
4
+ */
5
+ import { makeMockCompositionManagerContext, makeTimelineContext, } from '@remotion/test-utils';
6
+ import { renderToString } from 'react-dom/server';
7
+ import { AbsoluteFill, Internals } from 'remotion';
8
+ import { expect, test } from 'vitest';
9
+ import { fade } from '../presentations/fade.js';
10
+ import { linearTiming } from '../timings/linear-timing.js';
11
+ import { TransitionSeries } from '../TransitionSeries.js';
12
+ const renderForFrame = (frame, markup) => {
13
+ return renderToString(_jsx(Internals.CanUseRemotionHooksProvider, { children: _jsx(Internals.CompositionManager.Provider, { value: makeMockCompositionManagerContext(), children: _jsx(Internals.Timeline.TimelineContext.Provider, { value: makeTimelineContext(frame), children: markup }) }) }));
14
+ };
15
+ const Letter = ({ children, color }) => {
16
+ return (_jsx(AbsoluteFill, { style: {
17
+ backgroundColor: color,
18
+ opacity: 0.9,
19
+ justifyContent: 'center',
20
+ alignItems: 'center',
21
+ fontSize: 200,
22
+ color: 'white',
23
+ }, children: children }));
24
+ };
25
+ test('Should throw if two transitions in a row', () => {
26
+ expect(() => {
27
+ return renderForFrame(10, _jsxs(TransitionSeries, { children: [_jsx(TransitionSeries.Sequence, { durationInFrames: 60, children: _jsx(Letter, { color: "green", children: "C" }) }), _jsx(TransitionSeries.Transition, { presentation: fade({}), timing: linearTiming({
28
+ durationInFrames: 40,
29
+ }) }), _jsx(TransitionSeries.Transition, { presentation: fade({}), timing: linearTiming({
30
+ durationInFrames: 40,
31
+ }) })] }));
32
+ }).toThrow('A <TransitionSeries.Transition /> component must not be followed by another <TransitionSeries.Transition /> component (nth children = 1 and 2)');
33
+ });
@@ -0,0 +1,15 @@
1
+ import { interpolate } from 'remotion';
2
+ export const linearTiming = (options) => {
3
+ return {
4
+ getDurationInFrames: () => {
5
+ return options.durationInFrames;
6
+ },
7
+ getProgress: ({ frame }) => {
8
+ return interpolate(frame, [0, options.durationInFrames], [0, 1], {
9
+ easing: options.easing,
10
+ extrapolateLeft: 'clamp',
11
+ extrapolateRight: 'clamp',
12
+ });
13
+ },
14
+ };
15
+ };
@@ -0,0 +1,30 @@
1
+ import { measureSpring, spring } from 'remotion';
2
+ const springWithInvalidArgumentRejection = (args) => {
3
+ if (args.to || args.from) {
4
+ throw new Error('to / from values are not supported by springWithRoundUpIfThreshold');
5
+ }
6
+ return spring(args);
7
+ };
8
+ export const springTiming = (options = {}) => {
9
+ return {
10
+ getDurationInFrames: ({ fps }) => {
11
+ if (options.durationInFrames) {
12
+ return options.durationInFrames;
13
+ }
14
+ return measureSpring({
15
+ config: options.config,
16
+ threshold: options.durationRestThreshold,
17
+ fps,
18
+ });
19
+ },
20
+ getProgress: ({ fps, frame }) => {
21
+ return springWithInvalidArgumentRejection({
22
+ fps,
23
+ frame,
24
+ config: options.config,
25
+ durationInFrames: options.durationInFrames,
26
+ durationRestThreshold: options.durationRestThreshold,
27
+ });
28
+ },
29
+ };
30
+ };
@@ -0,0 +1,3 @@
1
+ /* eslint-disable prefer-destructuring */
2
+ import { NoReactInternals } from 'remotion/no-react';
3
+ export const validateDurationInFrames = NoReactInternals.validateDurationInFrames;
package/README.md ADDED
@@ -0,0 +1,18 @@
1
+ # @remotion/transitions
2
+
3
+ Library for creating transitions in Remotion
4
+
5
+ [![NPM Downloads](https://img.shields.io/npm/dm/@remotion/transitions.svg?style=flat&color=black&label=Downloads)](https://npmcharts.com/compare/@remotion/transitions?minimal=true)
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @remotion/transitions --save-exact
11
+ ```
12
+
13
+ When installing a Remotion package, make sure to align the version of all `remotion` and `@remotion/*` packages to the same version.
14
+ Remove the `^` character from the version number to use the exact version.
15
+
16
+ ## Usage
17
+
18
+ See the [documentation](https://www.remotion.dev/transitions) for more information.
package/bundle.ts CHANGED
@@ -5,7 +5,7 @@ if (process.env.NODE_ENV !== 'production') {
5
5
  throw new Error('This script must be run using NODE_ENV=production');
6
6
  }
7
7
 
8
- const presentations = ['slide', 'flip', 'wipe', 'fade', 'clock-wipe'];
8
+ const presentations = ['slide', 'flip', 'wipe', 'fade', 'clock-wipe', 'none'];
9
9
 
10
10
  const output = await build({
11
11
  entrypoints: [
@@ -5,6 +5,7 @@ const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const remotion_1 = require("remotion");
7
7
  const no_react_1 = require("remotion/no-react");
8
+ const context_js_1 = require("./context.js");
8
9
  const flatten_children_js_1 = require("./flatten-children.js");
9
10
  const slide_js_1 = require("./presentations/slide.js");
10
11
  const validate_js_1 = require("./validate.js");
@@ -125,21 +126,21 @@ const TransitionSeriesChildren = ({ children, }) => {
125
126
  const UppercasePrevPresentation = prevPresentation.component;
126
127
  return ((0, jsx_runtime_1.jsx)(remotion_1.Sequence
127
128
  // eslint-disable-next-line react/no-array-index-key
128
- , { from: Math.floor(actualStartFrame), durationInFrames: durationInFramesProp, ...passedProps, name: passedProps.name || '<TS.Sequence>', children: (0, jsx_runtime_1.jsx)(UppercaseNextPresentation, { passedProps: (_d = nextPresentation.props) !== null && _d !== void 0 ? _d : {}, presentationDirection: "exiting", presentationProgress: nextProgress, presentationDurationInFrames: next.props.timing.getDurationInFrames({ fps }), children: (0, jsx_runtime_1.jsx)(UppercasePrevPresentation, { passedProps: (_e = prevPresentation.props) !== null && _e !== void 0 ? _e : {}, presentationDirection: "entering", presentationProgress: prevProgress, presentationDurationInFrames: prev.props.timing.getDurationInFrames({ fps }), children: child }) }) }, i));
129
+ , { from: Math.floor(actualStartFrame), durationInFrames: durationInFramesProp, ...passedProps, name: passedProps.name || '<TS.Sequence>', children: (0, jsx_runtime_1.jsx)(UppercaseNextPresentation, { passedProps: (_d = nextPresentation.props) !== null && _d !== void 0 ? _d : {}, presentationDirection: "exiting", presentationProgress: nextProgress, presentationDurationInFrames: next.props.timing.getDurationInFrames({ fps }), children: (0, jsx_runtime_1.jsx)(context_js_1.WrapInExitingProgressContext, { presentationProgress: nextProgress, children: (0, jsx_runtime_1.jsx)(UppercasePrevPresentation, { passedProps: (_e = prevPresentation.props) !== null && _e !== void 0 ? _e : {}, presentationDirection: "entering", presentationProgress: prevProgress, presentationDurationInFrames: prev.props.timing.getDurationInFrames({ fps }), children: (0, jsx_runtime_1.jsx)(context_js_1.WrapInEnteringProgressContext, { presentationProgress: prevProgress, children: child }) }) }) }) }, i));
129
130
  }
130
131
  if (prevProgress !== null && prev) {
131
132
  const prevPresentation = (_f = prev.props.presentation) !== null && _f !== void 0 ? _f : (0, slide_js_1.slide)();
132
133
  const UppercasePrevPresentation = prevPresentation.component;
133
134
  return ((0, jsx_runtime_1.jsx)(remotion_1.Sequence
134
135
  // eslint-disable-next-line react/no-array-index-key
135
- , { from: Math.floor(actualStartFrame), durationInFrames: durationInFramesProp, ...passedProps, name: passedProps.name || '<TS.Sequence>', children: (0, jsx_runtime_1.jsx)(UppercasePrevPresentation, { passedProps: (_g = prevPresentation.props) !== null && _g !== void 0 ? _g : {}, presentationDirection: "entering", presentationProgress: prevProgress, presentationDurationInFrames: prev.props.timing.getDurationInFrames({ fps }), children: child }) }, i));
136
+ , { from: Math.floor(actualStartFrame), durationInFrames: durationInFramesProp, ...passedProps, name: passedProps.name || '<TS.Sequence>', children: (0, jsx_runtime_1.jsx)(UppercasePrevPresentation, { passedProps: (_g = prevPresentation.props) !== null && _g !== void 0 ? _g : {}, presentationDirection: "entering", presentationProgress: prevProgress, presentationDurationInFrames: prev.props.timing.getDurationInFrames({ fps }), children: (0, jsx_runtime_1.jsx)(context_js_1.WrapInEnteringProgressContext, { presentationProgress: prevProgress, children: child }) }) }, i));
136
137
  }
137
138
  if (nextProgress !== null && next) {
138
139
  const nextPresentation = (_h = next.props.presentation) !== null && _h !== void 0 ? _h : (0, slide_js_1.slide)();
139
140
  const UppercaseNextPresentation = nextPresentation.component;
140
141
  return ((0, jsx_runtime_1.jsx)(remotion_1.Sequence
141
142
  // eslint-disable-next-line react/no-array-index-key
142
- , { from: Math.floor(actualStartFrame), durationInFrames: durationInFramesProp, ...passedProps, name: passedProps.name || '<TS.Sequence>', children: (0, jsx_runtime_1.jsx)(UppercaseNextPresentation, { passedProps: (_j = nextPresentation.props) !== null && _j !== void 0 ? _j : {}, presentationDirection: "exiting", presentationProgress: nextProgress, presentationDurationInFrames: next.props.timing.getDurationInFrames({ fps }), children: child }) }, i));
143
+ , { from: Math.floor(actualStartFrame), durationInFrames: durationInFramesProp, ...passedProps, name: passedProps.name || '<TS.Sequence>', children: (0, jsx_runtime_1.jsx)(UppercaseNextPresentation, { passedProps: (_j = nextPresentation.props) !== null && _j !== void 0 ? _j : {}, presentationDirection: "exiting", presentationProgress: nextProgress, presentationDurationInFrames: next.props.timing.getDurationInFrames({ fps }), children: (0, jsx_runtime_1.jsx)(context_js_1.WrapInExitingProgressContext, { presentationProgress: nextProgress, children: child }) }) }, i));
143
144
  }
144
145
  return ((0, jsx_runtime_1.jsx)(remotion_1.Sequence
145
146
  // eslint-disable-next-line react/no-array-index-key
package/dist/context.d.ts CHANGED
@@ -1,9 +1,12 @@
1
1
  import React from 'react';
2
- export type TransitionState = {
3
- entering: number;
4
- exiting: number;
5
- isInTransitionSeries: boolean;
2
+ type EnteringState = {
3
+ enteringProgress: number;
6
4
  };
5
+ type ExitingState = {
6
+ exitingProgress: number;
7
+ };
8
+ export declare const EnteringContext: React.Context<EnteringState | null>;
9
+ export declare const ExitingContext: React.Context<ExitingState | null>;
7
10
  export declare const WrapInEnteringProgressContext: React.FC<{
8
11
  readonly presentationProgress: number;
9
12
  readonly children: React.ReactNode;
@@ -12,7 +15,4 @@ export declare const WrapInExitingProgressContext: React.FC<{
12
15
  readonly presentationProgress: number;
13
16
  readonly children: React.ReactNode;
14
17
  }>;
15
- /**
16
- * Gets the progress and direction of a transition with a context() presentation.
17
- */
18
- export declare const useTransitionProgress: () => TransitionState;
18
+ export {};
package/dist/context.js CHANGED
@@ -23,18 +23,18 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.useTransitionProgress = exports.WrapInExitingProgressContext = exports.WrapInEnteringProgressContext = void 0;
26
+ exports.WrapInExitingProgressContext = exports.WrapInEnteringProgressContext = exports.ExitingContext = exports.EnteringContext = void 0;
27
27
  const jsx_runtime_1 = require("react/jsx-runtime");
28
28
  const react_1 = __importStar(require("react"));
29
- const EnteringContext = react_1.default.createContext(null);
30
- const ExitingContext = react_1.default.createContext(null);
29
+ exports.EnteringContext = react_1.default.createContext(null);
30
+ exports.ExitingContext = react_1.default.createContext(null);
31
31
  const WrapInEnteringProgressContext = ({ presentationProgress, children }) => {
32
32
  const value = (0, react_1.useMemo)(() => {
33
33
  return {
34
34
  enteringProgress: presentationProgress,
35
35
  };
36
36
  }, [presentationProgress]);
37
- return ((0, jsx_runtime_1.jsx)(EnteringContext.Provider, { value: value, children: children }));
37
+ return ((0, jsx_runtime_1.jsx)(exports.EnteringContext.Provider, { value: value, children: children }));
38
38
  };
39
39
  exports.WrapInEnteringProgressContext = WrapInEnteringProgressContext;
40
40
  const WrapInExitingProgressContext = ({ presentationProgress, children }) => {
@@ -43,27 +43,6 @@ const WrapInExitingProgressContext = ({ presentationProgress, children }) => {
43
43
  exitingProgress: presentationProgress,
44
44
  };
45
45
  }, [presentationProgress]);
46
- return ((0, jsx_runtime_1.jsx)(ExitingContext.Provider, { value: value, children: children }));
46
+ return ((0, jsx_runtime_1.jsx)(exports.ExitingContext.Provider, { value: value, children: children }));
47
47
  };
48
48
  exports.WrapInExitingProgressContext = WrapInExitingProgressContext;
49
- /**
50
- * Gets the progress and direction of a transition with a context() presentation.
51
- */
52
- const useTransitionProgress = () => {
53
- var _a, _b;
54
- const entering = react_1.default.useContext(EnteringContext);
55
- const exiting = react_1.default.useContext(ExitingContext);
56
- if (!entering && !exiting) {
57
- return {
58
- isInTransitionSeries: false,
59
- entering: 1,
60
- exiting: 0,
61
- };
62
- }
63
- return {
64
- isInTransitionSeries: true,
65
- entering: (_a = entering === null || entering === void 0 ? void 0 : entering.enteringProgress) !== null && _a !== void 0 ? _a : 1,
66
- exiting: (_b = exiting === null || exiting === void 0 ? void 0 : exiting.exitingProgress) !== null && _b !== void 0 ? _b : 0,
67
- };
68
- };
69
- exports.useTransitionProgress = useTransitionProgress;
@@ -127,16 +127,46 @@ var springTiming = (options = {}) => {
127
127
  };
128
128
 
129
129
  // src/TransitionSeries.tsx
130
- import {Children, useMemo as useMemo2} from "react";
130
+ import {Children, useMemo as useMemo3} from "react";
131
131
  import {Internals, Sequence, useCurrentFrame, useVideoConfig} from "remotion";
132
132
  import {NoReactInternals as NoReactInternals2} from "remotion/no-react";
133
133
 
134
+ // src/context.tsx
135
+ import React2, {useMemo as useMemo2} from "react";
136
+ import {
137
+ jsx as jsx2
138
+ } from "react/jsx-runtime";
139
+ var EnteringContext = React2.createContext(null);
140
+ var ExitingContext = React2.createContext(null);
141
+ var WrapInEnteringProgressContext = ({ presentationProgress, children }) => {
142
+ const value = useMemo2(() => {
143
+ return {
144
+ enteringProgress: presentationProgress
145
+ };
146
+ }, [presentationProgress]);
147
+ return jsx2(EnteringContext.Provider, {
148
+ value,
149
+ children
150
+ });
151
+ };
152
+ var WrapInExitingProgressContext = ({ presentationProgress, children }) => {
153
+ const value = useMemo2(() => {
154
+ return {
155
+ exitingProgress: presentationProgress
156
+ };
157
+ }, [presentationProgress]);
158
+ return jsx2(ExitingContext.Provider, {
159
+ value,
160
+ children
161
+ });
162
+ };
163
+
134
164
  // src/flatten-children.ts
135
- import React2 from "react";
165
+ import React3 from "react";
136
166
  var flattenChildren = (children) => {
137
- const childrenArray = React2.Children.toArray(children);
167
+ const childrenArray = React3.Children.toArray(children);
138
168
  return childrenArray.reduce((flatChildren, child) => {
139
- if (child.type === React2.Fragment) {
169
+ if (child.type === React3.Fragment) {
140
170
  return flatChildren.concat(flattenChildren(child.props.children));
141
171
  }
142
172
  flatChildren.push(child);
@@ -150,14 +180,14 @@ var validateDurationInFrames = NoReactInternals.validateDurationInFrames;
150
180
 
151
181
  // src/TransitionSeries.tsx
152
182
  import {
153
- jsx as jsx2,
183
+ jsx as jsx3,
154
184
  Fragment
155
185
  } from "react/jsx-runtime";
156
186
  var TransitionSeriesTransition = function(_props) {
157
187
  return null;
158
188
  };
159
189
  var SeriesSequence = ({ children }) => {
160
- return jsx2(Fragment, {
190
+ return jsx3(Fragment, {
161
191
  children
162
192
  });
163
193
  };
@@ -166,7 +196,7 @@ var TransitionSeriesChildren = ({
166
196
  }) => {
167
197
  const { fps } = useVideoConfig();
168
198
  const frame = useCurrentFrame();
169
- const childrenValue = useMemo2(() => {
199
+ const childrenValue = useMemo3(() => {
170
200
  let transitionOffsets = 0;
171
201
  let startFrame = 0;
172
202
  const flattedChildren = flattenChildren(children);
@@ -250,22 +280,28 @@ var TransitionSeriesChildren = ({
250
280
  const prevPresentation = prev.props.presentation ?? slide();
251
281
  const UppercaseNextPresentation = nextPresentation.component;
252
282
  const UppercasePrevPresentation = prevPresentation.component;
253
- return jsx2(Sequence, {
283
+ return jsx3(Sequence, {
254
284
  from: Math.floor(actualStartFrame),
255
285
  durationInFrames: durationInFramesProp,
256
286
  ...passedProps,
257
287
  name: passedProps.name || "<TS.Sequence>",
258
- children: jsx2(UppercaseNextPresentation, {
288
+ children: jsx3(UppercaseNextPresentation, {
259
289
  passedProps: nextPresentation.props ?? {},
260
290
  presentationDirection: "exiting",
261
291
  presentationProgress: nextProgress,
262
292
  presentationDurationInFrames: next.props.timing.getDurationInFrames({ fps }),
263
- children: jsx2(UppercasePrevPresentation, {
264
- passedProps: prevPresentation.props ?? {},
265
- presentationDirection: "entering",
266
- presentationProgress: prevProgress,
267
- presentationDurationInFrames: prev.props.timing.getDurationInFrames({ fps }),
268
- children: child
293
+ children: jsx3(WrapInExitingProgressContext, {
294
+ presentationProgress: nextProgress,
295
+ children: jsx3(UppercasePrevPresentation, {
296
+ passedProps: prevPresentation.props ?? {},
297
+ presentationDirection: "entering",
298
+ presentationProgress: prevProgress,
299
+ presentationDurationInFrames: prev.props.timing.getDurationInFrames({ fps }),
300
+ children: jsx3(WrapInEnteringProgressContext, {
301
+ presentationProgress: prevProgress,
302
+ children: child
303
+ })
304
+ })
269
305
  })
270
306
  })
271
307
  }, i);
@@ -273,38 +309,44 @@ var TransitionSeriesChildren = ({
273
309
  if (prevProgress !== null && prev) {
274
310
  const prevPresentation = prev.props.presentation ?? slide();
275
311
  const UppercasePrevPresentation = prevPresentation.component;
276
- return jsx2(Sequence, {
312
+ return jsx3(Sequence, {
277
313
  from: Math.floor(actualStartFrame),
278
314
  durationInFrames: durationInFramesProp,
279
315
  ...passedProps,
280
316
  name: passedProps.name || "<TS.Sequence>",
281
- children: jsx2(UppercasePrevPresentation, {
317
+ children: jsx3(UppercasePrevPresentation, {
282
318
  passedProps: prevPresentation.props ?? {},
283
319
  presentationDirection: "entering",
284
320
  presentationProgress: prevProgress,
285
321
  presentationDurationInFrames: prev.props.timing.getDurationInFrames({ fps }),
286
- children: child
322
+ children: jsx3(WrapInEnteringProgressContext, {
323
+ presentationProgress: prevProgress,
324
+ children: child
325
+ })
287
326
  })
288
327
  }, i);
289
328
  }
290
329
  if (nextProgress !== null && next) {
291
330
  const nextPresentation = next.props.presentation ?? slide();
292
331
  const UppercaseNextPresentation = nextPresentation.component;
293
- return jsx2(Sequence, {
332
+ return jsx3(Sequence, {
294
333
  from: Math.floor(actualStartFrame),
295
334
  durationInFrames: durationInFramesProp,
296
335
  ...passedProps,
297
336
  name: passedProps.name || "<TS.Sequence>",
298
- children: jsx2(UppercaseNextPresentation, {
337
+ children: jsx3(UppercaseNextPresentation, {
299
338
  passedProps: nextPresentation.props ?? {},
300
339
  presentationDirection: "exiting",
301
340
  presentationProgress: nextProgress,
302
341
  presentationDurationInFrames: next.props.timing.getDurationInFrames({ fps }),
303
- children: child
342
+ children: jsx3(WrapInExitingProgressContext, {
343
+ presentationProgress: nextProgress,
344
+ children: child
345
+ })
304
346
  })
305
347
  }, i);
306
348
  }
307
- return jsx2(Sequence, {
349
+ return jsx3(Sequence, {
308
350
  from: Math.floor(actualStartFrame),
309
351
  durationInFrames: durationInFramesProp,
310
352
  ...passedProps,
@@ -313,7 +355,7 @@ var TransitionSeriesChildren = ({
313
355
  }, i);
314
356
  });
315
357
  }, [children, fps, frame]);
316
- return jsx2(Fragment, {
358
+ return jsx3(Fragment, {
317
359
  children: childrenValue
318
360
  });
319
361
  };
@@ -323,11 +365,11 @@ var TransitionSeries = ({ children, name, layout: passedLayout, ...otherProps })
323
365
  if (NoReactInternals2.ENABLE_V5_BREAKING_CHANGES && layout !== "absolute-fill") {
324
366
  throw new TypeError(`The "layout" prop of <TransitionSeries /> is not supported anymore in v5. TransitionSeries' must be absolutely positioned.`);
325
367
  }
326
- return jsx2(Sequence, {
368
+ return jsx3(Sequence, {
327
369
  name: displayName,
328
370
  layout,
329
371
  ...otherProps,
330
- children: jsx2(TransitionSeriesChildren, {
372
+ children: jsx3(TransitionSeriesChildren, {
331
373
  children
332
374
  })
333
375
  });
@@ -336,7 +378,27 @@ TransitionSeries.Sequence = SeriesSequence;
336
378
  TransitionSeries.Transition = TransitionSeriesTransition;
337
379
  Internals.addSequenceStackTraces(TransitionSeries);
338
380
  Internals.addSequenceStackTraces(SeriesSequence);
381
+
382
+ // src/use-transition-progress.ts
383
+ import React4 from "react";
384
+ var useTransitionProgress = () => {
385
+ const entering = React4.useContext(EnteringContext);
386
+ const exiting = React4.useContext(ExitingContext);
387
+ if (!entering && !exiting) {
388
+ return {
389
+ isInTransitionSeries: false,
390
+ entering: 1,
391
+ exiting: 0
392
+ };
393
+ }
394
+ return {
395
+ isInTransitionSeries: true,
396
+ entering: entering?.enteringProgress ?? 1,
397
+ exiting: exiting?.exitingProgress ?? 0
398
+ };
399
+ };
339
400
  export {
401
+ useTransitionProgress,
340
402
  springTiming,
341
403
  linearTiming,
342
404
  TransitionSeries
@@ -0,0 +1,26 @@
1
+ // src/presentations/none.tsx
2
+ import {useMemo} from "react";
3
+ import {AbsoluteFill} from "remotion";
4
+ import {
5
+ jsx
6
+ } from "react/jsx-runtime";
7
+ var NonePresentation = ({ children, presentationDirection, passedProps }) => {
8
+ const style = useMemo(() => {
9
+ return {
10
+ ...presentationDirection === "entering" ? passedProps.enterStyle : passedProps.exitStyle
11
+ };
12
+ }, [passedProps.enterStyle, passedProps.exitStyle, presentationDirection]);
13
+ return jsx(AbsoluteFill, {
14
+ style,
15
+ children
16
+ });
17
+ };
18
+ var none = (props) => {
19
+ return {
20
+ component: NonePresentation,
21
+ props: props ?? {}
22
+ };
23
+ };
24
+ export {
25
+ none
26
+ };
package/dist/index.d.ts CHANGED
@@ -2,3 +2,4 @@ export { linearTiming } from './timings/linear-timing.js';
2
2
  export { springTiming } from './timings/spring-timing.js';
3
3
  export { TransitionSeries } from './TransitionSeries.js';
4
4
  export { TransitionPresentation, TransitionPresentationComponentProps, TransitionTiming, } from './types.js';
5
+ export { TransitionState, useTransitionProgress, } from './use-transition-progress.js';
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TransitionSeries = exports.springTiming = exports.linearTiming = void 0;
3
+ exports.useTransitionProgress = exports.TransitionSeries = exports.springTiming = exports.linearTiming = void 0;
4
4
  // Timings
5
5
  var linear_timing_js_1 = require("./timings/linear-timing.js");
6
6
  Object.defineProperty(exports, "linearTiming", { enumerable: true, get: function () { return linear_timing_js_1.linearTiming; } });
@@ -9,3 +9,6 @@ Object.defineProperty(exports, "springTiming", { enumerable: true, get: function
9
9
  // Component
10
10
  var TransitionSeries_js_1 = require("./TransitionSeries.js");
11
11
  Object.defineProperty(exports, "TransitionSeries", { enumerable: true, get: function () { return TransitionSeries_js_1.TransitionSeries; } });
12
+ // Hooks
13
+ var use_transition_progress_js_1 = require("./use-transition-progress.js");
14
+ Object.defineProperty(exports, "useTransitionProgress", { enumerable: true, get: function () { return use_transition_progress_js_1.useTransitionProgress; } });
@@ -10,4 +10,4 @@ export type NoneProps = {
10
10
  * @param {NoneProps} [props] Optional properties to define 'enterStyle' and 'exitStyle'.
11
11
  * @returns {TransitionPresentation<NoneProps>} The transition presentation component setup.
12
12
  */
13
- export declare const context: (props?: NoneProps) => TransitionPresentation<NoneProps>;
13
+ export declare const none: (props?: NoneProps) => TransitionPresentation<NoneProps>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.context = void 0;
3
+ exports.none = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const remotion_1 = require("remotion");
@@ -20,10 +20,10 @@ const NonePresentation = ({ children, presentationDirection, passedProps }) => {
20
20
  * @param {NoneProps} [props] Optional properties to define 'enterStyle' and 'exitStyle'.
21
21
  * @returns {TransitionPresentation<NoneProps>} The transition presentation component setup.
22
22
  */
23
- const context = (props) => {
23
+ const none = (props) => {
24
24
  return {
25
25
  component: NonePresentation,
26
26
  props: props !== null && props !== void 0 ? props : {},
27
27
  };
28
28
  };
29
- exports.context = context;
29
+ exports.none = none;
@@ -0,0 +1,9 @@
1
+ export type TransitionState = {
2
+ entering: number;
3
+ exiting: number;
4
+ isInTransitionSeries: boolean;
5
+ };
6
+ /**
7
+ * Gets the progress and direction of a transition with a context() presentation.
8
+ */
9
+ export declare const useTransitionProgress: () => TransitionState;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.useTransitionProgress = void 0;
7
+ const react_1 = __importDefault(require("react"));
8
+ const context_1 = require("./context");
9
+ /**
10
+ * Gets the progress and direction of a transition with a context() presentation.
11
+ */
12
+ const useTransitionProgress = () => {
13
+ var _a, _b;
14
+ const entering = react_1.default.useContext(context_1.EnteringContext);
15
+ const exiting = react_1.default.useContext(context_1.ExitingContext);
16
+ if (!entering && !exiting) {
17
+ return {
18
+ isInTransitionSeries: false,
19
+ entering: 1,
20
+ exiting: 0,
21
+ };
22
+ }
23
+ return {
24
+ isInTransitionSeries: true,
25
+ entering: (_a = entering === null || entering === void 0 ? void 0 : entering.enteringProgress) !== null && _a !== void 0 ? _a : 1,
26
+ exiting: (_b = exiting === null || exiting === void 0 ? void 0 : exiting.exitingProgress) !== null && _b !== void 0 ? _b : 0,
27
+ };
28
+ };
29
+ exports.useTransitionProgress = useTransitionProgress;
package/none.js ADDED
@@ -0,0 +1,2 @@
1
+ // For backwards compatibility when you use `esm-wallaby`
2
+ module.exports = require('./dist/presentations/none.js');
package/package.json CHANGED
@@ -1,7 +1,10 @@
1
1
  {
2
+ "repository": {
3
+ "url": "https://github.com/remotion-dev/remotion/tree/main/packages/transitions"
4
+ },
2
5
  "name": "@remotion/transitions",
3
- "version": "4.0.177",
4
- "description": "Transition presets for Remotion",
6
+ "version": "4.0.179",
7
+ "description": "Library for creating transitions in Remotion",
5
8
  "sideEffects": false,
6
9
  "main": "dist/esm/index.mjs",
7
10
  "module": "dist/esm/index.js",
@@ -9,31 +12,21 @@
9
12
  "author": "Jonny Burger",
10
13
  "contributors": [],
11
14
  "license": "UNLICENSED",
12
- "repository": {
13
- "url": "https://github.com/remotion-dev/remotion"
14
- },
15
15
  "bugs": {
16
16
  "url": "https://github.com/remotion-dev/remotion/issues"
17
17
  },
18
18
  "dependencies": {
19
- "remotion": "4.0.177",
20
- "@remotion/shapes": "4.0.177",
21
- "@remotion/paths": "4.0.177"
19
+ "remotion": "4.0.179",
20
+ "@remotion/paths": "4.0.179",
21
+ "@remotion/shapes": "4.0.179"
22
22
  },
23
23
  "devDependencies": {
24
- "@jonny/eslint-config": "3.0.281",
25
- "eslint": "8.56.0",
26
- "prettier": "3.2.5",
27
- "prettier-plugin-organize-imports": "3.2.4",
24
+ "@happy-dom/global-registrator": "14.5.1",
28
25
  "react": "18.3.1",
29
26
  "react-dom": "18.3.1",
30
- "vitest": "0.31.1",
31
- "@types/react": "18.3.1",
32
- "@types/react-dom": "18.3.0",
33
- "@types/bun": "1.0.12",
34
27
  "@vitejs/plugin-react": "^2.0.0",
35
- "remotion": "4.0.177",
36
- "@remotion/test-utils": "4.0.177"
28
+ "remotion": "4.0.179",
29
+ "@remotion/test-utils": "4.0.179"
37
30
  },
38
31
  "peerDependencies": {
39
32
  "react": ">=16.8.0",
@@ -83,6 +76,12 @@
83
76
  "require": "./dist/presentations/clock-wipe.js",
84
77
  "types": "./dist/presentations/clock-wipe.d.ts"
85
78
  },
79
+ "./none": {
80
+ "module": "./dist/esm/none.mjs",
81
+ "import": "./dist/esm/none.mjs",
82
+ "require": "./dist/presentations/none.js",
83
+ "types": "./dist/presentations/none.d.ts"
84
+ },
86
85
  "./package.json": "./package.json"
87
86
  },
88
87
  "typesVersions": {
@@ -99,13 +98,17 @@
99
98
  "fade": [
100
99
  "dist/presentations/fade.d.ts"
101
100
  ],
101
+ "none": [
102
+ "dist/presentations/none.d.ts"
103
+ ],
102
104
  "clock-wipe": [
103
105
  "dist/presentations/clock-wipe.d.ts"
104
106
  ]
105
107
  }
106
108
  },
109
+ "homepage": "https://www.remotion.dev/transitions",
107
110
  "scripts": {
108
- "test": "vitest src --run",
111
+ "test": "bun test src",
109
112
  "lint": "eslint src --ext ts,tsx",
110
113
  "formatting": "prettier src --check",
111
114
  "build": "bun --env-file=../.env.bundle bundle.ts"
package/.prettierrc.js DELETED
@@ -1,14 +0,0 @@
1
- module.exports = {
2
- singleQuote: true,
3
- bracketSpacing: false,
4
- useTabs: true,
5
- overrides: [
6
- {
7
- files: ['*.yml'],
8
- options: {
9
- singleQuote: false,
10
- },
11
- },
12
- ],
13
- plugins: [require.resolve('prettier-plugin-organize-imports')],
14
- };
@@ -1,44 +0,0 @@
1
- // src/presentations/context.tsx
2
- import React, {useMemo} from "react";
3
- import {AbsoluteFill} from "remotion";
4
- import {
5
- jsx
6
- } from "react/jsx-runtime";
7
- var ContextPresentationContext = React.createContext(null);
8
- var ContextPresentation = ({ children, presentationDirection, presentationProgress, passedProps }) => {
9
- const style = useMemo(() => {
10
- return {
11
- ...presentationDirection === "entering" ? passedProps.enterStyle : passedProps.exitStyle
12
- };
13
- }, [passedProps.enterStyle, passedProps.exitStyle, presentationDirection]);
14
- const value = useMemo(() => {
15
- return {
16
- progress: presentationProgress,
17
- direction: presentationDirection
18
- };
19
- }, [presentationDirection, presentationProgress]);
20
- return jsx(ContextPresentationContext.Provider, {
21
- value,
22
- children: jsx(AbsoluteFill, {
23
- style,
24
- children
25
- })
26
- });
27
- };
28
- var context = (props) => {
29
- return {
30
- component: ContextPresentation,
31
- props: props ?? {}
32
- };
33
- };
34
- var useTransitionContext = () => {
35
- const value = React.useContext(ContextPresentationContext);
36
- if (!value) {
37
- return null;
38
- }
39
- return value;
40
- };
41
- export {
42
- useTransitionContext,
43
- context
44
- };
package/vitest.config.mts DELETED
@@ -1,11 +0,0 @@
1
- import react from '@vitejs/plugin-react';
2
- import {defineConfig} from 'vitest/config';
3
-
4
- export default defineConfig({
5
- test: {
6
- testTimeout: 90000,
7
- maxConcurrency: 1,
8
- threads: false,
9
- },
10
- plugins: [react()],
11
- });