@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
package/dist/Series.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo, Children, createContext, useContext, } from 'react';
|
|
3
|
+
import TimelineContext, { useTimeline } from './context';
|
|
4
|
+
/**
|
|
5
|
+
* Context for Series.Sequence to access its calculated timing.
|
|
6
|
+
*/
|
|
7
|
+
const SeriesContext = createContext(null);
|
|
8
|
+
/**
|
|
9
|
+
* Series renders children sequentially, auto-calculating `from` for each.
|
|
10
|
+
*
|
|
11
|
+
* Unlike Sequence (which requires explicit `from` values), Series automatically
|
|
12
|
+
* places each child one after another in the timeline.
|
|
13
|
+
*
|
|
14
|
+
* Usage:
|
|
15
|
+
* <Series>
|
|
16
|
+
* <Series.Sequence durationInFrames={60}>
|
|
17
|
+
* <Scene1 />
|
|
18
|
+
* </Series.Sequence>
|
|
19
|
+
* <Series.Sequence durationInFrames={90}>
|
|
20
|
+
* <Scene2 />
|
|
21
|
+
* </Series.Sequence>
|
|
22
|
+
* </Series>
|
|
23
|
+
*/
|
|
24
|
+
const Series = function Series({ children }) {
|
|
25
|
+
const parent = useTimeline();
|
|
26
|
+
const childArray = Children.toArray(children);
|
|
27
|
+
// Calculate cumulative offsets for each child
|
|
28
|
+
const timings = useMemo(() => {
|
|
29
|
+
let currentOffset = 0;
|
|
30
|
+
return childArray.map((child) => {
|
|
31
|
+
const duration = child.props?.durationInFrames ?? 0;
|
|
32
|
+
const offset = child.props?.offset ?? 0;
|
|
33
|
+
const from = currentOffset + offset;
|
|
34
|
+
currentOffset = from + duration;
|
|
35
|
+
return { from, duration };
|
|
36
|
+
});
|
|
37
|
+
}, [childArray]);
|
|
38
|
+
return (_jsx(_Fragment, { children: childArray.map((child, index) => {
|
|
39
|
+
const { from, duration } = timings[index];
|
|
40
|
+
return (_jsx(SeriesContext.Provider, { value: { from, duration, index }, children: child }, index));
|
|
41
|
+
}) }));
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Series.Sequence represents a scene within a Series.
|
|
45
|
+
*
|
|
46
|
+
* Props:
|
|
47
|
+
* durationInFrames - How many frames this sequence lasts (required unless last)
|
|
48
|
+
* offset - Adjust timing: positive = delay, negative = overlap with previous
|
|
49
|
+
* layout - 'absolute-fill' (default) or 'none'
|
|
50
|
+
* style - Additional CSS styles
|
|
51
|
+
* name - Optional label for debugging
|
|
52
|
+
*/
|
|
53
|
+
Series.Sequence = function SeriesSequence({ durationInFrames, offset = 0, layout = 'absolute-fill', style, name, children, }) {
|
|
54
|
+
const parent = useTimeline();
|
|
55
|
+
const seriesContext = useContext(SeriesContext);
|
|
56
|
+
if (!seriesContext) {
|
|
57
|
+
throw new Error('Series.Sequence must be used within a Series');
|
|
58
|
+
}
|
|
59
|
+
const { from, duration } = seriesContext;
|
|
60
|
+
const actualDuration = durationInFrames ?? duration;
|
|
61
|
+
// Calculate the child's local frame
|
|
62
|
+
const localFrame = parent.frame - from;
|
|
63
|
+
const contextValue = useMemo(() => ({
|
|
64
|
+
...parent,
|
|
65
|
+
frame: localFrame,
|
|
66
|
+
durationInFrames: actualDuration,
|
|
67
|
+
}), [parent, localFrame, actualDuration]);
|
|
68
|
+
const containerStyle = layout === 'absolute-fill'
|
|
69
|
+
? {
|
|
70
|
+
position: 'absolute',
|
|
71
|
+
top: 0,
|
|
72
|
+
left: 0,
|
|
73
|
+
right: 0,
|
|
74
|
+
bottom: 0,
|
|
75
|
+
...style,
|
|
76
|
+
}
|
|
77
|
+
: style;
|
|
78
|
+
// Don't render if we're outside this sequence's range
|
|
79
|
+
if (localFrame < 0 || localFrame >= actualDuration) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
return (_jsx(TimelineContext.Provider, { value: contextValue, children: _jsx("div", { style: containerStyle, "data-series-sequence-name": name, children: children }) }));
|
|
83
|
+
};
|
|
84
|
+
export { Series };
|
|
85
|
+
export default Series;
|
|
86
|
+
//# sourceMappingURL=Series.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Series.js","sourceRoot":"","sources":["../src/Series.tsx"],"names":[],"mappings":"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"}
|
package/dist/Text.d.ts
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text Component
|
|
3
|
+
*
|
|
4
|
+
* Motion-graphics-grade text with character-level animation support.
|
|
5
|
+
* Automatically waits for font loading via delayRender.
|
|
6
|
+
*/
|
|
7
|
+
import React from 'react';
|
|
8
|
+
/** Props accepted by the per-character `<Span>` component. */
|
|
9
|
+
export interface CharSpanProps {
|
|
10
|
+
style?: React.CSSProperties;
|
|
11
|
+
className?: string;
|
|
12
|
+
}
|
|
13
|
+
/** Metadata for a single character produced by `splitText`. */
|
|
14
|
+
export interface CharData {
|
|
15
|
+
char: string;
|
|
16
|
+
index: number;
|
|
17
|
+
wordIndex: number;
|
|
18
|
+
lineIndex: number;
|
|
19
|
+
isWhitespace: boolean;
|
|
20
|
+
isNewline: boolean;
|
|
21
|
+
/** A component that renders this character inside a styleable `<span>`. */
|
|
22
|
+
Span: React.ComponentType<CharSpanProps>;
|
|
23
|
+
}
|
|
24
|
+
/** Text stroke configuration. */
|
|
25
|
+
export interface StrokeConfig {
|
|
26
|
+
color: string;
|
|
27
|
+
width: number;
|
|
28
|
+
}
|
|
29
|
+
/** Text shadow configuration. */
|
|
30
|
+
export interface ShadowConfig {
|
|
31
|
+
color: string;
|
|
32
|
+
blur?: number;
|
|
33
|
+
x?: number;
|
|
34
|
+
y?: number;
|
|
35
|
+
}
|
|
36
|
+
/** Word boundary descriptor returned by `getWords`. */
|
|
37
|
+
export interface WordData {
|
|
38
|
+
word: string;
|
|
39
|
+
startIndex: number;
|
|
40
|
+
endIndex: number;
|
|
41
|
+
wordIndex: number;
|
|
42
|
+
}
|
|
43
|
+
/** Props for the `<Text>` component. */
|
|
44
|
+
export interface TextProps {
|
|
45
|
+
/** The text to render. */
|
|
46
|
+
text: string;
|
|
47
|
+
/** Font size in pixels. @default 40 */
|
|
48
|
+
fontSize?: number;
|
|
49
|
+
/** Font family. @default 'sans-serif' */
|
|
50
|
+
fontFamily?: string;
|
|
51
|
+
/** Font weight. @default 400 */
|
|
52
|
+
fontWeight?: number | string;
|
|
53
|
+
/** Text color. @default 'white' */
|
|
54
|
+
color?: string;
|
|
55
|
+
/** Letter spacing in pixels. @default 0 */
|
|
56
|
+
letterSpacing?: number;
|
|
57
|
+
/** Line height multiplier. @default 1.2 */
|
|
58
|
+
lineHeight?: number;
|
|
59
|
+
/** Text alignment. @default 'left' */
|
|
60
|
+
textAlign?: 'left' | 'center' | 'right';
|
|
61
|
+
/** CSS text-transform value. @default 'none' */
|
|
62
|
+
textTransform?: React.CSSProperties['textTransform'];
|
|
63
|
+
/** CSS white-space value. @default 'pre-wrap' */
|
|
64
|
+
whiteSpace?: React.CSSProperties['whiteSpace'];
|
|
65
|
+
/** Text stroke configuration. */
|
|
66
|
+
stroke?: StrokeConfig;
|
|
67
|
+
/** Text shadow configuration. */
|
|
68
|
+
shadow?: ShadowConfig;
|
|
69
|
+
/** Additional container styles. */
|
|
70
|
+
style?: React.CSSProperties;
|
|
71
|
+
/** Container class name. */
|
|
72
|
+
className?: string;
|
|
73
|
+
/**
|
|
74
|
+
* Render function receiving character data.
|
|
75
|
+
*
|
|
76
|
+
* When provided as a function the component splits the text into
|
|
77
|
+
* individually styleable `<Span>` components, enabling per-character
|
|
78
|
+
* animation.
|
|
79
|
+
*/
|
|
80
|
+
children?: (chars: CharData[]) => React.ReactNode;
|
|
81
|
+
}
|
|
82
|
+
interface RawCharData {
|
|
83
|
+
char: string;
|
|
84
|
+
index: number;
|
|
85
|
+
wordIndex: number;
|
|
86
|
+
lineIndex: number;
|
|
87
|
+
isWhitespace: boolean;
|
|
88
|
+
isNewline: boolean;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Split text into character, word, and line metadata.
|
|
92
|
+
*
|
|
93
|
+
* @param text - Text to split
|
|
94
|
+
* @returns Array of per-character metadata objects
|
|
95
|
+
*/
|
|
96
|
+
export declare function splitText(text: string): RawCharData[];
|
|
97
|
+
/**
|
|
98
|
+
* Get word boundaries from split text.
|
|
99
|
+
*
|
|
100
|
+
* @param chars - Output of `splitText()`
|
|
101
|
+
* @returns Array of word boundary descriptors
|
|
102
|
+
*/
|
|
103
|
+
export declare function getWords(chars: RawCharData[]): WordData[];
|
|
104
|
+
/**
|
|
105
|
+
* Text component with character-level animation.
|
|
106
|
+
*
|
|
107
|
+
* Renders text with each character wrapped in an individually styleable span.
|
|
108
|
+
* Waits for fonts to load before rendering (via delayRender).
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* // Simple text
|
|
112
|
+
* <Text text="Hello World" fontSize={80} color="white" />
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* // Character-by-character animation
|
|
116
|
+
* <Text text="Animate Me" fontSize={60} fontFamily="Inter">
|
|
117
|
+
* {(chars) => chars.map((c, i) => (
|
|
118
|
+
* <c.Span key={i} style={{
|
|
119
|
+
* opacity: interpolate(frame, [i * 2, i * 2 + 10], [0, 1], { extrapolateRight: 'clamp' }),
|
|
120
|
+
* }} />
|
|
121
|
+
* ))}
|
|
122
|
+
* </Text>
|
|
123
|
+
*/
|
|
124
|
+
export declare function Text({ text, fontSize, fontFamily, fontWeight, color, letterSpacing, lineHeight, textAlign, textTransform, whiteSpace, stroke, shadow, style, className, children, }: TextProps): React.ReactElement;
|
|
125
|
+
export declare namespace Text {
|
|
126
|
+
var displayName: string;
|
|
127
|
+
}
|
|
128
|
+
export default Text;
|
|
129
|
+
//# sourceMappingURL=Text.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Text.d.ts","sourceRoot":"","sources":["../src/Text.tsx"],"names":[],"mappings":"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"}
|
package/dist/Text.js
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Text Component
|
|
4
|
+
*
|
|
5
|
+
* Motion-graphics-grade text with character-level animation support.
|
|
6
|
+
* Automatically waits for font loading via delayRender.
|
|
7
|
+
*/
|
|
8
|
+
import { useEffect, useRef, useMemo } from 'react';
|
|
9
|
+
import { delayRender, continueRender } from './delayRender';
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
// Utility functions
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
/**
|
|
14
|
+
* Split text into character, word, and line metadata.
|
|
15
|
+
*
|
|
16
|
+
* @param text - Text to split
|
|
17
|
+
* @returns Array of per-character metadata objects
|
|
18
|
+
*/
|
|
19
|
+
export function splitText(text) {
|
|
20
|
+
const chars = [];
|
|
21
|
+
let wordIndex = 0;
|
|
22
|
+
let lineIndex = 0;
|
|
23
|
+
for (let i = 0; i < text.length; i++) {
|
|
24
|
+
const char = text[i];
|
|
25
|
+
const isNewline = char === '\n';
|
|
26
|
+
const isWhitespace = /\s/.test(char);
|
|
27
|
+
chars.push({
|
|
28
|
+
char,
|
|
29
|
+
index: i,
|
|
30
|
+
wordIndex,
|
|
31
|
+
lineIndex,
|
|
32
|
+
isWhitespace,
|
|
33
|
+
isNewline,
|
|
34
|
+
});
|
|
35
|
+
if (isNewline) {
|
|
36
|
+
lineIndex++;
|
|
37
|
+
wordIndex++;
|
|
38
|
+
}
|
|
39
|
+
else if (isWhitespace) {
|
|
40
|
+
wordIndex++;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return chars;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Get word boundaries from split text.
|
|
47
|
+
*
|
|
48
|
+
* @param chars - Output of `splitText()`
|
|
49
|
+
* @returns Array of word boundary descriptors
|
|
50
|
+
*/
|
|
51
|
+
export function getWords(chars) {
|
|
52
|
+
const words = [];
|
|
53
|
+
let currentWord = '';
|
|
54
|
+
let startIndex = 0;
|
|
55
|
+
let currentWordIndex = -1;
|
|
56
|
+
for (const c of chars) {
|
|
57
|
+
if (c.isWhitespace || c.isNewline) {
|
|
58
|
+
if (currentWord.length > 0) {
|
|
59
|
+
words.push({
|
|
60
|
+
word: currentWord,
|
|
61
|
+
startIndex,
|
|
62
|
+
endIndex: c.index - 1,
|
|
63
|
+
wordIndex: currentWordIndex,
|
|
64
|
+
});
|
|
65
|
+
currentWord = '';
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
if (currentWord.length === 0) {
|
|
70
|
+
startIndex = c.index;
|
|
71
|
+
currentWordIndex = c.wordIndex;
|
|
72
|
+
}
|
|
73
|
+
currentWord += c.char;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (currentWord.length > 0) {
|
|
77
|
+
words.push({
|
|
78
|
+
word: currentWord,
|
|
79
|
+
startIndex,
|
|
80
|
+
endIndex: chars[chars.length - 1].index,
|
|
81
|
+
wordIndex: currentWordIndex,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
return words;
|
|
85
|
+
}
|
|
86
|
+
// ---------------------------------------------------------------------------
|
|
87
|
+
// Internal helpers
|
|
88
|
+
// ---------------------------------------------------------------------------
|
|
89
|
+
/** Generic font families that never need to be loaded. */
|
|
90
|
+
const GENERIC_FONTS = new Set([
|
|
91
|
+
'sans-serif',
|
|
92
|
+
'serif',
|
|
93
|
+
'monospace',
|
|
94
|
+
]);
|
|
95
|
+
/**
|
|
96
|
+
* Create a character span component for per-character styling.
|
|
97
|
+
*/
|
|
98
|
+
function createCharSpan(charInfo, _baseStyle) {
|
|
99
|
+
const CharSpan = ({ style: charStyle, className: charClassName, }) => {
|
|
100
|
+
if (charInfo.isNewline) {
|
|
101
|
+
return _jsx("br", {});
|
|
102
|
+
}
|
|
103
|
+
return (_jsx("span", { className: charClassName, style: {
|
|
104
|
+
display: 'inline-block',
|
|
105
|
+
whiteSpace: charInfo.isWhitespace ? 'pre' : undefined,
|
|
106
|
+
...charStyle,
|
|
107
|
+
}, children: charInfo.char }));
|
|
108
|
+
};
|
|
109
|
+
CharSpan.displayName = `Char(${charInfo.char === ' ' ? 'space' : charInfo.char})`;
|
|
110
|
+
return CharSpan;
|
|
111
|
+
}
|
|
112
|
+
// ---------------------------------------------------------------------------
|
|
113
|
+
// Text component
|
|
114
|
+
// ---------------------------------------------------------------------------
|
|
115
|
+
/**
|
|
116
|
+
* Text component with character-level animation.
|
|
117
|
+
*
|
|
118
|
+
* Renders text with each character wrapped in an individually styleable span.
|
|
119
|
+
* Waits for fonts to load before rendering (via delayRender).
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* // Simple text
|
|
123
|
+
* <Text text="Hello World" fontSize={80} color="white" />
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* // Character-by-character animation
|
|
127
|
+
* <Text text="Animate Me" fontSize={60} fontFamily="Inter">
|
|
128
|
+
* {(chars) => chars.map((c, i) => (
|
|
129
|
+
* <c.Span key={i} style={{
|
|
130
|
+
* opacity: interpolate(frame, [i * 2, i * 2 + 10], [0, 1], { extrapolateRight: 'clamp' }),
|
|
131
|
+
* }} />
|
|
132
|
+
* ))}
|
|
133
|
+
* </Text>
|
|
134
|
+
*/
|
|
135
|
+
export function Text({ text, fontSize = 40, fontFamily = 'sans-serif', fontWeight = 400, color = 'white', letterSpacing = 0, lineHeight = 1.2, textAlign = 'left', textTransform = 'none', whiteSpace = 'pre-wrap', stroke, shadow, style, className, children, }) {
|
|
136
|
+
const delayHandle = useRef(null);
|
|
137
|
+
// Wait for font to load
|
|
138
|
+
useEffect(() => {
|
|
139
|
+
if (GENERIC_FONTS.has(fontFamily)) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const handle = delayRender(`Loading font: ${fontFamily}`);
|
|
143
|
+
delayHandle.current = handle;
|
|
144
|
+
document.fonts.ready
|
|
145
|
+
.then(() => {
|
|
146
|
+
continueRender(handle);
|
|
147
|
+
delayHandle.current = null;
|
|
148
|
+
})
|
|
149
|
+
.catch(() => {
|
|
150
|
+
// Continue even if font check fails
|
|
151
|
+
continueRender(handle);
|
|
152
|
+
delayHandle.current = null;
|
|
153
|
+
});
|
|
154
|
+
return () => {
|
|
155
|
+
if (delayHandle.current !== null) {
|
|
156
|
+
continueRender(delayHandle.current);
|
|
157
|
+
delayHandle.current = null;
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
}, [fontFamily]);
|
|
161
|
+
// Build base styles
|
|
162
|
+
const baseStyle = useMemo(() => {
|
|
163
|
+
const s = {
|
|
164
|
+
fontSize,
|
|
165
|
+
fontFamily,
|
|
166
|
+
fontWeight,
|
|
167
|
+
color,
|
|
168
|
+
letterSpacing: letterSpacing !== 0 ? `${letterSpacing}px` : undefined,
|
|
169
|
+
lineHeight,
|
|
170
|
+
textAlign,
|
|
171
|
+
textTransform,
|
|
172
|
+
whiteSpace,
|
|
173
|
+
margin: 0,
|
|
174
|
+
padding: 0,
|
|
175
|
+
...style,
|
|
176
|
+
};
|
|
177
|
+
if (stroke) {
|
|
178
|
+
s.WebkitTextStroke = `${stroke.width}px ${stroke.color}`;
|
|
179
|
+
}
|
|
180
|
+
if (shadow) {
|
|
181
|
+
s.textShadow = `${shadow.x || 0}px ${shadow.y || 0}px ${shadow.blur || 0}px ${shadow.color}`;
|
|
182
|
+
}
|
|
183
|
+
return s;
|
|
184
|
+
}, [
|
|
185
|
+
fontSize, fontFamily, fontWeight, color, letterSpacing,
|
|
186
|
+
lineHeight, textAlign, textTransform, whiteSpace,
|
|
187
|
+
stroke?.color, stroke?.width,
|
|
188
|
+
shadow?.color, shadow?.blur, shadow?.x, shadow?.y,
|
|
189
|
+
style,
|
|
190
|
+
]);
|
|
191
|
+
// Split text and create character data with Span components
|
|
192
|
+
const charData = useMemo(() => {
|
|
193
|
+
const chars = splitText(text);
|
|
194
|
+
return chars.map((c) => ({
|
|
195
|
+
...c,
|
|
196
|
+
Span: createCharSpan(c, baseStyle),
|
|
197
|
+
}));
|
|
198
|
+
}, [text, baseStyle]);
|
|
199
|
+
// If no children function, render simple text
|
|
200
|
+
if (typeof children !== 'function') {
|
|
201
|
+
return (_jsx("div", { className: className, style: baseStyle, children: text }));
|
|
202
|
+
}
|
|
203
|
+
return (_jsx("div", { className: className, style: {
|
|
204
|
+
...baseStyle,
|
|
205
|
+
// Reset text properties on container — chars handle their own
|
|
206
|
+
display: 'inline',
|
|
207
|
+
}, children: children(charData) }));
|
|
208
|
+
}
|
|
209
|
+
Text.displayName = 'Text';
|
|
210
|
+
export default Text;
|
|
211
|
+
//# sourceMappingURL=Text.js.map
|
package/dist/Text.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Text.js","sourceRoot":"","sources":["../src/Text.tsx"],"names":[],"mappings":"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"}
|
package/dist/Video.d.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { type CSSProperties, type SyntheticEvent } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* A volume value can be a static number (0-1) or a callback that receives the
|
|
4
|
+
* current frame and returns a number (0-1). The callback form is useful for
|
|
5
|
+
* animating volume over time (e.g. fade-in/fade-out).
|
|
6
|
+
*/
|
|
7
|
+
export type VolumeCallback = (frame: number) => number;
|
|
8
|
+
/**
|
|
9
|
+
* Props accepted by the Video component.
|
|
10
|
+
*
|
|
11
|
+
* Extends the standard HTML `<video>` attributes so that any native prop
|
|
12
|
+
* (e.g. `crossOrigin`, `poster`, `preload`) can be forwarded directly.
|
|
13
|
+
*/
|
|
14
|
+
export interface VideoProps extends Omit<React.VideoHTMLAttributes<HTMLVideoElement>, 'volume' | 'playbackRate' | 'muted' | 'loop' | 'onError'> {
|
|
15
|
+
/** Video source URL. Use `staticFile()` for local assets. */
|
|
16
|
+
src: string;
|
|
17
|
+
/**
|
|
18
|
+
* Volume level (0-1), or a callback `(frame) => number` for dynamic volume.
|
|
19
|
+
* Clamped to the 0-1 range at runtime.
|
|
20
|
+
* @default 1
|
|
21
|
+
*/
|
|
22
|
+
volume?: number | VolumeCallback;
|
|
23
|
+
/**
|
|
24
|
+
* Playback speed multiplier.
|
|
25
|
+
* @default 1
|
|
26
|
+
*/
|
|
27
|
+
playbackRate?: number;
|
|
28
|
+
/**
|
|
29
|
+
* Whether to mute audio.
|
|
30
|
+
* @default false
|
|
31
|
+
*/
|
|
32
|
+
muted?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Whether the video should loop.
|
|
35
|
+
* @default false
|
|
36
|
+
*/
|
|
37
|
+
loop?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Frame index from which the video should start playing (0-based).
|
|
40
|
+
* @default 0
|
|
41
|
+
*/
|
|
42
|
+
startFrom?: number;
|
|
43
|
+
/**
|
|
44
|
+
* Frame index at which the video should stop (exclusive).
|
|
45
|
+
* If omitted the video plays until its natural end.
|
|
46
|
+
*/
|
|
47
|
+
endAt?: number;
|
|
48
|
+
/** Optional CSS styles applied to the `<video>` element. */
|
|
49
|
+
style?: CSSProperties;
|
|
50
|
+
/** Optional CSS class name applied to the `<video>` element. */
|
|
51
|
+
className?: string;
|
|
52
|
+
/** Called when the video element encounters an error. */
|
|
53
|
+
onError?: (event: SyntheticEvent<HTMLVideoElement, Event>) => void;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Video component that syncs with the Framely timeline.
|
|
57
|
+
*
|
|
58
|
+
* The video's playback position is controlled by the current frame,
|
|
59
|
+
* ensuring perfect sync between the video and your composition.
|
|
60
|
+
*
|
|
61
|
+
* Usage:
|
|
62
|
+
* import { Video, staticFile } from './lib';
|
|
63
|
+
*
|
|
64
|
+
* <Video src={staticFile('videos/intro.mp4')} />
|
|
65
|
+
* <Video src={staticFile('videos/bg.mp4')} volume={0.5} muted />
|
|
66
|
+
* <Video
|
|
67
|
+
* src={staticFile('videos/clip.mp4')}
|
|
68
|
+
* startFrom={30}
|
|
69
|
+
* endAt={90}
|
|
70
|
+
* volume={(frame) => interpolate(frame, [0, 30], [0, 1])}
|
|
71
|
+
* />
|
|
72
|
+
*/
|
|
73
|
+
export declare function Video({ src, volume, playbackRate, muted, loop, startFrom, endAt, style, className, onError, ...rest }: VideoProps): JSX.Element | null;
|
|
74
|
+
export default Video;
|
|
75
|
+
//# sourceMappingURL=Video.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Video.d.ts","sourceRoot":"","sources":["../src/Video.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,aAAa,EAClB,KAAK,cAAc,EACpB,MAAM,OAAO,CAAC;AAMf;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;AAEvD;;;;;GAKG;AACH,MAAM,WAAW,UACf,SAAQ,IAAI,CACV,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAC3C,QAAQ,GAAG,cAAc,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CACzD;IACD,6DAA6D;IAC7D,GAAG,EAAE,MAAM,CAAC;IAEZ;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,cAAc,CAAC;IAEjC;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,4DAA4D;IAC5D,KAAK,CAAC,EAAE,aAAa,CAAC;IAEtB,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,yDAAyD;IACzD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,CAAC,gBAAgB,EAAE,KAAK,CAAC,KAAK,IAAI,CAAC;CACpE;AAID;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,KAAK,CAAC,EACpB,GAAG,EACH,MAAU,EACV,YAAgB,EAChB,KAAa,EACb,IAAY,EACZ,SAAa,EACb,KAAK,EACL,KAAK,EACL,SAAS,EACT,OAAO,EACP,GAAG,IAAI,EACR,EAAE,UAAU,GAAG,GAAG,CAAC,OAAO,GAAG,IAAI,CAmIjC;AAED,eAAe,KAAK,CAAC"}
|
package/dist/Video.js
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef, useState, useMemo, } from 'react';
|
|
3
|
+
import { useTimeline } from './context';
|
|
4
|
+
import { delayRender, continueRender, cancelRender } from './delayRender';
|
|
5
|
+
// ─── Component ────────────────────────────────────────────────────────────────
|
|
6
|
+
/**
|
|
7
|
+
* Video component that syncs with the Framely timeline.
|
|
8
|
+
*
|
|
9
|
+
* The video's playback position is controlled by the current frame,
|
|
10
|
+
* ensuring perfect sync between the video and your composition.
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* import { Video, staticFile } from './lib';
|
|
14
|
+
*
|
|
15
|
+
* <Video src={staticFile('videos/intro.mp4')} />
|
|
16
|
+
* <Video src={staticFile('videos/bg.mp4')} volume={0.5} muted />
|
|
17
|
+
* <Video
|
|
18
|
+
* src={staticFile('videos/clip.mp4')}
|
|
19
|
+
* startFrom={30}
|
|
20
|
+
* endAt={90}
|
|
21
|
+
* volume={(frame) => interpolate(frame, [0, 30], [0, 1])}
|
|
22
|
+
* />
|
|
23
|
+
*/
|
|
24
|
+
export function Video({ src, volume = 1, playbackRate = 1, muted = false, loop = false, startFrom = 0, endAt, style, className, onError, ...rest }) {
|
|
25
|
+
const { frame, fps, playing } = useTimeline();
|
|
26
|
+
const videoRef = useRef(null);
|
|
27
|
+
const handleRef = useRef(null);
|
|
28
|
+
const [ready, setReady] = useState(false);
|
|
29
|
+
// Calculate the actual volume (support callback)
|
|
30
|
+
const actualVolume = useMemo(() => {
|
|
31
|
+
if (typeof volume === 'function') {
|
|
32
|
+
return Math.max(0, Math.min(1, volume(frame)));
|
|
33
|
+
}
|
|
34
|
+
return Math.max(0, Math.min(1, volume));
|
|
35
|
+
}, [volume, frame]);
|
|
36
|
+
// Calculate target time based on frame
|
|
37
|
+
const targetTime = useMemo(() => {
|
|
38
|
+
const relativeFrame = frame - startFrom;
|
|
39
|
+
if (relativeFrame < 0)
|
|
40
|
+
return 0;
|
|
41
|
+
return relativeFrame / fps;
|
|
42
|
+
}, [frame, startFrom, fps]);
|
|
43
|
+
// Check if we're within the video's active range
|
|
44
|
+
const isActive = useMemo(() => {
|
|
45
|
+
if (frame < startFrom)
|
|
46
|
+
return false;
|
|
47
|
+
if (endAt !== undefined && frame >= endAt)
|
|
48
|
+
return false;
|
|
49
|
+
return true;
|
|
50
|
+
}, [frame, startFrom, endAt]);
|
|
51
|
+
// Delay render until video is ready
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
handleRef.current = delayRender(`Loading video: ${src}`, {
|
|
54
|
+
timeoutInMilliseconds: 30000,
|
|
55
|
+
});
|
|
56
|
+
return () => {
|
|
57
|
+
if (handleRef.current !== null) {
|
|
58
|
+
continueRender(handleRef.current);
|
|
59
|
+
handleRef.current = null;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
}, [src]);
|
|
63
|
+
// Handle video ready state
|
|
64
|
+
const handleCanPlay = () => {
|
|
65
|
+
setReady(true);
|
|
66
|
+
if (handleRef.current !== null) {
|
|
67
|
+
continueRender(handleRef.current);
|
|
68
|
+
handleRef.current = null;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
// Handle video error
|
|
72
|
+
const handleError = (event) => {
|
|
73
|
+
const err = new Error(`Failed to load video: ${src}`);
|
|
74
|
+
onError?.(event);
|
|
75
|
+
if (handleRef.current !== null) {
|
|
76
|
+
cancelRender(err);
|
|
77
|
+
handleRef.current = null;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
// Sync video time with frame
|
|
81
|
+
useEffect(() => {
|
|
82
|
+
const video = videoRef.current;
|
|
83
|
+
if (!video || !ready)
|
|
84
|
+
return;
|
|
85
|
+
// Only seek if we're more than half a frame off
|
|
86
|
+
const tolerance = 0.5 / fps;
|
|
87
|
+
if (Math.abs(video.currentTime - targetTime) > tolerance) {
|
|
88
|
+
video.currentTime = targetTime;
|
|
89
|
+
}
|
|
90
|
+
}, [targetTime, ready, fps]);
|
|
91
|
+
// Sync volume
|
|
92
|
+
useEffect(() => {
|
|
93
|
+
const video = videoRef.current;
|
|
94
|
+
if (!video)
|
|
95
|
+
return;
|
|
96
|
+
video.volume = actualVolume;
|
|
97
|
+
}, [actualVolume]);
|
|
98
|
+
// Sync playback rate
|
|
99
|
+
useEffect(() => {
|
|
100
|
+
const video = videoRef.current;
|
|
101
|
+
if (!video)
|
|
102
|
+
return;
|
|
103
|
+
video.playbackRate = playbackRate;
|
|
104
|
+
}, [playbackRate]);
|
|
105
|
+
// Sync muted state
|
|
106
|
+
useEffect(() => {
|
|
107
|
+
const video = videoRef.current;
|
|
108
|
+
if (!video)
|
|
109
|
+
return;
|
|
110
|
+
video.muted = muted;
|
|
111
|
+
}, [muted]);
|
|
112
|
+
// Handle play/pause (for preview mode)
|
|
113
|
+
useEffect(() => {
|
|
114
|
+
const video = videoRef.current;
|
|
115
|
+
if (!video || !ready)
|
|
116
|
+
return;
|
|
117
|
+
if (playing && isActive) {
|
|
118
|
+
video.play().catch(() => {
|
|
119
|
+
// Autoplay might be blocked, that's okay
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
video.pause();
|
|
124
|
+
}
|
|
125
|
+
}, [playing, ready, isActive]);
|
|
126
|
+
// Don't render if outside active range
|
|
127
|
+
if (!isActive) {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
return (_jsx("video", { ref: videoRef, src: src, style: {
|
|
131
|
+
...style,
|
|
132
|
+
opacity: ready ? (style?.opacity ?? 1) : 0,
|
|
133
|
+
}, className: className, onCanPlayThrough: handleCanPlay, onError: handleError, playsInline: true, preload: "auto", loop: loop, ...rest }));
|
|
134
|
+
}
|
|
135
|
+
export default Video;
|
|
136
|
+
//# sourceMappingURL=Video.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Video.js","sourceRoot":"","sources":["../src/Video.tsx"],"names":[],"mappings":"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"}
|