remotion 4.0.460 → 4.0.462

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 (53) hide show
  1. package/dist/cjs/CompositionManager.d.ts +2 -2
  2. package/dist/cjs/HtmlInCanvas.d.ts +3 -1
  3. package/dist/cjs/HtmlInCanvas.js +15 -6
  4. package/dist/cjs/RemotionRoot.d.ts +0 -1
  5. package/dist/cjs/RemotionRoot.js +2 -2
  6. package/dist/cjs/Sequence.d.ts +2 -2
  7. package/dist/cjs/Sequence.js +3 -6
  8. package/dist/cjs/SequenceManager.d.ts +40 -19
  9. package/dist/cjs/SequenceManager.js +78 -46
  10. package/dist/cjs/bezier.js +5 -4
  11. package/dist/cjs/delete-nested-key.d.ts +1 -0
  12. package/dist/cjs/delete-nested-key.js +36 -0
  13. package/dist/cjs/easing.js +14 -8
  14. package/dist/cjs/effects/Solid.js +8 -2
  15. package/dist/cjs/effects/create-effect.d.ts +4 -0
  16. package/dist/cjs/effects/create-effect.js +24 -0
  17. package/dist/cjs/effects/define-effect.js +4 -1
  18. package/dist/cjs/effects/effect-internals.d.ts +3 -4
  19. package/dist/cjs/effects/effect-internals.js +1 -18
  20. package/dist/cjs/effects/effect-types.d.ts +16 -5
  21. package/dist/cjs/effects/index.d.ts +1 -1
  22. package/dist/cjs/effects/run-effect-chain.d.ts +2 -2
  23. package/dist/cjs/effects/run-effect-chain.js +1 -2
  24. package/dist/cjs/effects/use-memoized-effects.d.ts +27 -2
  25. package/dist/cjs/effects/use-memoized-effects.js +126 -7
  26. package/dist/cjs/find-props-to-delete.d.ts +6 -0
  27. package/dist/cjs/find-props-to-delete.js +37 -0
  28. package/dist/cjs/flatten-schema.js +4 -1
  29. package/dist/cjs/get-effective-visual-mode-value.d.ts +3 -4
  30. package/dist/cjs/get-effective-visual-mode-value.js +1 -7
  31. package/dist/cjs/index.d.ts +3 -3
  32. package/dist/cjs/index.js +3 -1
  33. package/dist/cjs/internals.d.ts +73 -14
  34. package/dist/cjs/internals.js +14 -7
  35. package/dist/cjs/interpolate.d.ts +2 -1
  36. package/dist/cjs/interpolate.js +32 -3
  37. package/dist/cjs/no-react.d.ts +66 -3
  38. package/dist/cjs/no-react.js +6 -1
  39. package/dist/cjs/sequence-field-schema.d.ts +42 -1
  40. package/dist/cjs/sequence-field-schema.js +16 -0
  41. package/dist/cjs/sequence-node-path.d.ts +3 -3
  42. package/dist/cjs/use-schema.d.ts +14 -7
  43. package/dist/cjs/use-schema.js +31 -8
  44. package/dist/cjs/version.d.ts +1 -1
  45. package/dist/cjs/version.js +1 -1
  46. package/dist/cjs/wrap-in-schema.d.ts +2 -1
  47. package/dist/cjs/wrap-in-schema.js +17 -15
  48. package/dist/esm/index.mjs +621 -339
  49. package/dist/esm/no-react.mjs +132 -3
  50. package/dist/esm/version.mjs +1 -1
  51. package/package.json +2 -2
  52. package/dist/cjs/use-sequence-control-override.d.ts +0 -1
  53. package/dist/cjs/use-sequence-control-override.js +0 -16
@@ -3,7 +3,7 @@ import React from 'react';
3
3
  import type { AnyZodObject } from './any-zod-type.js';
4
4
  import type { CalculateMetadataFunction } from './Composition.js';
5
5
  import type { DownloadBehavior } from './download-behavior.js';
6
- import type { EffectDefinitionAndStack } from './effects/effect-types.js';
6
+ import type { EffectDefinition } from './effects/effect-types.js';
7
7
  import type { NonceHistory } from './nonce.js';
8
8
  import type { InferProps, PropsIfHasProps } from './props-if-has-props.js';
9
9
  import type { SequenceSchema } from './sequence-field-schema.js';
@@ -69,7 +69,7 @@ export type TSequence = {
69
69
  premountDisplay: number | null;
70
70
  postmountDisplay: number | null;
71
71
  controls: SequenceControls | null;
72
- effects: EffectDefinitionAndStack<unknown>[];
72
+ effects: readonly EffectDefinition<unknown>[];
73
73
  } & EnhancedTSequenceData;
