@codellyson/framely 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AbsoluteFill.d.ts +18 -0
- package/dist/AbsoluteFill.d.ts.map +1 -0
- package/dist/AbsoluteFill.js +25 -0
- package/dist/AbsoluteFill.js.map +1 -0
- package/dist/Audio.d.ts +80 -0
- package/dist/Audio.d.ts.map +1 -0
- package/dist/Audio.js +221 -0
- package/dist/Audio.js.map +1 -0
- package/dist/Composition.d.ts +208 -0
- package/dist/Composition.d.ts.map +1 -0
- package/dist/Composition.js +210 -0
- package/dist/Composition.js.map +1 -0
- package/dist/Easing.d.ts +88 -0
- package/dist/Easing.d.ts.map +1 -0
- package/dist/Easing.js +266 -0
- package/dist/Easing.js.map +1 -0
- package/dist/ErrorBoundary.d.ts +35 -0
- package/dist/ErrorBoundary.d.ts.map +1 -0
- package/dist/ErrorBoundary.js +74 -0
- package/dist/ErrorBoundary.js.map +1 -0
- package/dist/Folder.d.ts +46 -0
- package/dist/Folder.d.ts.map +1 -0
- package/dist/Folder.js +44 -0
- package/dist/Folder.js.map +1 -0
- package/dist/Freeze.d.ts +35 -0
- package/dist/Freeze.d.ts.map +1 -0
- package/dist/Freeze.js +40 -0
- package/dist/Freeze.js.map +1 -0
- package/dist/IFrame.d.ts +28 -0
- package/dist/IFrame.d.ts.map +1 -0
- package/dist/IFrame.js +57 -0
- package/dist/IFrame.js.map +1 -0
- package/dist/Img.d.ts +36 -0
- package/dist/Img.d.ts.map +1 -0
- package/dist/Img.js +91 -0
- package/dist/Img.js.map +1 -0
- package/dist/Loop.d.ts +66 -0
- package/dist/Loop.d.ts.map +1 -0
- package/dist/Loop.js +79 -0
- package/dist/Loop.js.map +1 -0
- package/dist/Player.d.ts +118 -0
- package/dist/Player.d.ts.map +1 -0
- package/dist/Player.js +311 -0
- package/dist/Player.js.map +1 -0
- package/dist/Sequence.d.ts +25 -0
- package/dist/Sequence.d.ts.map +1 -0
- package/dist/Sequence.js +37 -0
- package/dist/Sequence.js.map +1 -0
- package/dist/Series.d.ts +52 -0
- package/dist/Series.d.ts.map +1 -0
- package/dist/Series.js +86 -0
- package/dist/Series.js.map +1 -0
- package/dist/Text.d.ts +129 -0
- package/dist/Text.d.ts.map +1 -0
- package/dist/Text.js +211 -0
- package/dist/Text.js.map +1 -0
- package/dist/Video.d.ts +75 -0
- package/dist/Video.d.ts.map +1 -0
- package/dist/Video.js +136 -0
- package/dist/Video.js.map +1 -0
- package/dist/config.d.ts +128 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +243 -0
- package/dist/config.js.map +1 -0
- package/dist/context.d.ts +84 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +131 -0
- package/dist/context.js.map +1 -0
- package/dist/delayRender.d.ts +130 -0
- package/dist/delayRender.d.ts.map +1 -0
- package/dist/delayRender.js +197 -0
- package/dist/delayRender.js.map +1 -0
- package/dist/getInputProps.d.ts +118 -0
- package/dist/getInputProps.d.ts.map +1 -0
- package/dist/getInputProps.js +181 -0
- package/dist/getInputProps.js.map +1 -0
- package/dist/hooks/useDelayRender.d.ts +52 -0
- package/dist/hooks/useDelayRender.d.ts.map +1 -0
- package/dist/hooks/useDelayRender.js +92 -0
- package/dist/hooks/useDelayRender.js.map +1 -0
- package/dist/hooks.d.ts +19 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +17 -0
- package/dist/hooks.js.map +1 -0
- package/dist/index.d.ts +71 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +65 -0
- package/dist/index.js.map +1 -0
- package/dist/interpolate.d.ts +80 -0
- package/dist/interpolate.d.ts.map +1 -0
- package/dist/interpolate.js +108 -0
- package/dist/interpolate.js.map +1 -0
- package/dist/interpolateColors.d.ts +50 -0
- package/dist/interpolateColors.d.ts.map +1 -0
- package/dist/interpolateColors.js +300 -0
- package/dist/interpolateColors.js.map +1 -0
- package/dist/makeTransform.d.ts +98 -0
- package/dist/makeTransform.d.ts.map +1 -0
- package/dist/makeTransform.js +287 -0
- package/dist/makeTransform.js.map +1 -0
- package/dist/measureSpring.d.ts +75 -0
- package/dist/measureSpring.d.ts.map +1 -0
- package/dist/measureSpring.js +108 -0
- package/dist/measureSpring.js.map +1 -0
- package/dist/noise.d.ts +110 -0
- package/dist/noise.d.ts.map +1 -0
- package/dist/noise.js +228 -0
- package/dist/noise.js.map +1 -0
- package/dist/preload.d.ts +145 -0
- package/dist/preload.d.ts.map +1 -0
- package/dist/preload.js +225 -0
- package/dist/preload.js.map +1 -0
- package/dist/registerRoot.d.ts +140 -0
- package/dist/registerRoot.d.ts.map +1 -0
- package/dist/registerRoot.js +238 -0
- package/dist/registerRoot.js.map +1 -0
- package/dist/shapes/Circle.d.ts +15 -0
- package/dist/shapes/Circle.d.ts.map +1 -0
- package/dist/shapes/Circle.js +11 -0
- package/dist/shapes/Circle.js.map +1 -0
- package/dist/shapes/Ellipse.d.ts +16 -0
- package/dist/shapes/Ellipse.d.ts.map +1 -0
- package/dist/shapes/Ellipse.js +11 -0
- package/dist/shapes/Ellipse.js.map +1 -0
- package/dist/shapes/Line.d.ts +15 -0
- package/dist/shapes/Line.d.ts.map +1 -0
- package/dist/shapes/Line.js +11 -0
- package/dist/shapes/Line.js.map +1 -0
- package/dist/shapes/Path.d.ts +20 -0
- package/dist/shapes/Path.d.ts.map +1 -0
- package/dist/shapes/Path.js +14 -0
- package/dist/shapes/Path.js.map +1 -0
- package/dist/shapes/Polygon.d.ts +15 -0
- package/dist/shapes/Polygon.d.ts.map +1 -0
- package/dist/shapes/Polygon.js +16 -0
- package/dist/shapes/Polygon.js.map +1 -0
- package/dist/shapes/Rect.d.ts +18 -0
- package/dist/shapes/Rect.d.ts.map +1 -0
- package/dist/shapes/Rect.js +11 -0
- package/dist/shapes/Rect.js.map +1 -0
- package/dist/shapes/Svg.d.ts +16 -0
- package/dist/shapes/Svg.d.ts.map +1 -0
- package/dist/shapes/Svg.js +15 -0
- package/dist/shapes/Svg.js.map +1 -0
- package/dist/shapes/index.d.ts +16 -0
- package/dist/shapes/index.d.ts.map +1 -0
- package/dist/shapes/index.js +9 -0
- package/dist/shapes/index.js.map +1 -0
- package/dist/shapes/usePathLength.d.ts +24 -0
- package/dist/shapes/usePathLength.d.ts.map +1 -0
- package/dist/shapes/usePathLength.js +32 -0
- package/dist/shapes/usePathLength.js.map +1 -0
- package/dist/staticFile.d.ts +47 -0
- package/dist/staticFile.d.ts.map +1 -0
- package/dist/staticFile.js +105 -0
- package/dist/staticFile.js.map +1 -0
- package/dist/templates/api.d.ts +26 -0
- package/dist/templates/api.d.ts.map +1 -0
- package/dist/templates/api.js +142 -0
- package/dist/templates/api.js.map +1 -0
- package/dist/templates/index.d.ts +7 -0
- package/dist/templates/index.d.ts.map +1 -0
- package/dist/templates/index.js +7 -0
- package/dist/templates/index.js.map +1 -0
- package/dist/templates/mockData.d.ts +7 -0
- package/dist/templates/mockData.d.ts.map +1 -0
- package/dist/templates/mockData.js +262 -0
- package/dist/templates/mockData.js.map +1 -0
- package/dist/templates/types.d.ts +104 -0
- package/dist/templates/types.d.ts.map +1 -0
- package/dist/templates/types.js +16 -0
- package/dist/templates/types.js.map +1 -0
- package/dist/transitions/TransitionSeries.d.ts +127 -0
- package/dist/transitions/TransitionSeries.d.ts.map +1 -0
- package/dist/transitions/TransitionSeries.js +190 -0
- package/dist/transitions/TransitionSeries.js.map +1 -0
- package/dist/transitions/index.d.ts +52 -0
- package/dist/transitions/index.d.ts.map +1 -0
- package/dist/transitions/index.js +31 -0
- package/dist/transitions/index.js.map +1 -0
- package/dist/transitions/presets/fade.d.ts +45 -0
- package/dist/transitions/presets/fade.d.ts.map +1 -0
- package/dist/transitions/presets/fade.js +56 -0
- package/dist/transitions/presets/fade.js.map +1 -0
- package/dist/transitions/presets/flip.d.ts +99 -0
- package/dist/transitions/presets/flip.d.ts.map +1 -0
- package/dist/transitions/presets/flip.js +153 -0
- package/dist/transitions/presets/flip.js.map +1 -0
- package/dist/transitions/presets/slide.d.ts +61 -0
- package/dist/transitions/presets/slide.d.ts.map +1 -0
- package/dist/transitions/presets/slide.js +116 -0
- package/dist/transitions/presets/slide.js.map +1 -0
- package/dist/transitions/presets/wipe.d.ts +69 -0
- package/dist/transitions/presets/wipe.d.ts.map +1 -0
- package/dist/transitions/presets/wipe.js +136 -0
- package/dist/transitions/presets/wipe.js.map +1 -0
- package/dist/transitions/presets/zoom.d.ts +76 -0
- package/dist/transitions/presets/zoom.d.ts.map +1 -0
- package/dist/transitions/presets/zoom.js +110 -0
- package/dist/transitions/presets/zoom.js.map +1 -0
- package/dist/useAudioData.d.ts +112 -0
- package/dist/useAudioData.d.ts.map +1 -0
- package/dist/useAudioData.js +183 -0
- package/dist/useAudioData.js.map +1 -0
- package/dist/useSpring.d.ts +79 -0
- package/dist/useSpring.d.ts.map +1 -0
- package/dist/useSpring.js +140 -0
- package/dist/useSpring.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Component } from 'react';
|
|
3
|
+
export class ErrorBoundary extends Component {
|
|
4
|
+
constructor(props) {
|
|
5
|
+
super(props);
|
|
6
|
+
this.state = { hasError: false, error: null };
|
|
7
|
+
}
|
|
8
|
+
static getDerivedStateFromError(error) {
|
|
9
|
+
return { hasError: true, error };
|
|
10
|
+
}
|
|
11
|
+
componentDidCatch(error, errorInfo) {
|
|
12
|
+
// In render mode, expose the error for CLI detection
|
|
13
|
+
if (typeof window !== 'undefined') {
|
|
14
|
+
window.__FRAMELY_RENDER_ERROR = {
|
|
15
|
+
message: error.message,
|
|
16
|
+
stack: error.stack,
|
|
17
|
+
componentStack: errorInfo?.componentStack,
|
|
18
|
+
};
|
|
19
|
+
// Dispatch custom event for render pipeline
|
|
20
|
+
window.dispatchEvent(new CustomEvent('framely-render-error', {
|
|
21
|
+
detail: { error, errorInfo },
|
|
22
|
+
}));
|
|
23
|
+
}
|
|
24
|
+
if (this.props.onError) {
|
|
25
|
+
this.props.onError(error, errorInfo);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
render() {
|
|
29
|
+
if (this.state.hasError) {
|
|
30
|
+
// Custom fallback UI
|
|
31
|
+
if (this.props.fallback) {
|
|
32
|
+
return this.props.fallback;
|
|
33
|
+
}
|
|
34
|
+
// In render mode, show nothing (error is on window)
|
|
35
|
+
const params = new URLSearchParams(typeof window !== 'undefined' ? window.location.search : '');
|
|
36
|
+
if (params.get('renderMode') === 'true') {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
// Dev/studio mode - show error details
|
|
40
|
+
return (_jsxs("div", { style: {
|
|
41
|
+
position: 'absolute',
|
|
42
|
+
inset: 0,
|
|
43
|
+
display: 'flex',
|
|
44
|
+
flexDirection: 'column',
|
|
45
|
+
alignItems: 'center',
|
|
46
|
+
justifyContent: 'center',
|
|
47
|
+
background: '#1a1a1a',
|
|
48
|
+
color: '#ef4444',
|
|
49
|
+
fontFamily: 'system-ui, sans-serif',
|
|
50
|
+
padding: '24px',
|
|
51
|
+
}, children: [_jsx("div", { style: { fontSize: '18px', fontWeight: 600, marginBottom: '12px' }, children: "Composition Error" }), _jsx("div", { style: {
|
|
52
|
+
fontSize: '14px',
|
|
53
|
+
color: '#fff',
|
|
54
|
+
marginBottom: '16px',
|
|
55
|
+
textAlign: 'center',
|
|
56
|
+
maxWidth: '600px',
|
|
57
|
+
}, children: this.state.error?.message || 'An unknown error occurred' }), this.state.error?.stack && (_jsx("pre", { style: {
|
|
58
|
+
fontSize: '11px',
|
|
59
|
+
color: '#888',
|
|
60
|
+
background: '#111',
|
|
61
|
+
padding: '12px',
|
|
62
|
+
borderRadius: '6px',
|
|
63
|
+
maxWidth: '80%',
|
|
64
|
+
maxHeight: '200px',
|
|
65
|
+
overflow: 'auto',
|
|
66
|
+
whiteSpace: 'pre-wrap',
|
|
67
|
+
wordBreak: 'break-word',
|
|
68
|
+
}, children: this.state.error.stack }))] }));
|
|
69
|
+
}
|
|
70
|
+
return this.props.children;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
export default ErrorBoundary;
|
|
74
|
+
//# sourceMappingURL=ErrorBoundary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ErrorBoundary.js","sourceRoot":"","sources":["../src/ErrorBoundary.tsx"],"names":[],"mappings":"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"}
|
package/dist/Folder.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* The folder path represented as an array of folder names from root to current.
|
|
4
|
+
*/
|
|
5
|
+
type FolderPath = string[];
|
|
6
|
+
/**
|
|
7
|
+
* Props for the Folder component.
|
|
8
|
+
*/
|
|
9
|
+
interface FolderProps {
|
|
10
|
+
/** The folder name displayed in the sidebar */
|
|
11
|
+
name: string;
|
|
12
|
+
/** Child elements (Compositions or nested Folders) */
|
|
13
|
+
children: ReactNode;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Hook to access the current folder path
|
|
17
|
+
*
|
|
18
|
+
* Returns:
|
|
19
|
+
* string[] - Array of folder names from root to current
|
|
20
|
+
*
|
|
21
|
+
* Usage:
|
|
22
|
+
* const path = useFolder();
|
|
23
|
+
* console.log(path.join(' / ')); // "Effects / Transitions"
|
|
24
|
+
*/
|
|
25
|
+
export declare function useFolder(): FolderPath;
|
|
26
|
+
/**
|
|
27
|
+
* Folder organizes compositions in the Studio sidebar.
|
|
28
|
+
*
|
|
29
|
+
* Folders can be nested to create hierarchical organization.
|
|
30
|
+
* They don't affect rendering — they're purely for organization in the UI.
|
|
31
|
+
*
|
|
32
|
+
* Props:
|
|
33
|
+
* name - The folder name displayed in the sidebar
|
|
34
|
+
*
|
|
35
|
+
* Usage:
|
|
36
|
+
* <Folder name="Marketing">
|
|
37
|
+
* <Composition id="promo-video" ... />
|
|
38
|
+
* <Folder name="Social">
|
|
39
|
+
* <Composition id="instagram-reel" ... />
|
|
40
|
+
* <Composition id="tiktok-clip" ... />
|
|
41
|
+
* </Folder>
|
|
42
|
+
* </Folder>
|
|
43
|
+
*/
|
|
44
|
+
export declare function Folder({ name, children }: FolderProps): JSX.Element;
|
|
45
|
+
export default Folder;
|
|
46
|
+
//# sourceMappingURL=Folder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Folder.d.ts","sourceRoot":"","sources":["../src/Folder.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAElE;;GAEG;AACH,KAAK,UAAU,GAAG,MAAM,EAAE,CAAC;AAE3B;;GAEG;AACH,UAAU,WAAW;IACnB,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,sDAAsD;IACtD,QAAQ,EAAE,SAAS,CAAC;CACrB;AAOD;;;;;;;;;GASG;AACH,wBAAgB,SAAS,IAAI,UAAU,CAEtC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,WAAW,GAAG,GAAG,CAAC,OAAO,CASnE;AAED,eAAe,MAAM,CAAC"}
|
package/dist/Folder.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useContext } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* Context for tracking folder hierarchy
|
|
5
|
+
*/
|
|
6
|
+
const FolderContext = createContext([]);
|
|
7
|
+
/**
|
|
8
|
+
* Hook to access the current folder path
|
|
9
|
+
*
|
|
10
|
+
* Returns:
|
|
11
|
+
* string[] - Array of folder names from root to current
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* const path = useFolder();
|
|
15
|
+
* console.log(path.join(' / ')); // "Effects / Transitions"
|
|
16
|
+
*/
|
|
17
|
+
export function useFolder() {
|
|
18
|
+
return useContext(FolderContext);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Folder organizes compositions in the Studio sidebar.
|
|
22
|
+
*
|
|
23
|
+
* Folders can be nested to create hierarchical organization.
|
|
24
|
+
* They don't affect rendering — they're purely for organization in the UI.
|
|
25
|
+
*
|
|
26
|
+
* Props:
|
|
27
|
+
* name - The folder name displayed in the sidebar
|
|
28
|
+
*
|
|
29
|
+
* Usage:
|
|
30
|
+
* <Folder name="Marketing">
|
|
31
|
+
* <Composition id="promo-video" ... />
|
|
32
|
+
* <Folder name="Social">
|
|
33
|
+
* <Composition id="instagram-reel" ... />
|
|
34
|
+
* <Composition id="tiktok-clip" ... />
|
|
35
|
+
* </Folder>
|
|
36
|
+
* </Folder>
|
|
37
|
+
*/
|
|
38
|
+
export function Folder({ name, children }) {
|
|
39
|
+
const parentPath = useContext(FolderContext);
|
|
40
|
+
const currentPath = [...parentPath, name];
|
|
41
|
+
return (_jsx(FolderContext.Provider, { value: currentPath, children: children }));
|
|
42
|
+
}
|
|
43
|
+
export default Folder;
|
|
44
|
+
//# sourceMappingURL=Folder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Folder.js","sourceRoot":"","sources":["../src/Folder.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAkB,MAAM,OAAO,CAAC;AAiBlE;;GAEG;AACH,MAAM,aAAa,GAAG,aAAa,CAAa,EAAE,CAAC,CAAC;AAEpD;;;;;;;;;GASG;AACH,MAAM,UAAU,SAAS;IACvB,OAAO,UAAU,CAAC,aAAa,CAAC,CAAC;AACnC,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAe;IACpD,MAAM,UAAU,GAAe,UAAU,CAAC,aAAa,CAAC,CAAC;IACzD,MAAM,WAAW,GAAe,CAAC,GAAG,UAAU,EAAE,IAAI,CAAC,CAAC;IAEtD,OAAO,CACL,KAAC,aAAa,CAAC,QAAQ,IAAC,KAAK,EAAE,WAAW,YACvC,QAAQ,GACc,CAC1B,CAAC;AACJ,CAAC;AAED,eAAe,MAAM,CAAC"}
|
package/dist/Freeze.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Props for the Freeze component.
|
|
4
|
+
*/
|
|
5
|
+
export interface FreezeProps {
|
|
6
|
+
/** The frame number children should see (required). */
|
|
7
|
+
frame: number;
|
|
8
|
+
/** Whether to freeze (default: true). If false, children see the normal frame. */
|
|
9
|
+
active?: boolean;
|
|
10
|
+
/** The content to render inside the freeze boundary. */
|
|
11
|
+
children: ReactNode;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Freeze pauses children at a specific frame.
|
|
15
|
+
*
|
|
16
|
+
* Children inside a Freeze component will always see the same frame value,
|
|
17
|
+
* regardless of the actual timeline position. This is useful for:
|
|
18
|
+
* - Pausing complex animations at a specific state
|
|
19
|
+
* - Creating "freeze frame" effects
|
|
20
|
+
* - Displaying a static frame from a video or animation
|
|
21
|
+
*
|
|
22
|
+
* Usage:
|
|
23
|
+
* // Freeze at frame 15
|
|
24
|
+
* <Freeze frame={15}>
|
|
25
|
+
* <MyAnimation />
|
|
26
|
+
* </Freeze>
|
|
27
|
+
*
|
|
28
|
+
* // Conditional freeze
|
|
29
|
+
* <Freeze frame={30} active={shouldFreeze}>
|
|
30
|
+
* <MyAnimation />
|
|
31
|
+
* </Freeze>
|
|
32
|
+
*/
|
|
33
|
+
export declare function Freeze({ frame, active, children }: FreezeProps): ReactNode;
|
|
34
|
+
export default Freeze;
|
|
35
|
+
//# sourceMappingURL=Freeze.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Freeze.d.ts","sourceRoot":"","sources":["../src/Freeze.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAGhD;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,uDAAuD;IACvD,KAAK,EAAE,MAAM,CAAC;IACd,kFAAkF;IAClF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,wDAAwD;IACxD,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,MAAM,CAAC,EAAE,KAAK,EAAE,MAAa,EAAE,QAAQ,EAAE,EAAE,WAAW,GAAG,SAAS,CAyBjF;AAED,eAAe,MAAM,CAAC"}
|
package/dist/Freeze.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import TimelineContext, { useTimeline } from './context';
|
|
4
|
+
/**
|
|
5
|
+
* Freeze pauses children at a specific frame.
|
|
6
|
+
*
|
|
7
|
+
* Children inside a Freeze component will always see the same frame value,
|
|
8
|
+
* regardless of the actual timeline position. This is useful for:
|
|
9
|
+
* - Pausing complex animations at a specific state
|
|
10
|
+
* - Creating "freeze frame" effects
|
|
11
|
+
* - Displaying a static frame from a video or animation
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* // Freeze at frame 15
|
|
15
|
+
* <Freeze frame={15}>
|
|
16
|
+
* <MyAnimation />
|
|
17
|
+
* </Freeze>
|
|
18
|
+
*
|
|
19
|
+
* // Conditional freeze
|
|
20
|
+
* <Freeze frame={30} active={shouldFreeze}>
|
|
21
|
+
* <MyAnimation />
|
|
22
|
+
* </Freeze>
|
|
23
|
+
*/
|
|
24
|
+
export function Freeze({ frame, active = true, children }) {
|
|
25
|
+
const parent = useTimeline();
|
|
26
|
+
if (frame === undefined) {
|
|
27
|
+
throw new Error('Freeze requires a frame prop');
|
|
28
|
+
}
|
|
29
|
+
const contextValue = useMemo(() => ({
|
|
30
|
+
...parent,
|
|
31
|
+
frame: active ? frame : parent.frame,
|
|
32
|
+
}), [parent, frame, active]);
|
|
33
|
+
// If not active, just render children without context override
|
|
34
|
+
if (!active) {
|
|
35
|
+
return children;
|
|
36
|
+
}
|
|
37
|
+
return (_jsx(TimelineContext.Provider, { value: contextValue, children: children }));
|
|
38
|
+
}
|
|
39
|
+
export default Freeze;
|
|
40
|
+
//# sourceMappingURL=Freeze.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Freeze.js","sourceRoot":"","sources":["../src/Freeze.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,OAAO,EAAkB,MAAM,OAAO,CAAC;AAChD,OAAO,eAAe,EAAE,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAczD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,EAAe;IACpE,MAAM,MAAM,GAAG,WAAW,EAAE,CAAC;IAE7B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;IAClD,CAAC;IAED,MAAM,YAAY,GAAG,OAAO,CAC1B,GAAG,EAAE,CAAC,CAAC;QACL,GAAG,MAAM;QACT,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK;KACrC,CAAC,EACF,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CACxB,CAAC;IAEF,+DAA+D;IAC/D,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,OAAO,CACL,KAAC,eAAe,CAAC,QAAQ,IAAC,KAAK,EAAE,YAAY,YAC1C,QAAQ,GACgB,CAC5B,CAAC;AACJ,CAAC;AAED,eAAe,MAAM,CAAC"}
|
package/dist/IFrame.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Props for the IFrame component.
|
|
4
|
+
*
|
|
5
|
+
* Extends standard iframe HTML attributes so all native iframe props
|
|
6
|
+
* (e.g., sandbox, allow, referrerPolicy) are supported.
|
|
7
|
+
*/
|
|
8
|
+
export interface IFrameProps extends React.IframeHTMLAttributes<HTMLIFrameElement> {
|
|
9
|
+
/** URL to load in the iframe. */
|
|
10
|
+
src?: string;
|
|
11
|
+
/** Timeout in ms before failing the delay render. Defaults to 30000. */
|
|
12
|
+
delayRenderTimeout?: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* IFrame component that delays rendering until the iframe content is loaded.
|
|
16
|
+
*
|
|
17
|
+
* Useful for embedding web content, charts, maps, or other external content
|
|
18
|
+
* that needs to be fully loaded before capturing the frame.
|
|
19
|
+
*
|
|
20
|
+
* Usage:
|
|
21
|
+
* <IFrame
|
|
22
|
+
* src="https://example.com/chart"
|
|
23
|
+
* style={{ width: 800, height: 600 }}
|
|
24
|
+
* />
|
|
25
|
+
*/
|
|
26
|
+
export declare function IFrame({ src, delayRenderTimeout, onLoad, onError, style, className, ...rest }: IFrameProps): React.ReactElement;
|
|
27
|
+
export default IFrame;
|
|
28
|
+
//# sourceMappingURL=IFrame.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IFrame.d.ts","sourceRoot":"","sources":["../src/IFrame.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAG3D;;;;;GAKG;AACH,MAAM,WAAW,WACf,SAAQ,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC;IACrD,iCAAiC;IACjC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,MAAM,CAAC,EACrB,GAAG,EACH,kBAA0B,EAC1B,MAAM,EACN,OAAO,EACP,KAAK,EACL,SAAS,EACT,GAAG,IAAI,EACR,EAAE,WAAW,GAAG,KAAK,CAAC,YAAY,CA4DlC;AAED,eAAe,MAAM,CAAC"}
|
package/dist/IFrame.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef, useState } from 'react';
|
|
3
|
+
import { delayRender, continueRender, cancelRender } from './delayRender';
|
|
4
|
+
/**
|
|
5
|
+
* IFrame component that delays rendering until the iframe content is loaded.
|
|
6
|
+
*
|
|
7
|
+
* Useful for embedding web content, charts, maps, or other external content
|
|
8
|
+
* that needs to be fully loaded before capturing the frame.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* <IFrame
|
|
12
|
+
* src="https://example.com/chart"
|
|
13
|
+
* style={{ width: 800, height: 600 }}
|
|
14
|
+
* />
|
|
15
|
+
*/
|
|
16
|
+
export function IFrame({ src, delayRenderTimeout = 30000, onLoad, onError, style, className, ...rest }) {
|
|
17
|
+
const iframeRef = useRef(null);
|
|
18
|
+
const handleRef = useRef(null);
|
|
19
|
+
const [loaded, setLoaded] = useState(false);
|
|
20
|
+
// Delay render until iframe is loaded
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
handleRef.current = delayRender(`Loading iframe: ${src}`, {
|
|
23
|
+
timeoutInMilliseconds: delayRenderTimeout,
|
|
24
|
+
});
|
|
25
|
+
return () => {
|
|
26
|
+
if (handleRef.current !== null) {
|
|
27
|
+
continueRender(handleRef.current);
|
|
28
|
+
handleRef.current = null;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
}, [src, delayRenderTimeout]);
|
|
32
|
+
// Handle iframe load
|
|
33
|
+
const handleLoad = (event) => {
|
|
34
|
+
setLoaded(true);
|
|
35
|
+
onLoad?.(event);
|
|
36
|
+
if (handleRef.current !== null) {
|
|
37
|
+
continueRender(handleRef.current);
|
|
38
|
+
handleRef.current = null;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
// Handle iframe error
|
|
42
|
+
const handleError = (event) => {
|
|
43
|
+
const err = new Error(`Failed to load iframe: ${src}`);
|
|
44
|
+
onError?.(event);
|
|
45
|
+
if (handleRef.current !== null) {
|
|
46
|
+
cancelRender(err);
|
|
47
|
+
handleRef.current = null;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
return (_jsx("iframe", { ref: iframeRef, src: src, onLoad: handleLoad, onError: handleError, style: {
|
|
51
|
+
border: 'none',
|
|
52
|
+
...style,
|
|
53
|
+
opacity: loaded ? (style?.opacity ?? 1) : 0,
|
|
54
|
+
}, className: className, ...rest }));
|
|
55
|
+
}
|
|
56
|
+
export default IFrame;
|
|
57
|
+
//# sourceMappingURL=IFrame.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IFrame.js","sourceRoot":"","sources":["../src/IFrame.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAgB1E;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,MAAM,CAAC,EACrB,GAAG,EACH,kBAAkB,GAAG,KAAK,EAC1B,MAAM,EACN,OAAO,EACP,KAAK,EACL,SAAS,EACT,GAAG,IAAI,EACK;IACZ,MAAM,SAAS,GAAG,MAAM,CAAoB,IAAI,CAAC,CAAC;IAClD,MAAM,SAAS,GAAG,MAAM,CAAgB,IAAI,CAAC,CAAC;IAC9C,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAU,KAAK,CAAC,CAAC;IAErD,sCAAsC;IACtC,SAAS,CAAC,GAAG,EAAE;QACb,SAAS,CAAC,OAAO,GAAG,WAAW,CAAC,mBAAmB,GAAG,EAAE,EAAE;YACxD,qBAAqB,EAAE,kBAAkB;SAC1C,CAAC,CAAC;QAEH,OAAO,GAAG,EAAE;YACV,IAAI,SAAS,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;gBAC/B,cAAc,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;gBAClC,SAAS,CAAC,OAAO,GAAG,IAAI,CAAC;YAC3B,CAAC;QACH,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC,CAAC;IAE9B,qBAAqB;IACrB,MAAM,UAAU,GAAG,CACjB,KAA8C,EACxC,EAAE;QACR,SAAS,CAAC,IAAI,CAAC,CAAC;QAChB,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC;QAEhB,IAAI,SAAS,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;YAC/B,cAAc,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YAClC,SAAS,CAAC,OAAO,GAAG,IAAI,CAAC;QAC3B,CAAC;IACH,CAAC,CAAC;IAEF,sBAAsB;IACtB,MAAM,WAAW,GAAG,CAClB,KAA8C,EACxC,EAAE;QACR,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,0BAA0B,GAAG,EAAE,CAAC,CAAC;QACvD,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;QAEjB,IAAI,SAAS,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;YAC/B,YAAY,CAAC,GAAG,CAAC,CAAC;YAClB,SAAS,CAAC,OAAO,GAAG,IAAI,CAAC;QAC3B,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,CACL,iBACE,GAAG,EAAE,SAAS,EACd,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,WAAW,EACpB,KAAK,EAAE;YACL,MAAM,EAAE,MAAM;YACd,GAAG,KAAK;YACR,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SAC5C,EACD,SAAS,EAAE,SAAS,KAChB,IAAI,GACR,CACH,CAAC;AACJ,CAAC;AAED,eAAe,MAAM,CAAC"}
|
package/dist/Img.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Props for the Img component.
|
|
4
|
+
*
|
|
5
|
+
* Extends standard HTML img attributes with additional props
|
|
6
|
+
* for controlling image loading behavior during rendering.
|
|
7
|
+
*/
|
|
8
|
+
export interface ImgProps extends React.ImgHTMLAttributes<HTMLImageElement> {
|
|
9
|
+
/** Image source URL. Use staticFile() for local assets. */
|
|
10
|
+
src: string;
|
|
11
|
+
/** Callback when the image fails to load after all retries. */
|
|
12
|
+
onError?: React.ReactEventHandler<HTMLImageElement>;
|
|
13
|
+
/** Number of retry attempts on load failure. Defaults to 2. */
|
|
14
|
+
maxRetries?: number;
|
|
15
|
+
/** Pause playback while loading in preview mode. Defaults to false. */
|
|
16
|
+
pauseWhenLoading?: boolean;
|
|
17
|
+
/** Custom timeout in milliseconds for delayRender. Defaults to 30000. */
|
|
18
|
+
delayRenderTimeout?: number;
|
|
19
|
+
/** Number of retries for delay render timeout. Defaults to 0. */
|
|
20
|
+
delayRenderRetries?: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Image component that delays rendering until the image is loaded.
|
|
24
|
+
*
|
|
25
|
+
* This ensures that images are always visible in rendered frames,
|
|
26
|
+
* preventing blank spaces or loading states in the final video.
|
|
27
|
+
*
|
|
28
|
+
* Usage:
|
|
29
|
+
* import { Img, staticFile } from './lib';
|
|
30
|
+
*
|
|
31
|
+
* <Img src={staticFile('images/hero.png')} alt="Hero" />
|
|
32
|
+
* <Img src="https://example.com/image.jpg" style={{ width: 200 }} />
|
|
33
|
+
*/
|
|
34
|
+
export declare const Img: React.ForwardRefExoticComponent<ImgProps & React.RefAttributes<HTMLImageElement>>;
|
|
35
|
+
export default Img;
|
|
36
|
+
//# sourceMappingURL=Img.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Img.d.ts","sourceRoot":"","sources":["../src/Img.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAG3D;;;;;GAKG;AACH,MAAM,WAAW,QAAS,SAAQ,KAAK,CAAC,iBAAiB,CAAC,gBAAgB,CAAC;IACzE,2DAA2D;IAC3D,GAAG,EAAE,MAAM,CAAC;IACZ,+DAA+D;IAC/D,OAAO,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;IACpD,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uEAAuE;IACvE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,yEAAyE;IACzE,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,iEAAiE;IACjE,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,GAAG,mFAyGf,CAAC;AAIF,eAAe,GAAG,CAAC"}
|
package/dist/Img.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
3
|
+
import { delayRender, continueRender, cancelRender } from './delayRender';
|
|
4
|
+
/**
|
|
5
|
+
* Image component that delays rendering until the image is loaded.
|
|
6
|
+
*
|
|
7
|
+
* This ensures that images are always visible in rendered frames,
|
|
8
|
+
* preventing blank spaces or loading states in the final video.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* import { Img, staticFile } from './lib';
|
|
12
|
+
*
|
|
13
|
+
* <Img src={staticFile('images/hero.png')} alt="Hero" />
|
|
14
|
+
* <Img src="https://example.com/image.jpg" style={{ width: 200 }} />
|
|
15
|
+
*/
|
|
16
|
+
export const Img = React.forwardRef(({ src, onError, maxRetries = 2, pauseWhenLoading = false, delayRenderTimeout = 30000, delayRenderRetries = 0, ...rest }, forwardedRef) => {
|
|
17
|
+
const [loaded, setLoaded] = useState(false);
|
|
18
|
+
const [error, setError] = useState(null);
|
|
19
|
+
const [retryCount, setRetryCount] = useState(0);
|
|
20
|
+
const handleRef = useRef(null);
|
|
21
|
+
const imgRef = useRef(null);
|
|
22
|
+
// Merge forwarded ref and internal ref
|
|
23
|
+
const setRefs = React.useCallback((node) => {
|
|
24
|
+
imgRef.current = node;
|
|
25
|
+
if (typeof forwardedRef === 'function') {
|
|
26
|
+
forwardedRef(node);
|
|
27
|
+
}
|
|
28
|
+
else if (forwardedRef) {
|
|
29
|
+
forwardedRef.current = node;
|
|
30
|
+
}
|
|
31
|
+
}, [forwardedRef]);
|
|
32
|
+
// Initialize delay render on mount
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
handleRef.current = delayRender(`Loading image: ${src}`, {
|
|
35
|
+
timeoutInMilliseconds: delayRenderTimeout,
|
|
36
|
+
retries: delayRenderRetries,
|
|
37
|
+
});
|
|
38
|
+
return () => {
|
|
39
|
+
// Cleanup if component unmounts before load
|
|
40
|
+
if (handleRef.current !== null) {
|
|
41
|
+
continueRender(handleRef.current);
|
|
42
|
+
handleRef.current = null;
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
}, [src, delayRenderTimeout, delayRenderRetries]);
|
|
46
|
+
// Handle image load
|
|
47
|
+
const handleLoad = () => {
|
|
48
|
+
setLoaded(true);
|
|
49
|
+
setError(null);
|
|
50
|
+
if (handleRef.current !== null) {
|
|
51
|
+
continueRender(handleRef.current);
|
|
52
|
+
handleRef.current = null;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
// Handle image error
|
|
56
|
+
const handleError = (event) => {
|
|
57
|
+
if (retryCount < maxRetries) {
|
|
58
|
+
// Retry by forcing a new request
|
|
59
|
+
setRetryCount((c) => c + 1);
|
|
60
|
+
if (imgRef.current) {
|
|
61
|
+
// Add cache-busting query param
|
|
62
|
+
const separator = src.includes('?') ? '&' : '?';
|
|
63
|
+
imgRef.current.src = `${src}${separator}_retry=${retryCount + 1}`;
|
|
64
|
+
}
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const err = new Error(`Failed to load image: ${src}`);
|
|
68
|
+
setError(err);
|
|
69
|
+
onError?.(event);
|
|
70
|
+
// Cancel the render - image is required
|
|
71
|
+
if (handleRef.current !== null) {
|
|
72
|
+
cancelRender(err);
|
|
73
|
+
handleRef.current = null;
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
// Check if image is already cached (loads synchronously)
|
|
77
|
+
useEffect(() => {
|
|
78
|
+
if (imgRef.current?.complete && imgRef.current?.naturalWidth > 0) {
|
|
79
|
+
handleLoad();
|
|
80
|
+
}
|
|
81
|
+
}, [src]);
|
|
82
|
+
return (_jsx("img", { ref: setRefs, src: src, onLoad: handleLoad, onError: handleError, ...rest,
|
|
83
|
+
// Hide image until loaded to prevent flash of broken image
|
|
84
|
+
style: {
|
|
85
|
+
...rest.style,
|
|
86
|
+
opacity: loaded ? (rest.style?.opacity ?? 1) : 0,
|
|
87
|
+
} }));
|
|
88
|
+
});
|
|
89
|
+
Img.displayName = 'Img';
|
|
90
|
+
export default Img;
|
|
91
|
+
//# sourceMappingURL=Img.js.map
|
package/dist/Img.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Img.js","sourceRoot":"","sources":["../src/Img.tsx"],"names":[],"mappings":"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"}
|
package/dist/Loop.d.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import React, { CSSProperties, ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Metadata exposed by the Loop component via LoopContext.
|
|
4
|
+
*/
|
|
5
|
+
export interface LoopContextValue {
|
|
6
|
+
/** Current iteration index (0-based) */
|
|
7
|
+
iteration: number;
|
|
8
|
+
/** Duration of each loop iteration in frames */
|
|
9
|
+
durationInFrames: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Props for the Loop component.
|
|
13
|
+
*/
|
|
14
|
+
export interface LoopProps {
|
|
15
|
+
/** Number of frames per iteration (required, must be positive) */
|
|
16
|
+
durationInFrames: number;
|
|
17
|
+
/** Number of repetitions (default: Infinity) */
|
|
18
|
+
times?: number;
|
|
19
|
+
/** Layout mode: 'absolute-fill' applies absolute positioning, 'none' applies no layout */
|
|
20
|
+
layout?: 'absolute-fill' | 'none';
|
|
21
|
+
/** Additional CSS styles applied to the container div */
|
|
22
|
+
style?: CSSProperties;
|
|
23
|
+
/** Optional label for debugging */
|
|
24
|
+
name?: string;
|
|
25
|
+
/** Child elements rendered inside the loop */
|
|
26
|
+
children: ReactNode;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Hook to access loop metadata when inside a Loop component.
|
|
30
|
+
*
|
|
31
|
+
* Returns:
|
|
32
|
+
* { iteration, durationInFrames } - Current iteration (0-indexed) and loop duration
|
|
33
|
+
* null - If not inside a Loop
|
|
34
|
+
*
|
|
35
|
+
* Usage:
|
|
36
|
+
* const loop = Loop.useLoop();
|
|
37
|
+
* if (loop) {
|
|
38
|
+
* console.log(`Iteration ${loop.iteration + 1}`);
|
|
39
|
+
* }
|
|
40
|
+
*/
|
|
41
|
+
declare function useLoop(): LoopContextValue | null;
|
|
42
|
+
/**
|
|
43
|
+
* Loop repeats its children for a specified number of iterations.
|
|
44
|
+
*
|
|
45
|
+
* The frame counter resets at the start of each iteration, so children
|
|
46
|
+
* always see frames 0 to durationInFrames-1.
|
|
47
|
+
*
|
|
48
|
+
* Props:
|
|
49
|
+
* durationInFrames - Frames per iteration (required)
|
|
50
|
+
* times - Number of repetitions (default: Infinity)
|
|
51
|
+
* layout - 'absolute-fill' (default) or 'none'
|
|
52
|
+
* style - Additional CSS styles
|
|
53
|
+
* name - Optional label for debugging
|
|
54
|
+
*
|
|
55
|
+
* Usage:
|
|
56
|
+
* <Loop durationInFrames={30} times={3}>
|
|
57
|
+
* <PulseAnimation />
|
|
58
|
+
* </Loop>
|
|
59
|
+
*/
|
|
60
|
+
export declare function Loop({ durationInFrames, times, layout, style, name, children, }: LoopProps): React.ReactElement | null;
|
|
61
|
+
export declare namespace Loop {
|
|
62
|
+
var useLoop: typeof import("./Loop").useLoop;
|
|
63
|
+
}
|
|
64
|
+
export { useLoop };
|
|
65
|
+
export default Loop;
|
|
66
|
+
//# sourceMappingURL=Loop.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Loop.d.ts","sourceRoot":"","sources":["../src/Loop.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAsC,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAG5F;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,gDAAgD;IAChD,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,kEAAkE;IAClE,gBAAgB,EAAE,MAAM,CAAC;IACzB,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0FAA0F;IAC1F,MAAM,CAAC,EAAE,eAAe,GAAG,MAAM,CAAC;IAClC,yDAAyD;IACzD,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,mCAAmC;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8CAA8C;IAC9C,QAAQ,EAAE,SAAS,CAAC;CACrB;AAOD;;;;;;;;;;;;GAYG;AACH,iBAAS,OAAO,IAAI,gBAAgB,GAAG,IAAI,CAE1C;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,IAAI,CAAC,EACnB,gBAAgB,EAChB,KAAgB,EAChB,MAAwB,EACxB,KAAK,EACL,IAAI,EACJ,QAAQ,GACT,EAAE,SAAS,GAAG,KAAK,CAAC,YAAY,GAAG,IAAI,CAsDvC;yBA7De,IAAI;;;AAkEpB,OAAO,EAAE,OAAO,EAAE,CAAC;AACnB,eAAe,IAAI,CAAC"}
|
package/dist/Loop.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo, createContext, useContext } from 'react';
|
|
3
|
+
import TimelineContext, { useTimeline } from './context';
|
|
4
|
+
/**
|
|
5
|
+
* Context for accessing loop metadata
|
|
6
|
+
*/
|
|
7
|
+
const LoopContext = createContext(null);
|
|
8
|
+
/**
|
|
9
|
+
* Hook to access loop metadata when inside a Loop component.
|
|
10
|
+
*
|
|
11
|
+
* Returns:
|
|
12
|
+
* { iteration, durationInFrames } - Current iteration (0-indexed) and loop duration
|
|
13
|
+
* null - If not inside a Loop
|
|
14
|
+
*
|
|
15
|
+
* Usage:
|
|
16
|
+
* const loop = Loop.useLoop();
|
|
17
|
+
* if (loop) {
|
|
18
|
+
* console.log(`Iteration ${loop.iteration + 1}`);
|
|
19
|
+
* }
|
|
20
|
+
*/
|
|
21
|
+
function useLoop() {
|
|
22
|
+
return useContext(LoopContext);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Loop repeats its children for a specified number of iterations.
|
|
26
|
+
*
|
|
27
|
+
* The frame counter resets at the start of each iteration, so children
|
|
28
|
+
* always see frames 0 to durationInFrames-1.
|
|
29
|
+
*
|
|
30
|
+
* Props:
|
|
31
|
+
* durationInFrames - Frames per iteration (required)
|
|
32
|
+
* times - Number of repetitions (default: Infinity)
|
|
33
|
+
* layout - 'absolute-fill' (default) or 'none'
|
|
34
|
+
* style - Additional CSS styles
|
|
35
|
+
* name - Optional label for debugging
|
|
36
|
+
*
|
|
37
|
+
* Usage:
|
|
38
|
+
* <Loop durationInFrames={30} times={3}>
|
|
39
|
+
* <PulseAnimation />
|
|
40
|
+
* </Loop>
|
|
41
|
+
*/
|
|
42
|
+
export function Loop({ durationInFrames, times = Infinity, layout = 'absolute-fill', style, name, children, }) {
|
|
43
|
+
const parent = useTimeline();
|
|
44
|
+
if (durationInFrames === undefined || durationInFrames <= 0) {
|
|
45
|
+
throw new Error('Loop requires a positive durationInFrames');
|
|
46
|
+
}
|
|
47
|
+
// Calculate which iteration we're on and the local frame within that iteration
|
|
48
|
+
const iteration = Math.floor(parent.frame / durationInFrames);
|
|
49
|
+
const localFrame = parent.frame % durationInFrames;
|
|
50
|
+
const contextValue = useMemo(() => ({
|
|
51
|
+
...parent,
|
|
52
|
+
frame: localFrame,
|
|
53
|
+
durationInFrames,
|
|
54
|
+
}), [parent, localFrame, durationInFrames]);
|
|
55
|
+
const loopValue = useMemo(() => ({
|
|
56
|
+
iteration,
|
|
57
|
+
durationInFrames,
|
|
58
|
+
}), [iteration, durationInFrames]);
|
|
59
|
+
const containerStyle = layout === 'absolute-fill'
|
|
60
|
+
? {
|
|
61
|
+
position: 'absolute',
|
|
62
|
+
top: 0,
|
|
63
|
+
left: 0,
|
|
64
|
+
right: 0,
|
|
65
|
+
bottom: 0,
|
|
66
|
+
...style,
|
|
67
|
+
}
|
|
68
|
+
: style;
|
|
69
|
+
// Check if we've exceeded the number of loops
|
|
70
|
+
if (times !== Infinity && iteration >= times) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
return (_jsx(LoopContext.Provider, { value: loopValue, children: _jsx(TimelineContext.Provider, { value: contextValue, children: _jsx("div", { style: containerStyle, "data-loop-name": name, "data-loop-iteration": iteration, children: children }) }) }));
|
|
74
|
+
}
|
|
75
|
+
// Attach the hook to the Loop component for convenient access
|
|
76
|
+
Loop.useLoop = useLoop;
|
|
77
|
+
export { useLoop };
|
|
78
|
+
export default Loop;
|
|
79
|
+
//# sourceMappingURL=Loop.js.map
|
package/dist/Loop.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Loop.js","sourceRoot":"","sources":["../src/Loop.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,OAAO,EAAE,aAAa,EAAE,UAAU,EAA4B,MAAM,OAAO,CAAC;AAC5F,OAAO,eAAe,EAAE,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AA8BzD;;GAEG;AACH,MAAM,WAAW,GAAG,aAAa,CAA0B,IAAI,CAAC,CAAC;AAEjE;;;;;;;;;;;;GAYG;AACH,SAAS,OAAO;IACd,OAAO,UAAU,CAAC,WAAW,CAAC,CAAC;AACjC,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,IAAI,CAAC,EACnB,gBAAgB,EAChB,KAAK,GAAG,QAAQ,EAChB,MAAM,GAAG,eAAe,EACxB,KAAK,EACL,IAAI,EACJ,QAAQ,GACE;IACV,MAAM,MAAM,GAAG,WAAW,EAAE,CAAC;IAE7B,IAAI,gBAAgB,KAAK,SAAS,IAAI,gBAAgB,IAAI,CAAC,EAAE,CAAC;QAC5D,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC/D,CAAC;IAED,+EAA+E;IAC/E,MAAM,SAAS,GAAW,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,GAAG,gBAAgB,CAAC,CAAC;IACtE,MAAM,UAAU,GAAW,MAAM,CAAC,KAAK,GAAG,gBAAgB,CAAC;IAE3D,MAAM,YAAY,GAAG,OAAO,CAC1B,GAAG,EAAE,CAAC,CAAC;QACL,GAAG,MAAM;QACT,KAAK,EAAE,UAAU;QACjB,gBAAgB;KACjB,CAAC,EACF,CAAC,MAAM,EAAE,UAAU,EAAE,gBAAgB,CAAC,CACvC,CAAC;IAEF,MAAM,SAAS,GAAqB,OAAO,CACzC,GAAG,EAAE,CAAC,CAAC;QACL,SAAS;QACT,gBAAgB;KACjB,CAAC,EACF,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAC9B,CAAC;IAEF,MAAM,cAAc,GAClB,MAAM,KAAK,eAAe;QACxB,CAAC,CAAC;YACE,QAAQ,EAAE,UAAmB;YAC7B,GAAG,EAAE,CAAC;YACN,IAAI,EAAE,CAAC;YACP,KAAK,EAAE,CAAC;YACR,MAAM,EAAE,CAAC;YACT,GAAG,KAAK;SACT;QACH,CAAC,CAAC,KAAK,CAAC;IAEZ,8CAA8C;IAC9C,IAAI,KAAK,KAAK,QAAQ,IAAI,SAAS,IAAI,KAAK,EAAE,CAAC;QAC7C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CACL,KAAC,WAAW,CAAC,QAAQ,IAAC,KAAK,EAAE,SAAS,YACpC,KAAC,eAAe,CAAC,QAAQ,IAAC,KAAK,EAAE,YAAY,YAC3C,cAAK,KAAK,EAAE,cAAc,oBAAkB,IAAI,yBAAuB,SAAS,YAC7E,QAAQ,GACL,GACmB,GACN,CACxB,CAAC;AACJ,CAAC;AAED,8DAA8D;AAC9D,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;AAEvB,OAAO,EAAE,OAAO,EAAE,CAAC;AACnB,eAAe,IAAI,CAAC"}
|