74
74
  export type AudioOrVideoAsset = {
75
75
  type: 'audio' | 'video';
@@ -42,10 +42,12 @@ export type HtmlInCanvasOnPaintParams = {
42
42
  readonly elementImage: ElementImage;
43
43
  };
44
44
  export declare const isHtmlInCanvasSupported: () => boolean;
45
+ /** Shown when {@link isHtmlInCanvasSupported} is false: APIs are absent (old Chrome and/or flag off). */
46
+ export declare const HTML_IN_CANVAS_UNSUPPORTED_MESSAGE = "HTML in Canvas is not supported. Two common causes: Chrome is older than version 148 (update Chrome), or the HTML-in-Canvas flag is disabled at chrome://flags/#canvas-draw-element (enable it and restart Chrome).";
45
47
  export type HtmlInCanvasOnPaint = (params: HtmlInCanvasOnPaintParams) => void | Promise<void>;
46
48
  export type HtmlInCanvasOnInitCleanup = () => void;
47
49
  export type HtmlInCanvasOnInit = (params: HtmlInCanvasOnPaintParams) => HtmlInCanvasOnInitCleanup | Promise<HtmlInCanvasOnInitCleanup>;
48
- export type HtmlInCanvasProps = Omit<SequenceProps, 'children' | 'durationInFrames' | keyof LayoutAndStyle> & Omit<AbsoluteFillLayout, 'layout' | 'styleWhilePostmounted' | 'postmountFor' | 'premountFor' | 'styleWhilePremounted'> & {
50
+ export type HtmlInCanvasProps = Omit<SequenceProps, 'children' | 'durationInFrames' | keyof LayoutAndStyle | '_experimentalEffects'> & Omit<AbsoluteFillLayout, 'layout' | 'styleWhilePostmounted' | 'postmountFor' | 'premountFor' | 'styleWhilePremounted'> & {
49
51
  readonly durationInFrames?: number;
50
52
  readonly width: number;
51
53
  readonly height: number;
@@ -1,11 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.HtmlInCanvas = exports.isHtmlInCanvasSupported = void 0;
3
+ exports.HtmlInCanvas = exports.HTML_IN_CANVAS_UNSUPPORTED_MESSAGE = exports.isHtmlInCanvasSupported = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const delay_render_js_1 = require("./delay-render.js");
7
7
  const run_effect_chain_js_1 = require("./effects/run-effect-chain.js");
8
8
  const use_effect_chain_state_js_1 = require("./effects/use-effect-chain-state.js");
9
+ const use_memoized_effects_js_1 = require("./effects/use-memoized-effects.js");
9
10
  const enable_sequence_stack_traces_js_1 = require("./enable-sequence-stack-traces.js");
10
11
  const sequence_field_schema_js_1 = require("./sequence-field-schema.js");
11
12
  const Sequence_js_1 = require("./Sequence.js");
@@ -33,6 +34,8 @@ const isHtmlInCanvasSupported = () => {
33
34
  return cachedSupport;
34
35
  };
35
36
  exports.isHtmlInCanvasSupported = isHtmlInCanvasSupported;
37
+ /** Shown when {@link isHtmlInCanvasSupported} is false: APIs are absent (old Chrome and/or flag off). */
38
+ exports.HTML_IN_CANVAS_UNSUPPORTED_MESSAGE = 'HTML in Canvas is not supported. Two common causes: Chrome is older than version 148 (update Chrome), or the HTML-in-Canvas flag is disabled at chrome://flags/#canvas-draw-element (enable it and restart Chrome).';
36
39
  function assertHtmlInCanvasDimensions(width, height) {
37
40
  if (typeof width !== 'number' || typeof height !== 'number') {
38
41
  throw new Error(`HtmlInCanvas: \`width\` and \`height\` must be numbers. Received width=${String(width)}, height=${String(height)}.`);
@@ -56,11 +59,12 @@ const defaultOnPaint = ({ canvas, element, elementImage, }) => {
56
59
  /* eslint-enable react/require-default-props */
57
60
  const HtmlInCanvasAncestorContext = (0, react_1.createContext)(false);
58
61
  const HtmlInCanvasInner = (0, react_1.forwardRef)(({ width, height, _experimentalEffects: effects = [], children, onPaint, onInit, _experimentalControls: controls, style, durationInFrames, ...sequenceProps }, ref) => {
62
+ var _a;
59
63
  const isInsideAncestorHtmlInCanvas = (0, react_1.useContext)(HtmlInCanvasAncestorContext);
60
64
  assertHtmlInCanvasDimensions(width, height);
61
65
  const { continueRender, cancelRender } = (0, use_delay_render_js_1.useDelayRender)();
62
66
  if (!(0, exports.isHtmlInCanvasSupported)()) {
63
- cancelRender(new Error('HTML in Canvas is not supported. Open this page in Chrome Canary with chrome://flags/#canvas-draw-element enabled.'));
67
+ cancelRender(new Error(exports.HTML_IN_CANVAS_UNSUPPORTED_MESSAGE));
64
68
  }
65
69
  const { durationInFrames: videoDuration } = (0, use_video_config_js_1.useVideoConfig)();
66
70
  const resolvedDuration = durationInFrames !== null && durationInFrames !== void 0 ? durationInFrames : videoDuration;
@@ -79,9 +83,14 @@ const HtmlInCanvasInner = (0, react_1.forwardRef)(({ width, height, _experimenta
79
83
  }, [ref]);
80
84
  const [offscreenCanvas] = (0, react_1.useState)(() => new OffscreenCanvas(1, 1));
81
85
  const chainState = (0, use_effect_chain_state_js_1.useEffectChainState)();
86
+ const memoizedEffects = (0, use_memoized_effects_js_1.useMemoizedEffects)({
87
+ effects,
88
+ overrideId: (_a = controls === null || controls === void 0 ? void 0 : controls.overrideId) !== null && _a !== void 0 ? _a : null,
89
+ });
90
+ const memoizedEffectDefinitions = (0, use_memoized_effects_js_1.useMemoizedEffectDefinitions)(effects);
82
91
  // Refs so the paint handler always reads fresh values.
83
- const effectsRef = (0, react_1.useRef)(effects);
84
- effectsRef.current = effects;
92
+ const effectsRef = (0, react_1.useRef)(memoizedEffects);
93
+ effectsRef.current = memoizedEffects;
85
94
  const frameRef = (0, react_1.useRef)(frame);
86
95
  frameRef.current = frame;
87
96
  const onPaintRef = (0, react_1.useRef)(onPaint);
@@ -198,7 +207,7 @@ const HtmlInCanvasInner = (0, react_1.forwardRef)(({ width, height, _experimenta
198
207
  return;
199
208
  }
200
209
  (_a = canvas.requestPaint) === null || _a === void 0 ? void 0 : _a.call(canvas);
201
- }, [onPaint]);
210
+ }, [onPaint, memoizedEffects]);
202
211
  (0, react_1.useLayoutEffect)(() => {
203
212
  const canvas = canvas2dRef.current;
204
213
  if (!canvas) {
@@ -221,7 +230,7 @@ const HtmlInCanvasInner = (0, react_1.forwardRef)(({ width, height, _experimenta
221
230
  if (isInsideAncestorHtmlInCanvas) {
222
231
  throw new Error('<HtmlInCanvas> effects cannot be nested together. Chrome will only display the outer effect. Consider merging the effects into one if you can.');
223
232
  }
224
- return ((0, jsx_runtime_1.jsx)(Sequence_js_1.Sequence, { durationInFrames: resolvedDuration, name: "<HtmlInCanvas>", _experimentalControls: controls, _experimentalEffects: effects, layout: "none", ...sequenceProps, children: (0, jsx_runtime_1.jsx)(HtmlInCanvasAncestorContext.Provider, { value: true, children: (0, jsx_runtime_1.jsx)("canvas", { ref: setLayoutCanvasRef, width: width, height: height, style: style, children: (0, jsx_runtime_1.jsx)("div", { ref: divRef, style: innerStyle, children: children }) }) }) }));
233
+ return ((0, jsx_runtime_1.jsx)(Sequence_js_1.Sequence, { durationInFrames: resolvedDuration, name: "<HtmlInCanvas>", _experimentalControls: controls, _experimentalEffects: memoizedEffectDefinitions, layout: "none", ...sequenceProps, children: (0, jsx_runtime_1.jsx)(HtmlInCanvasAncestorContext.Provider, { value: true, children: (0, jsx_runtime_1.jsx)("canvas", { ref: setLayoutCanvasRef, width: width, height: height, style: style, children: (0, jsx_runtime_1.jsx)("div", { ref: divRef, style: innerStyle, children: children }) }) }) }));
225
234
  });
226
235
  HtmlInCanvasInner.displayName = 'HtmlInCanvas';
227
236
  const HtmlInCanvasWrapped = (0, wrap_in_schema_js_1.wrapInSchema)(HtmlInCanvasInner, sequence_field_schema_js_1.sequenceStyleSchema);
@@ -8,5 +8,4 @@ export declare const RemotionRootContexts: React.FC<{
8
8
  readonly videoEnabled: boolean;
9
9
  readonly audioEnabled: boolean;
10
10
  readonly frameState: Record<string, number> | null;
11
- readonly visualModeEnabled: boolean;
12
11
  }>;
@@ -13,7 +13,7 @@ const SequenceManager_js_1 = require("./SequenceManager.js");
13
13
  const TimelineContext_js_1 = require("./TimelineContext.js");
14
14
  const use_media_enabled_js_1 = require("./use-media-enabled.js");
15
15
  const duration_state_js_1 = require("./video/duration-state.js");
16
- const RemotionRootContexts = ({ children, numberOfAudioTags, logLevel, audioLatencyHint, videoEnabled, audioEnabled, frameState, visualModeEnabled, }) => {
16
+ const RemotionRootContexts = ({ children, numberOfAudioTags, logLevel, audioLatencyHint, videoEnabled, audioEnabled, frameState, }) => {
17
17
  const nonceContext = (0, react_1.useMemo)(() => {
18
18
  let counter = 0;
19
19
  return {
@@ -23,6 +23,6 @@ const RemotionRootContexts = ({ children, numberOfAudioTags, logLevel, audioLate
23
23
  const logging = (0, react_1.useMemo)(() => {
24
24
  return { logLevel, mountTime: Date.now() };
25
25
  }, [logLevel]);
26
- return ((0, jsx_runtime_1.jsx)(log_level_context_js_1.LogLevelContext.Provider, { value: logging, children: (0, jsx_runtime_1.jsx)(nonce_js_1.NonceContext.Provider, { value: nonceContext, children: (0, jsx_runtime_1.jsx)(TimelineContext_js_1.TimelineContextProvider, { frameState: frameState, children: (0, jsx_runtime_1.jsx)(use_media_enabled_js_1.MediaEnabledProvider, { videoEnabled: videoEnabled, audioEnabled: audioEnabled, children: (0, jsx_runtime_1.jsx)(EditorProps_js_1.EditorPropsProvider, { children: (0, jsx_runtime_1.jsx)(prefetch_state_js_1.PrefetchProvider, { children: (0, jsx_runtime_1.jsx)(SequenceManager_js_1.SequenceManagerProvider, { visualModeEnabled: visualModeEnabled, children: (0, jsx_runtime_1.jsx)(duration_state_js_1.DurationsContextProvider, { children: (0, jsx_runtime_1.jsx)(buffering_js_1.BufferingProvider, { children: (0, jsx_runtime_1.jsx)(shared_audio_tags_js_1.SharedAudioContextProvider, { audioLatencyHint: audioLatencyHint, audioEnabled: audioEnabled, children: (0, jsx_runtime_1.jsx)(shared_audio_tags_js_1.SharedAudioTagsContextProvider, { numberOfAudioTags: numberOfAudioTags, children: children }) }) }) }) }) }) }) }) }) }) }));
26
+ return ((0, jsx_runtime_1.jsx)(log_level_context_js_1.LogLevelContext.Provider, { value: logging, children: (0, jsx_runtime_1.jsx)(nonce_js_1.NonceContext.Provider, { value: nonceContext, children: (0, jsx_runtime_1.jsx)(TimelineContext_js_1.TimelineContextProvider, { frameState: frameState, children: (0, jsx_runtime_1.jsx)(use_media_enabled_js_1.MediaEnabledProvider, { videoEnabled: videoEnabled, audioEnabled: audioEnabled, children: (0, jsx_runtime_1.jsx)(EditorProps_js_1.EditorPropsProvider, { children: (0, jsx_runtime_1.jsx)(prefetch_state_js_1.PrefetchProvider, { children: (0, jsx_runtime_1.jsx)(SequenceManager_js_1.SequenceManagerProvider, { children: (0, jsx_runtime_1.jsx)(duration_state_js_1.DurationsContextProvider, { children: (0, jsx_runtime_1.jsx)(buffering_js_1.BufferingProvider, { children: (0, jsx_runtime_1.jsx)(shared_audio_tags_js_1.SharedAudioContextProvider, { audioLatencyHint: audioLatencyHint, audioEnabled: audioEnabled, children: (0, jsx_runtime_1.jsx)(shared_audio_tags_js_1.SharedAudioTagsContextProvider, { numberOfAudioTags: numberOfAudioTags, children: children }) }) }) }) }) }) }) }) }) }) }));
27
27
  };
28
28
  exports.RemotionRootContexts = RemotionRootContexts;
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import type { LoopDisplay, SequenceControls } from './CompositionManager.js';
3
- import type { EffectsProp } from './effects/effect-types.js';
3
+ import type { EffectDefinition } from './effects/effect-types.js';
4
4
  import type { BasicMediaInTimelineReturnType } from './use-media-in-timeline.js';
5
5
  export type AbsoluteFillLayout = {
6
6
  layout?: 'absolute-fill';
@@ -22,7 +22,7 @@ export type SequencePropsWithoutDuration = {
22
22
  readonly name?: string;
23
23
  readonly showInTimeline?: boolean;
24
24
  readonly _experimentalControls?: SequenceControls;
25
- readonly _experimentalEffects?: EffectsProp;
25
+ readonly _experimentalEffects?: readonly EffectDefinition<unknown>[];
26
26
  /**
27
27
  * @deprecated For internal use only.
28
28
  */
@@ -5,8 +5,6 @@ const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  /* eslint-disable @typescript-eslint/no-use-before-define */
6
6
  const react_1 = require("react");
7
7
  const AbsoluteFill_js_1 = require("./AbsoluteFill.js");
8
- const effect_internals_js_1 = require("./effects/effect-internals.js");
9
- const use_memoized_effects_js_1 = require("./effects/use-memoized-effects.js");
10
8
  const freeze_js_1 = require("./freeze.js");
11
9
  const nonce_js_1 = require("./nonce.js");
12
10
  const PremountContext_js_1 = require("./PremountContext.js");
@@ -101,7 +99,6 @@ const RegularSequenceRefForwardingFunction = ({ from = 0, durationInFrames = Inf
101
99
  }, [name]);
102
100
  const env = (0, use_remotion_environment_js_1.useRemotionEnvironment)();
103
101
  const inheritedStack = (_a = other === null || other === void 0 ? void 0 : other.stack) !== null && _a !== void 0 ? _a : null;
104
- const memoizedEffects = (0, use_memoized_effects_js_1.useMemoizedEffects)((0, effect_internals_js_1.flattenEffects)(_experimentalEffects !== null && _experimentalEffects !== void 0 ? _experimentalEffects : []));
105
102
  (0, react_1.useEffect)(() => {
106
103
  var _a, _b;
107
104
  if (!env.isStudio) {
@@ -111,7 +108,7 @@ const RegularSequenceRefForwardingFunction = ({ from = 0, durationInFrames = Inf
111
108
  registerSequence({
112
109
  type: isMedia.type,
113
110
  controls: controls !== null && controls !== void 0 ? controls : null,
114
- effects: memoizedEffects,
111
+ effects: _experimentalEffects !== null && _experimentalEffects !== void 0 ? _experimentalEffects : [],
115
112
  displayName: timelineClipName,
116
113
  doesVolumeChange: isMedia.data.doesVolumeChange,
117
114
  duration: actualDurationInFrames,
@@ -149,7 +146,7 @@ const RegularSequenceRefForwardingFunction = ({ from = 0, durationInFrames = Inf
149
146
  premountDisplay: premountDisplay !== null && premountDisplay !== void 0 ? premountDisplay : null,
150
147
  postmountDisplay: postmountDisplay !== null && postmountDisplay !== void 0 ? postmountDisplay : null,
151
148
  controls: controls !== null && controls !== void 0 ? controls : null,
152
- effects: memoizedEffects,
149
+ effects: _experimentalEffects !== null && _experimentalEffects !== void 0 ? _experimentalEffects : [],
153
150
  });
154
151
  return () => {
155
152
  unregisterSequence(id);
@@ -174,7 +171,7 @@ const RegularSequenceRefForwardingFunction = ({ from = 0, durationInFrames = Inf
174
171
  env.isStudio,
175
172
  inheritedStack,
176
173
  controls,
177
- memoizedEffects,
174
+ _experimentalEffects,
178
175
  isMedia,
179
176
  ]);
180
177
  // Ceil to support floats
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import type { TSequence } from './CompositionManager.js';
3
- import type { CanUpdateSequencePropStatus, CodeValues, GetCodeValues, GetDragOverrides } from './use-schema.js';
3
+ import type { CanUpdateSequencePropStatus, CodeValues, GetDragOverrides, GetEffectDragOverrides } from './use-schema.js';
4
4
  export type SequenceManagerContext = {
5
5
  registerSequence: (seq: TSequence) => void;
6
6
  unregisterSequence: (id: string) => void;
@@ -13,33 +13,54 @@ export type SequenceVisibilityToggleState = {
13
13
  setHidden: React.Dispatch<React.SetStateAction<Record<string, boolean>>>;
14
14
  };
15
15
  export declare const SequenceVisibilityToggleContext: React.Context<SequenceVisibilityToggleState>;
16
- export type VisualModeGetters = {
17
- visualModeEnabled: boolean;
16
+ export type VisualModeCodeValues = {
17
+ codeValues: CodeValues;
18
+ };
19
+ export type VisualModeDragOverrides = {
18
20
  getDragOverrides: GetDragOverrides;
19
- getCodeValues: GetCodeValues;
20
- getIsJsxInMapCallback: (nodePath: SequenceNodePath) => boolean;
21
+ getEffectDragOverrides: GetEffectDragOverrides;
21
22
  };
22
23
  export type VisualModeSetters = {
23
- setDragOverrides: (nodePath: SequenceNodePath, key: string, value: unknown) => void;
24
- clearDragOverrides: (nodePath: SequenceNodePath) => void;
25
- setCodeValues: (nodePath: SequenceNodePath, values: CanUpdateSequencePropsResponse) => void;
24
+ setDragOverrides: (nodePath: SequencePropsSubscriptionKey, key: string, value: unknown) => void;
25
+ clearDragOverrides: (nodePath: SequencePropsSubscriptionKey) => void;
26
+ setEffectDragOverrides: (nodePath: SequencePropsSubscriptionKey, effectIndex: number, key: string, value: unknown) => void;
27
+ clearEffectDragOverrides: (nodePath: SequencePropsSubscriptionKey, effectIndex: number) => void;
28
+ setCodeValues: (nodePath: SequencePropsSubscriptionKey, values: (prev: CanUpdateSequencePropsResponse) => CanUpdateSequencePropsResponse) => void;
26
29
  };
27
- export type CanUpdateSequencePropsResponse = {
30
+ export type CanUpdateEffectPropsResponseTrue = {
28
31
  canUpdate: true;
32
+ callee: string;
33
+ effectIndex: number;
29
34
  props: Record<string, CanUpdateSequencePropStatus>;
30
- nodePath: SequenceNodePath;
31
- /** True when the JSX is inside a `.map()` callback (list iteration). */
32
- jsxInMapCallback: boolean;
33
- } | {
35
+ };
36
+ export type CannotUpdateEffectReason = 'not-found' | 'computed' | 'not-call-expression';
37
+ export type CannotUpdateSequenceReason = 'not-found' | 'error';
38
+ export type CanUpdateEffectPropsResponseFalse = {
39
+ canUpdate: false;
40
+ effectIndex: number;
41
+ reason: CannotUpdateEffectReason;
42
+ };
43
+ export type CanUpdateEffectPropsResponse = CanUpdateEffectPropsResponseTrue | CanUpdateEffectPropsResponseFalse;
44
+ export type CanUpdateSequencePropsResponseTrue = {
45
+ canUpdate: true;
46
+ props: Record<string, CanUpdateSequencePropStatus>;
47
+ effects: CanUpdateEffectPropsResponse[];
48
+ };
49
+ export type CanUpdateSequencePropsResponseFalse = {
34
50
  canUpdate: false;
35
- reason: string;
51
+ reason: CannotUpdateSequenceReason;
36
52
  };
37
- declare const getCodeValues: (codeValues: CodeValues, nodePath: SequenceNodePath) => Record<string, CanUpdateSequencePropStatus> | undefined;
38
- export type GetCodeValuesType = typeof getCodeValues;
39
- export declare const VisualModeGettersContext: React.Context<VisualModeGetters>;
53
+ export type CanUpdateSequencePropsResponse = CanUpdateSequencePropsResponseTrue | CanUpdateSequencePropsResponseFalse;
54
+ export declare const makeSequencePropsSubscriptionKey: (key: SequencePropsSubscriptionKey) => string;
55
+ export declare const VisualModeCodeValuesContext: React.Context<VisualModeCodeValues>;
56
+ export declare const VisualModeDragOverridesContext: React.Context<VisualModeDragOverrides>;
40
57
  export declare const VisualModeSettersContext: React.Context<VisualModeSetters>;
58
+ export type SequencePropsSubscriptionKey = {
59
+ absolutePath: string;
60
+ nodePath: SequenceNodePath;
61
+ sequenceKeys: string[];
62
+ effectKeys: string[][];
63
+ };
41
64
  export declare const SequenceManagerProvider: React.FC<{
42
65
  readonly children: React.ReactNode;
43
- readonly visualModeEnabled: boolean;
44
66
  }>;
45
- export {};
@@ -33,12 +33,9 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.SequenceManagerProvider = exports.VisualModeSettersContext = exports.VisualModeGettersContext = exports.SequenceVisibilityToggleContext = exports.SequenceManager = void 0;
36
+ exports.SequenceManagerProvider = exports.VisualModeSettersContext = exports.VisualModeDragOverridesContext = exports.VisualModeCodeValuesContext = exports.makeSequencePropsSubscriptionKey = exports.SequenceVisibilityToggleContext = exports.SequenceManager = void 0;
37
37
  const jsx_runtime_1 = require("react/jsx-runtime");
38
38
  const react_1 = __importStar(require("react"));
39
- const nodePathToString = (nodePath) => {
40
- return nodePath.join('.');
41
- };
42
39
  exports.SequenceManager = react_1.default.createContext({
43
40
  registerSequence: () => {
44
41
  throw new Error('SequenceManagerContext not initialized');
@@ -54,37 +51,20 @@ exports.SequenceVisibilityToggleContext = react_1.default.createContext({
54
51
  throw new Error('SequenceVisibilityToggle not initialized');
55
52
  },
56
53
  });
57
- const getCodeValues = (codeValues, nodePath) => {
58
- const status = codeValues[nodePathToString(nodePath)];
59
- if (!status) {
60
- return undefined;
61
- }
62
- if (!status.canUpdate) {
63
- return undefined;
64
- }
65
- return status.props;
66
- };
67
- const getIsJsxInMapCallback = (codeValues, nodePath) => {
68
- const status = codeValues[nodePathToString(nodePath)];
69
- if (!status) {
70
- return false;
71
- }
72
- if (!status.canUpdate) {
73
- return false;
74
- }
75
- return status.jsxInMapCallback;
54
+ const makeSequencePropsSubscriptionKey = (key) => {
55
+ return `${key.nodePath.join('.')}.${key.sequenceKeys.join('.')}.${key.effectKeys.map((keys) => keys.join('.')).join('.')}`;
76
56
  };
77
- exports.VisualModeGettersContext = react_1.default.createContext({
57
+ exports.makeSequencePropsSubscriptionKey = makeSequencePropsSubscriptionKey;
58
+ exports.VisualModeCodeValuesContext = react_1.default.createContext({
59
+ codeValues: {},
60
+ });
61
+ exports.VisualModeDragOverridesContext = react_1.default.createContext({
78
62
  getDragOverrides: () => {
79
- throw new Error('VisualModeGettersContext not initialized');
80
- },
81
- getCodeValues: () => {
82
- throw new Error('VisualModeGettersContext not initialized');
63
+ throw new Error('VisualModeDragOverridesContext not initialized');
83
64
  },
84
- getIsJsxInMapCallback: () => {
85
- throw new Error('VisualModeGettersContext not initialized');
65
+ getEffectDragOverrides: () => {
66
+ throw new Error('VisualModeDragOverridesContext not initialized');
86
67
  },
87
- visualModeEnabled: false,
88
68
  });
89
69
  exports.VisualModeSettersContext = react_1.default.createContext({
90
70
  setDragOverrides: () => {
@@ -93,29 +73,37 @@ exports.VisualModeSettersContext = react_1.default.createContext({
93
73
  clearDragOverrides: () => {
94
74
  throw new Error('VisualModeSettersContext not initialized');
95
75
  },
76
+ setEffectDragOverrides: () => {
77
+ throw new Error('VisualModeSettersContext not initialized');
78
+ },
79
+ clearEffectDragOverrides: () => {
80
+ throw new Error('VisualModeSettersContext not initialized');
81
+ },
96
82
  setCodeValues: () => {
97
83
  throw new Error('VisualModeSettersContext not initialized');
98
84
  },
99
85
  });
100
- const SequenceManagerProvider = ({ children, visualModeEnabled }) => {
86
+ const effectDragOverridesKey = (nodePath, effectIndex) => `${(0, exports.makeSequencePropsSubscriptionKey)(nodePath)}.effects.${effectIndex}`;
87
+ const SequenceManagerProvider = ({ children }) => {
101
88
  const [sequences, setSequences] = (0, react_1.useState)([]);
102
89
  const [hidden, setHidden] = (0, react_1.useState)({});
103
90
  const [dragOverrides, setControlOverrides] = (0, react_1.useState)({});
104
91
  const controlOverridesRef = (0, react_1.useRef)(dragOverrides);
105
92
  controlOverridesRef.current = dragOverrides;
93
+ const [effectDragOverridesState, setEffectDragOverridesState] = (0, react_1.useState)({});
106
94
  const [codeValues, setCodeValuesMapState] = (0, react_1.useState)({});
107
95
  const setDragOverrides = (0, react_1.useCallback)((nodePath, key, value) => {
108
96
  setControlOverrides((prev) => ({
109
97
  ...prev,
110
- [nodePathToString(nodePath)]: {
111
- ...prev[nodePathToString(nodePath)],
98
+ [(0, exports.makeSequencePropsSubscriptionKey)(nodePath)]: {
99
+ ...prev[(0, exports.makeSequencePropsSubscriptionKey)(nodePath)],
112
100
  [key]: value,
113
101
  },
114
102
  }));
115
103
  }, []);
116
104
  const clearDragOverrides = (0, react_1.useCallback)((nodePath) => {
117
105
  setControlOverrides((prev) => {
118
- const key = nodePathToString(nodePath);
106
+ const key = (0, exports.makeSequencePropsSubscriptionKey)(nodePath);
119
107
  if (!prev[key]) {
120
108
  return prev;
121
109
  }
@@ -124,13 +112,38 @@ const SequenceManagerProvider = ({ children, visualModeEnabled }) => {
124
112
  return next;
125
113
  });
126
114
  }, []);
115
+ const setEffectDragOverrides = (0, react_1.useCallback)((nodePath, effectIndex, key, value) => {
116
+ setEffectDragOverridesState((prev) => {
117
+ const mapKey = effectDragOverridesKey(nodePath, effectIndex);
118
+ return {
119
+ ...prev,
120
+ [mapKey]: {
121
+ ...prev[mapKey],
122
+ [key]: value,
123
+ },
124
+ };
125
+ });
126
+ }, []);
127
+ const clearEffectDragOverrides = (0, react_1.useCallback)((nodePath, effectIndex) => {
128
+ setEffectDragOverridesState((prev) => {
129
+ const mapKey = effectDragOverridesKey(nodePath, effectIndex);
130
+ if (!prev[mapKey]) {
131
+ return prev;
132
+ }
133
+ const next = { ...prev };
134
+ delete next[mapKey];
135
+ return next;
136
+ });
137
+ }, []);
127
138
  const setCodeValues = (0, react_1.useCallback)((nodePath, values) => {
128
139
  setCodeValuesMapState((prev) => {
129
- const key = nodePathToString(nodePath);
130
- if (prev[key] === values) {
140
+ const key = (0, exports.makeSequencePropsSubscriptionKey)(nodePath);
141
+ const prevKey = prev[key];
142
+ const newKey = values(prevKey);
143
+ if (prevKey === newKey) {
131
144
  return prev;
132
145
  }
133
- return { ...prev, [key]: values };
146
+ return { ...prev, [key]: newKey };
134
147
  });
135
148
  }, []);
136
149
  const registerSequence = (0, react_1.useCallback)((seq) => {
@@ -154,21 +167,40 @@ const SequenceManagerProvider = ({ children, visualModeEnabled }) => {
154
167
  setHidden,
155
168
  };
156
169
  }, [hidden]);
157
- const gettersContext = (0, react_1.useMemo)(() => {
170
+ const getDragOverrides = (0, react_1.useCallback)((nodePath) => {
171
+ var _a;
172
+ return (_a = dragOverrides[(0, exports.makeSequencePropsSubscriptionKey)(nodePath)]) !== null && _a !== void 0 ? _a : {};
173
+ }, [dragOverrides]);
174
+ const getEffectDragOverrides = (0, react_1.useCallback)((nodePath, effectIndex) => {
175
+ var _a;
176
+ return ((_a = effectDragOverridesState[effectDragOverridesKey(nodePath, effectIndex)]) !== null && _a !== void 0 ? _a : {});
177
+ }, [effectDragOverridesState]);
178
+ const codeValuesContext = (0, react_1.useMemo)(() => {
179
+ return {
180
+ codeValues,
181
+ };
182
+ }, [codeValues]);
183
+ const dragOverridesContext = (0, react_1.useMemo)(() => {
158
184
  return {
159
- visualModeEnabled,
160
- getDragOverrides: (nodePath) => { var _a; return (_a = dragOverrides[nodePathToString(nodePath)]) !== null && _a !== void 0 ? _a : {}; },
161
- getCodeValues: (nodePath) => getCodeValues(codeValues, nodePath),
162
- getIsJsxInMapCallback: (nodePath) => getIsJsxInMapCallback(codeValues, nodePath),
185
+ getDragOverrides,
186
+ getEffectDragOverrides,
163
187
  };
164
- }, [visualModeEnabled, dragOverrides, codeValues]);
188
+ }, [getDragOverrides, getEffectDragOverrides]);
165
189
  const settersContext = (0, react_1.useMemo)(() => {
166
190
  return {
167
191
  setDragOverrides,
168
192
  clearDragOverrides,
193
+ setEffectDragOverrides,
194
+ clearEffectDragOverrides,
169
195
  setCodeValues,
170
196
  };
171
- }, [setDragOverrides, clearDragOverrides, setCodeValues]);
172
- return ((0, jsx_runtime_1.jsx)(exports.SequenceManager.Provider, { value: sequenceContext, children: (0, jsx_runtime_1.jsx)(exports.SequenceVisibilityToggleContext.Provider, { value: hiddenContext, children: (0, jsx_runtime_1.jsx)(exports.VisualModeGettersContext.Provider, { value: gettersContext, children: (0, jsx_runtime_1.jsx)(exports.VisualModeSettersContext.Provider, { value: settersContext, children: children }) }) }) }));
197
+ }, [
198
+ setDragOverrides,
199
+ clearDragOverrides,
200
+ setEffectDragOverrides,
201
+ clearEffectDragOverrides,
202
+ setCodeValues,
203
+ ]);
204
+ return ((0, jsx_runtime_1.jsx)(exports.SequenceManager.Provider, { value: sequenceContext, children: (0, jsx_runtime_1.jsx)(exports.SequenceVisibilityToggleContext.Provider, { value: hiddenContext, children: (0, jsx_runtime_1.jsx)(exports.VisualModeCodeValuesContext.Provider, { value: codeValuesContext, children: (0, jsx_runtime_1.jsx)(exports.VisualModeDragOverridesContext.Provider, { value: dragOverridesContext, children: (0, jsx_runtime_1.jsx)(exports.VisualModeSettersContext.Provider, { value: settersContext, children: children }) }) }) }) }));
173
205
  };
174
206
  exports.SequenceManagerProvider = SequenceManagerProvider;
@@ -98,16 +98,17 @@ function bezier(mX1, mY1, mX2, mY2) {
98
98
  });
99
99
  }
100
100
  return function (x) {
101
+ const clampedX = Math.min(1, Math.max(0, x));
101
102
  if (mX1 === mY1 && mX2 === mY2) {
102
- return x; // linear
103
+ return clampedX; // linear
103
104
  }
104
105
  // Because JavaScript number are imprecise, we should guarantee the extremes are right.
105
- if (x === 0) {
106
+ if (clampedX === 0) {
106
107
  return 0;
107
108
  }
108
- if (x === 1) {
109
+ if (clampedX === 1) {
109
110
  return 1;
110
111
  }
111
- return calcBezier(getTForX(x), mY1, mY2);
112
+ return calcBezier(getTForX(clampedX), mY1, mY2);
112
113
  };
113
114
  }
@@ -0,0 +1 @@
1
+ export declare const deleteNestedKey: (obj: Record<string, unknown>, keysToRemove: Set<string>) => Record<string, unknown>;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deleteNestedKey = void 0;
4
+ const deleteNestedKey = (obj, keysToRemove) => {
5
+ for (const key of keysToRemove) {
6
+ const parts = key.split('.');
7
+ const parents = [obj];
8
+ let current = obj;
9
+ for (let i = 0; i < parts.length - 1; i++) {
10
+ const part = parts[i];
11
+ const next = current[part];
12
+ if (next === undefined || next === null) {
13
+ current = null;
14
+ break;
15
+ }
16
+ current = next;
17
+ parents.push(current);
18
+ }
19
+ if (current === null) {
20
+ continue;
21
+ }
22
+ delete current[parts[parts.length - 1]];
23
+ for (let i = parents.length - 1; i > 0; i--) {
24
+ const parent = parents[i];
25
+ if (Object.keys(parent).length === 0) {
26
+ const parentKey = parts[i - 1];
27
+ delete parents[i - 1][parentKey];
28
+ }
29
+ else {
30
+ break;
31
+ }
32
+ }
33
+ }
34
+ return obj;
35
+ };
36
+ exports.deleteNestedKey = deleteNestedKey;
@@ -3,6 +3,10 @@
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.Easing = void 0;
5
5
  const bezier_js_1 = require("./bezier.js");
6
+ // Some easing curves are only defined on [0, 1] (e.g. quarter circle, bounce segments).
7
+ // `interpolate(..., { extrapolate: 'extend' })` can pass values outside that interval; clamp
8
+ // there so we return endpoints instead of NaN or unintended extrapolation.
9
+ const clampUnit = (t) => Math.min(1, Math.max(0, t));
6
10
  /**
7
11
  * @description The Easing module implements common easing functions. You can use it with the interpolate() API.
8
12
  * @see [Documentation](https://www.remotion.dev/docs/easing)
@@ -33,7 +37,8 @@ class Easing {
33
37
  return 1 - Math.cos((t * Math.PI) / 2);
34
38
  }
35
39
  static circle(t) {
36
- return 1 - Math.sqrt(1 - t * t);
40
+ const u = clampUnit(t);
41
+ return 1 - Math.sqrt(1 - u * u);
37
42
  }
38
43
  static exp(t) {
39
44
  return 2 ** (10 * (t - 1));
@@ -46,18 +51,19 @@ class Easing {
46
51
  return (t) => t * t * ((s + 1) * t - s);
47
52
  }
48
53
  static bounce(t) {
49
- if (t < 1 / 2.75) {
50
- return 7.5625 * t * t;
54
+ const u = clampUnit(t);
55
+ if (u < 1 / 2.75) {
56
+ return 7.5625 * u * u;
51
57
  }
52
- if (t < 2 / 2.75) {
53
- const t2_ = t - 1.5 / 2.75;
58
+ if (u < 2 / 2.75) {
59
+ const t2_ = u - 1.5 / 2.75;
54
60
  return 7.5625 * t2_ * t2_ + 0.75;
55
61
  }
56
- if (t < 2.5 / 2.75) {
57
- const t2_ = t - 2.25 / 2.75;
62
+ if (u < 2.5 / 2.75) {
63
+ const t2_ = u - 2.25 / 2.75;
58
64
  return 7.5625 * t2_ * t2_ + 0.9375;
59
65
  }
60
- const t2 = t - 2.625 / 2.75;
66
+ const t2 = u - 2.625 / 2.75;
61
67
  return 7.5625 * t2 * t2 + 0.984375;
62
68
  }
63
69
  static bezier(x1, y1, x2, y2) {
@@ -7,10 +7,16 @@ const use_current_frame_js_1 = require("../use-current-frame.js");
7
7
  const use_delay_render_js_1 = require("../use-delay-render.js");
8
8
  const run_effect_chain_js_1 = require("./run-effect-chain.js");
9
9
  const use_effect_chain_state_js_1 = require("./use-effect-chain-state.js");
10
+ const use_memoized_effects_js_1 = require("./use-memoized-effects.js");
10
11
  const Solid = ({ color, width, height, _experimentalEffects: experimentalEffects = [], className, style, pixelRatio = 1, }) => {
11
12
  const frame = (0, use_current_frame_js_1.useCurrentFrame)();
12
13
  const { delayRender, continueRender, cancelRender } = (0, use_delay_render_js_1.useDelayRender)();
13
14
  const [outputCanvas, setOutputCanvas] = (0, react_1.useState)(null);
15
+ const memoizedEffects = (0, use_memoized_effects_js_1.useMemoizedEffects)({
16
+ effects: experimentalEffects,
17
+ // TODO: Add schema to Solid
18
+ overrideId: null,
19
+ });
14
20
  const sourceCanvas = (0, react_1.useMemo)(() => {
15
21
  if (typeof document === 'undefined') {
16
22
  return null;
@@ -43,7 +49,7 @@ const Solid = ({ color, width, height, _experimentalEffects: experimentalEffects
43
49
  (0, run_effect_chain_js_1.runEffectChain)({
44
50
  state: chainState.get(width, height),
45
51
  source: sourceCanvas,
46
- effects: experimentalEffects,
52
+ effects: memoizedEffects,
47
53
  output: outputCanvas,
48
54
  frame,
49
55
  width,
@@ -63,7 +69,6 @@ const Solid = ({ color, width, height, _experimentalEffects: experimentalEffects
63
69
  }, [
64
70
  frame,
65
71
  color,
66
- experimentalEffects,
67
72
  outputCanvas,
68
73
  sourceCanvas,
69
74
  chainState,
@@ -73,6 +78,7 @@ const Solid = ({ color, width, height, _experimentalEffects: experimentalEffects
73
78
  delayRender,
74
79
  continueRender,
75
80
  cancelRender,
81
+ memoizedEffects,
76
82
  ]);
77
83
  return ((0, jsx_runtime_1.jsx)("canvas", { ref: setOutputCanvas, width: width, height: height, className: className, style: style }));
78
84
  };
@@ -0,0 +1,4 @@
1
+ import type { EffectDefinition, EffectDescriptor } from './effect-types.js';
2
+ type EffectFactory<P> = {} extends P ? (params?: P) => EffectDescriptor<unknown> : (params: P) => EffectDescriptor<unknown>;
3
+ export declare const createEffect: <P, S>(definition: EffectDefinition<P, S>) => EffectFactory<P>;
4
+ export {};