@effing/effie-preview 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/LICENSE +11 -0
- package/README.md +317 -0
- package/dist/index.d.ts +102 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/react/index.d.ts +229 -0
- package/dist/react/index.js +622 -0
- package/dist/react/index.js.map +1 -0
- package/package.json +55 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
O'Saasy License
|
|
2
|
+
|
|
3
|
+
Copyright © 2026, Trackuity BV.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
+
|
|
7
|
+
1. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
+
|
|
9
|
+
2. No licensee or downstream recipient may use the Software (including any modified or derivative versions) to directly compete with the original Licensor by offering it to third parties as a hosted, managed, or Software-as-a-Service (SaaS) product or cloud service where the primary value of the service is the functionality of the Software itself.
|
|
10
|
+
|
|
11
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
# @effing/effie-preview
|
|
2
|
+
|
|
3
|
+
**Preview components for Effie video compositions.**
|
|
4
|
+
|
|
5
|
+
> Part of the [**Effing**](../../README.md) family — programmatic video creation with TypeScript.
|
|
6
|
+
|
|
7
|
+
Preview covers, backgrounds, layers, and segments before rendering. Uses `@effing/annie-player` for animation playback.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @effing/effie-preview @effing/effie @effing/annie-player
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
Components support two usage patterns:
|
|
18
|
+
|
|
19
|
+
### Simple API (built-in styles)
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import { createEffieSourceResolver } from "@effing/effie-preview";
|
|
23
|
+
import {
|
|
24
|
+
EffieCoverPreview,
|
|
25
|
+
EffieBackgroundPreview,
|
|
26
|
+
EffieSegmentPreview,
|
|
27
|
+
} from "@effing/effie-preview/react";
|
|
28
|
+
|
|
29
|
+
function EffiePreview({ effieJson, renderedVideoUrl }) {
|
|
30
|
+
const resolveSource = createEffieSourceResolver(effieJson.sources);
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<div>
|
|
34
|
+
<h2>Cover</h2>
|
|
35
|
+
<EffieCoverPreview cover={effieJson.cover} video={renderedVideoUrl} />
|
|
36
|
+
|
|
37
|
+
<h2>Background</h2>
|
|
38
|
+
<EffieBackgroundPreview
|
|
39
|
+
background={effieJson.background}
|
|
40
|
+
resolveSource={resolveSource}
|
|
41
|
+
/>
|
|
42
|
+
|
|
43
|
+
<h2>Segments</h2>
|
|
44
|
+
{effieJson.segments.map((segment, i) => (
|
|
45
|
+
<EffieSegmentPreview
|
|
46
|
+
key={i}
|
|
47
|
+
segment={segment}
|
|
48
|
+
index={i}
|
|
49
|
+
resolveSource={resolveSource}
|
|
50
|
+
/>
|
|
51
|
+
))}
|
|
52
|
+
</div>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Compound API (full control)
|
|
58
|
+
|
|
59
|
+
For custom layouts, use the compound sub-components:
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
import {
|
|
63
|
+
EffieBackgroundPreview,
|
|
64
|
+
EffieSegmentPreview,
|
|
65
|
+
EffieLayerPreview,
|
|
66
|
+
} from "@effing/effie-preview/react";
|
|
67
|
+
|
|
68
|
+
function CustomLayout({ effieJson }) {
|
|
69
|
+
const resolveSource = createEffieSourceResolver(effieJson.sources);
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<div>
|
|
73
|
+
{/* Background with custom layout */}
|
|
74
|
+
<EffieBackgroundPreview.Root style={{ display: "grid", gap: "2rem" }}>
|
|
75
|
+
<EffieBackgroundPreview.Media
|
|
76
|
+
background={effieJson.background}
|
|
77
|
+
resolveSource={resolveSource}
|
|
78
|
+
style={{ height: 300, objectFit: "cover" }}
|
|
79
|
+
/>
|
|
80
|
+
<EffieBackgroundPreview.Info
|
|
81
|
+
background={effieJson.background}
|
|
82
|
+
style={{ fontSize: "0.9rem" }}
|
|
83
|
+
/>
|
|
84
|
+
</EffieBackgroundPreview.Root>
|
|
85
|
+
|
|
86
|
+
{/* Segments with custom layer layout */}
|
|
87
|
+
{effieJson.segments.map((segment, i) => (
|
|
88
|
+
<EffieSegmentPreview.Root key={i} style={{ padding: "2rem" }}>
|
|
89
|
+
<EffieSegmentPreview.Header style={{ fontWeight: 700 }}>
|
|
90
|
+
Segment {i + 1} — {segment.duration}s
|
|
91
|
+
</EffieSegmentPreview.Header>
|
|
92
|
+
<EffieSegmentPreview.Layers
|
|
93
|
+
style={{ display: "grid", gridTemplateColumns: "repeat(2, 1fr)" }}
|
|
94
|
+
>
|
|
95
|
+
{segment.layers.map((layer, j) => (
|
|
96
|
+
<EffieLayerPreview.Root key={j}>
|
|
97
|
+
<EffieLayerPreview.Media
|
|
98
|
+
layer={layer}
|
|
99
|
+
index={j}
|
|
100
|
+
resolveSource={resolveSource}
|
|
101
|
+
resolution={{ width: 356, height: 200 }}
|
|
102
|
+
/>
|
|
103
|
+
<EffieLayerPreview.Info layer={layer} index={j} />
|
|
104
|
+
</EffieLayerPreview.Root>
|
|
105
|
+
))}
|
|
106
|
+
</EffieSegmentPreview.Layers>
|
|
107
|
+
</EffieSegmentPreview.Root>
|
|
108
|
+
))}
|
|
109
|
+
</div>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Concepts
|
|
115
|
+
|
|
116
|
+
### Source Resolution
|
|
117
|
+
|
|
118
|
+
Effie compositions can reference sources by name (`#mySource`) instead of full URLs. The preview components use a source resolver to look up these references:
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
import { createEffieSourceResolver } from "@effing/effie-preview";
|
|
122
|
+
|
|
123
|
+
const resolve = createEffieSourceResolver(effieJson.sources);
|
|
124
|
+
resolve("#background"); // Returns the actual URL
|
|
125
|
+
resolve("https://..."); // Returns as-is
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## API Overview
|
|
129
|
+
|
|
130
|
+
### Core
|
|
131
|
+
|
|
132
|
+
#### `createEffieSourceResolver(sources?)`
|
|
133
|
+
|
|
134
|
+
Create a function that resolves source references:
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
function createEffieSourceResolver(sources?: EffieSources): EffieSourceResolver;
|
|
138
|
+
|
|
139
|
+
type EffieSourceResolver = (src: string) => string;
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### React Components
|
|
143
|
+
|
|
144
|
+
All preview components support both simple and compound usage patterns.
|
|
145
|
+
|
|
146
|
+
#### `EffieCoverPreview`
|
|
147
|
+
|
|
148
|
+
Display the cover image, or a video player if a rendered video is available.
|
|
149
|
+
|
|
150
|
+
```tsx
|
|
151
|
+
<EffieCoverPreview
|
|
152
|
+
cover={EffieWebUrl} // Cover image URL
|
|
153
|
+
resolution={{ width, height }} // Preview resolution
|
|
154
|
+
video={string | null} // Optional rendered video URL
|
|
155
|
+
onPlay={() => void} // Callback when video starts playing
|
|
156
|
+
onFullyBuffered={() => void} // Callback when video is fully buffered
|
|
157
|
+
className={string} // Class name for img/video element
|
|
158
|
+
style={CSSProperties} // Style for img/video element
|
|
159
|
+
/>
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
#### `EffieBackgroundPreview`
|
|
163
|
+
|
|
164
|
+
Preview the composition background (color, image, or video).
|
|
165
|
+
|
|
166
|
+
**Simple:**
|
|
167
|
+
|
|
168
|
+
```tsx
|
|
169
|
+
<EffieBackgroundPreview
|
|
170
|
+
background={EffieBackground}
|
|
171
|
+
resolveSource={EffieSourceResolver}
|
|
172
|
+
resolution={{ width, height }}
|
|
173
|
+
className={string}
|
|
174
|
+
style={CSSProperties}
|
|
175
|
+
/>
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
**Compound:**
|
|
179
|
+
|
|
180
|
+
```tsx
|
|
181
|
+
<EffieBackgroundPreview.Root className={string} style={CSSProperties}>
|
|
182
|
+
<EffieBackgroundPreview.Media
|
|
183
|
+
background={EffieBackground}
|
|
184
|
+
resolveSource={EffieSourceResolver}
|
|
185
|
+
className={string}
|
|
186
|
+
style={CSSProperties}
|
|
187
|
+
/>
|
|
188
|
+
<EffieBackgroundPreview.Info
|
|
189
|
+
background={EffieBackground}
|
|
190
|
+
className={string}
|
|
191
|
+
style={CSSProperties}
|
|
192
|
+
/>
|
|
193
|
+
</EffieBackgroundPreview.Root>
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
#### `EffieSegmentPreview`
|
|
197
|
+
|
|
198
|
+
Preview a segment with all its layers. The `stacking` prop controls how layers are arranged:
|
|
199
|
+
|
|
200
|
+
- `"vertical"` (default): layers stack vertically, info beside each layer
|
|
201
|
+
- `"horizontal"`: layers flow horizontally, info below each layer
|
|
202
|
+
|
|
203
|
+
**Simple:**
|
|
204
|
+
|
|
205
|
+
```tsx
|
|
206
|
+
<EffieSegmentPreview
|
|
207
|
+
segment={EffieSegment}
|
|
208
|
+
index={number}
|
|
209
|
+
resolveSource={EffieSourceResolver}
|
|
210
|
+
resolution={{ width, height }}
|
|
211
|
+
stacking={"vertical" | "horizontal"} // Default: "vertical"
|
|
212
|
+
className={string}
|
|
213
|
+
style={CSSProperties}
|
|
214
|
+
/>
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
**Compound:**
|
|
218
|
+
|
|
219
|
+
```tsx
|
|
220
|
+
<EffieSegmentPreview.Root className={string} style={CSSProperties}>
|
|
221
|
+
<EffieSegmentPreview.Header className={string} style={CSSProperties}>
|
|
222
|
+
{children}
|
|
223
|
+
</EffieSegmentPreview.Header>
|
|
224
|
+
<EffieSegmentPreview.Layers className={string} style={CSSProperties}>
|
|
225
|
+
{children}
|
|
226
|
+
</EffieSegmentPreview.Layers>
|
|
227
|
+
</EffieSegmentPreview.Root>
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
#### `EffieLayerPreview`
|
|
231
|
+
|
|
232
|
+
Preview a single layer (image or animation). The `stacking` prop controls layout:
|
|
233
|
+
|
|
234
|
+
- `"horizontal"` (default): info beside media (flex row)
|
|
235
|
+
- `"vertical"`: info below media (flex column)
|
|
236
|
+
|
|
237
|
+
**Simple:**
|
|
238
|
+
|
|
239
|
+
```tsx
|
|
240
|
+
<EffieLayerPreview
|
|
241
|
+
layer={EffieLayer}
|
|
242
|
+
index={number}
|
|
243
|
+
resolveSource={EffieSourceResolver}
|
|
244
|
+
resolution={{ width, height }}
|
|
245
|
+
stacking={"vertical" | "horizontal"} // Default: "horizontal"
|
|
246
|
+
className={string}
|
|
247
|
+
style={CSSProperties}
|
|
248
|
+
/>
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
**Compound:**
|
|
252
|
+
|
|
253
|
+
```tsx
|
|
254
|
+
<EffieLayerPreview.Root className={string} style={CSSProperties}>
|
|
255
|
+
<EffieLayerPreview.Media
|
|
256
|
+
layer={EffieLayer}
|
|
257
|
+
index={number}
|
|
258
|
+
resolveSource={EffieSourceResolver}
|
|
259
|
+
resolution={{ width, height }}
|
|
260
|
+
className={string}
|
|
261
|
+
style={CSSProperties}
|
|
262
|
+
/>
|
|
263
|
+
<EffieLayerPreview.Info
|
|
264
|
+
layer={EffieLayer}
|
|
265
|
+
index={number}
|
|
266
|
+
className={string}
|
|
267
|
+
style={CSSProperties}
|
|
268
|
+
/>
|
|
269
|
+
</EffieLayerPreview.Root>
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
For animation layers, `EffieLayerPreview.Media` renders an `AnniePlayer` with load/play controls.
|
|
273
|
+
|
|
274
|
+
### Validation Errors
|
|
275
|
+
|
|
276
|
+
#### `parseEffieValidationIssues(issues)`
|
|
277
|
+
|
|
278
|
+
Parse validation issues from an error response:
|
|
279
|
+
|
|
280
|
+
```typescript
|
|
281
|
+
import { parseEffieValidationIssues } from "@effing/effie-preview";
|
|
282
|
+
|
|
283
|
+
const response = await fetch("ffs.example.com/render", {
|
|
284
|
+
method: "POST",
|
|
285
|
+
body,
|
|
286
|
+
});
|
|
287
|
+
if (!response.ok) {
|
|
288
|
+
const errorBody = await response.json();
|
|
289
|
+
const issues = parseEffieValidationIssues(errorBody.issues);
|
|
290
|
+
// issues: EffieValidationIssue[] | undefined
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
#### `EffieValidationErrors`
|
|
295
|
+
|
|
296
|
+
Display validation errors with detailed issue breakdown:
|
|
297
|
+
|
|
298
|
+
```tsx
|
|
299
|
+
import { EffieValidationErrors } from "@effing/effie-preview/react";
|
|
300
|
+
|
|
301
|
+
<EffieValidationErrors
|
|
302
|
+
error={string} // Error message (e.g., "Invalid effie data")
|
|
303
|
+
issues={EffieValidationIssue[]} // Optional list of validation issues
|
|
304
|
+
className={string}
|
|
305
|
+
style={CSSProperties}
|
|
306
|
+
/>
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
Each `EffieValidationIssue` contains:
|
|
310
|
+
|
|
311
|
+
- `path` — Path to the field that failed validation (e.g., `"segments.0.transition.sweep"`)
|
|
312
|
+
- `message` — Human-readable error message
|
|
313
|
+
|
|
314
|
+
## Related Packages
|
|
315
|
+
|
|
316
|
+
- [`@effing/effie`](../effie) — Video composition types
|
|
317
|
+
- [`@effing/annie-player`](../annie-player) — Animation playback (used internally)
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { EffieSources } from '@effing/effie';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Create a source resolver function that handles #reference lookups
|
|
5
|
+
* in effie source fields.
|
|
6
|
+
*
|
|
7
|
+
* @param sources - The sources map from an EffieData object
|
|
8
|
+
* @returns A function that resolves source references to URLs
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* const resolve = createEffieSourceResolver(effieJson.sources);
|
|
13
|
+
* const url = resolve(layer.source); // Handles both "#ref" and direct URLs
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
declare function createEffieSourceResolver(sources?: EffieSources): (src: string) => string;
|
|
17
|
+
/**
|
|
18
|
+
* Type alias for a source resolver function
|
|
19
|
+
*/
|
|
20
|
+
type EffieSourceResolver = ReturnType<typeof createEffieSourceResolver>;
|
|
21
|
+
/**
|
|
22
|
+
* Represents a validation issue from EffieData schema validation.
|
|
23
|
+
*/
|
|
24
|
+
type EffieValidationIssue = {
|
|
25
|
+
/** Path to the field that failed validation (e.g., "segments.0.transition.sweep") */
|
|
26
|
+
path: string;
|
|
27
|
+
/** Human-readable error message */
|
|
28
|
+
message: string;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Parse an unknown value as an array of validation issues.
|
|
32
|
+
*
|
|
33
|
+
* @param issues - The issues value to parse (typically from errorBody.issues)
|
|
34
|
+
* @returns Array of validation issues, or undefined if not a valid array
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* const errorBody = await response.json();
|
|
39
|
+
* const issues = parseEffieValidationIssues(errorBody.issues);
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
declare function parseEffieValidationIssues(issues: unknown): EffieValidationIssue[] | undefined;
|
|
43
|
+
|
|
44
|
+
/** Progress event when a source is processed */
|
|
45
|
+
type EffieWarmupProgressEvent = {
|
|
46
|
+
url: string;
|
|
47
|
+
status: "hit" | "cached" | "error";
|
|
48
|
+
cached: number;
|
|
49
|
+
failed: number;
|
|
50
|
+
total: number;
|
|
51
|
+
ms?: number;
|
|
52
|
+
error?: string;
|
|
53
|
+
};
|
|
54
|
+
/** Downloading event during source fetch */
|
|
55
|
+
type EffieWarmupDownloadingEvent = {
|
|
56
|
+
url: string;
|
|
57
|
+
status: "started" | "downloading";
|
|
58
|
+
bytesReceived: number;
|
|
59
|
+
};
|
|
60
|
+
/** Union of all SSE event types */
|
|
61
|
+
type EffieWarmupEvent = {
|
|
62
|
+
type: "start";
|
|
63
|
+
total: number;
|
|
64
|
+
} | {
|
|
65
|
+
type: "progress";
|
|
66
|
+
data: EffieWarmupProgressEvent;
|
|
67
|
+
} | {
|
|
68
|
+
type: "downloading";
|
|
69
|
+
data: EffieWarmupDownloadingEvent;
|
|
70
|
+
} | {
|
|
71
|
+
type: "keepalive";
|
|
72
|
+
cached: number;
|
|
73
|
+
failed: number;
|
|
74
|
+
total: number;
|
|
75
|
+
} | {
|
|
76
|
+
type: "summary";
|
|
77
|
+
cached: number;
|
|
78
|
+
failed: number;
|
|
79
|
+
total: number;
|
|
80
|
+
} | {
|
|
81
|
+
type: "complete";
|
|
82
|
+
status: "ready";
|
|
83
|
+
} | {
|
|
84
|
+
type: "error";
|
|
85
|
+
message: string;
|
|
86
|
+
};
|
|
87
|
+
/** Current warmup state */
|
|
88
|
+
type EffieWarmupState = {
|
|
89
|
+
status: "idle" | "connecting" | "warming" | "ready" | "error";
|
|
90
|
+
total: number;
|
|
91
|
+
cached: number;
|
|
92
|
+
failed: number;
|
|
93
|
+
downloading: Map<string, {
|
|
94
|
+
url: string;
|
|
95
|
+
bytesReceived: number;
|
|
96
|
+
}>;
|
|
97
|
+
error?: string;
|
|
98
|
+
startTime?: number;
|
|
99
|
+
endTime?: number;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
export { type EffieSourceResolver, type EffieValidationIssue, type EffieWarmupEvent, type EffieWarmupState, createEffieSourceResolver, parseEffieValidationIssues };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// src/core.ts
|
|
2
|
+
function createEffieSourceResolver(sources) {
|
|
3
|
+
return (src) => {
|
|
4
|
+
if (src.startsWith("#")) {
|
|
5
|
+
const key = src.slice(1);
|
|
6
|
+
return sources?.[key] ?? src;
|
|
7
|
+
}
|
|
8
|
+
return src;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
function parseEffieValidationIssues(issues) {
|
|
12
|
+
if (issues && Array.isArray(issues)) {
|
|
13
|
+
if (issues.every(
|
|
14
|
+
(issue) => typeof issue === "object" && issue !== null && "path" in issue && "message" in issue
|
|
15
|
+
)) {
|
|
16
|
+
return issues;
|
|
17
|
+
} else {
|
|
18
|
+
throw new Error("Invalid validation issues");
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return void 0;
|
|
22
|
+
}
|
|
23
|
+
export {
|
|
24
|
+
createEffieSourceResolver,
|
|
25
|
+
parseEffieValidationIssues
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core.ts"],"sourcesContent":["import type { EffieSources } from \"@effing/effie\";\n\n/**\n * Create a source resolver function that handles #reference lookups\n * in effie source fields.\n *\n * @param sources - The sources map from an EffieData object\n * @returns A function that resolves source references to URLs\n *\n * @example\n * ```ts\n * const resolve = createEffieSourceResolver(effieJson.sources);\n * const url = resolve(layer.source); // Handles both \"#ref\" and direct URLs\n * ```\n */\nexport function createEffieSourceResolver(sources?: EffieSources) {\n return (src: string): string => {\n if (src.startsWith(\"#\")) {\n const key = src.slice(1);\n return sources?.[key] ?? src;\n }\n return src;\n };\n}\n\n/**\n * Type alias for a source resolver function\n */\nexport type EffieSourceResolver = ReturnType<typeof createEffieSourceResolver>;\n\n/**\n * Represents a validation issue from EffieData schema validation.\n */\nexport type EffieValidationIssue = {\n /** Path to the field that failed validation (e.g., \"segments.0.transition.sweep\") */\n path: string;\n /** Human-readable error message */\n message: string;\n};\n\n/**\n * Parse an unknown value as an array of validation issues.\n *\n * @param issues - The issues value to parse (typically from errorBody.issues)\n * @returns Array of validation issues, or undefined if not a valid array\n *\n * @example\n * ```ts\n * const errorBody = await response.json();\n * const issues = parseEffieValidationIssues(errorBody.issues);\n * ```\n */\nexport function parseEffieValidationIssues(\n issues: unknown,\n): EffieValidationIssue[] | undefined {\n if (issues && Array.isArray(issues)) {\n if (\n issues.every(\n (issue) =>\n typeof issue === \"object\" &&\n issue !== null &&\n \"path\" in issue &&\n \"message\" in issue,\n )\n ) {\n return issues as EffieValidationIssue[];\n } else {\n throw new Error(\"Invalid validation issues\");\n }\n }\n return undefined;\n}\n"],"mappings":";AAeO,SAAS,0BAA0B,SAAwB;AAChE,SAAO,CAAC,QAAwB;AAC9B,QAAI,IAAI,WAAW,GAAG,GAAG;AACvB,YAAM,MAAM,IAAI,MAAM,CAAC;AACvB,aAAO,UAAU,GAAG,KAAK;AAAA,IAC3B;AACA,WAAO;AAAA,EACT;AACF;AA6BO,SAAS,2BACd,QACoC;AACpC,MAAI,UAAU,MAAM,QAAQ,MAAM,GAAG;AACnC,QACE,OAAO;AAAA,MACL,CAAC,UACC,OAAO,UAAU,YACjB,UAAU,QACV,UAAU,SACV,aAAa;AAAA,IACjB,GACA;AACA,aAAO;AAAA,IACT,OAAO;AACL,YAAM,IAAI,MAAM,2BAA2B;AAAA,IAC7C;AAAA,EACF;AACA,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { EffieWebUrl, EffieBackground, EffieSources, EffieLayer, EffieSegment } from '@effing/effie';
|
|
3
|
+
import { EffieSourceResolver, EffieValidationIssue, EffieWarmupState } from '../index.js';
|
|
4
|
+
|
|
5
|
+
type EffieCoverPreviewProps = {
|
|
6
|
+
/** Cover image URL */
|
|
7
|
+
cover: EffieWebUrl;
|
|
8
|
+
/** Resolution for preview */
|
|
9
|
+
resolution: {
|
|
10
|
+
width: number;
|
|
11
|
+
height: number;
|
|
12
|
+
};
|
|
13
|
+
/** Optional video URL to show instead of cover image (e.g., after rendering) */
|
|
14
|
+
video?: string | null;
|
|
15
|
+
/** Callback when video starts playing */
|
|
16
|
+
onPlay?: () => void;
|
|
17
|
+
/** Callback when video is fully buffered (entire video downloaded) */
|
|
18
|
+
onFullyBuffered?: () => void;
|
|
19
|
+
/** Class name for the img/video element */
|
|
20
|
+
className?: string;
|
|
21
|
+
/** Style for the img/video element */
|
|
22
|
+
style?: React.CSSProperties;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Displays the effie cover image, or a video if provided.
|
|
26
|
+
* Simple component with built-in inline styles.
|
|
27
|
+
*/
|
|
28
|
+
declare function EffieCoverPreview({ cover, resolution, video, onPlay, onFullyBuffered, className, style, }: EffieCoverPreviewProps): react_jsx_runtime.JSX.Element;
|
|
29
|
+
type EffieBackgroundPreviewRootProps = {
|
|
30
|
+
className?: string;
|
|
31
|
+
style?: React.CSSProperties;
|
|
32
|
+
children: React.ReactNode;
|
|
33
|
+
};
|
|
34
|
+
declare function EffieBackgroundPreviewRoot({ className, style, children, }: EffieBackgroundPreviewRootProps): react_jsx_runtime.JSX.Element;
|
|
35
|
+
type EffieBackgroundPreviewMediaProps = {
|
|
36
|
+
/** Background configuration from effie JSON */
|
|
37
|
+
background: EffieBackground<EffieSources>;
|
|
38
|
+
/** Function to resolve source references */
|
|
39
|
+
resolveSource: EffieSourceResolver;
|
|
40
|
+
/** Class name for the media element */
|
|
41
|
+
className?: string;
|
|
42
|
+
/** Style for the media element */
|
|
43
|
+
style?: React.CSSProperties;
|
|
44
|
+
};
|
|
45
|
+
declare function EffieBackgroundPreviewMedia({ background, resolveSource, className, style, }: EffieBackgroundPreviewMediaProps): react_jsx_runtime.JSX.Element | null;
|
|
46
|
+
type EffieBackgroundPreviewInfoProps = {
|
|
47
|
+
/** Background configuration from effie JSON */
|
|
48
|
+
background: EffieBackground<EffieSources>;
|
|
49
|
+
/** Class name for the info section */
|
|
50
|
+
className?: string;
|
|
51
|
+
/** Style for the info section */
|
|
52
|
+
style?: React.CSSProperties;
|
|
53
|
+
};
|
|
54
|
+
declare function EffieBackgroundPreviewInfo({ background, className, style, }: EffieBackgroundPreviewInfoProps): react_jsx_runtime.JSX.Element;
|
|
55
|
+
type EffieBackgroundPreviewProps = {
|
|
56
|
+
/** Background configuration from effie JSON */
|
|
57
|
+
background: EffieBackground<EffieSources>;
|
|
58
|
+
/** Function to resolve source references */
|
|
59
|
+
resolveSource: EffieSourceResolver;
|
|
60
|
+
/** Resolution for preview */
|
|
61
|
+
resolution: {
|
|
62
|
+
width: number;
|
|
63
|
+
height: number;
|
|
64
|
+
};
|
|
65
|
+
/** Class name for the container */
|
|
66
|
+
className?: string;
|
|
67
|
+
/** Style for the container */
|
|
68
|
+
style?: React.CSSProperties;
|
|
69
|
+
};
|
|
70
|
+
declare function EffieBackgroundPreviewSimple({ background, resolveSource, resolution, className, style, }: EffieBackgroundPreviewProps): react_jsx_runtime.JSX.Element;
|
|
71
|
+
/**
|
|
72
|
+
* Displays a preview of the effie background (color, image, or video).
|
|
73
|
+
*
|
|
74
|
+
* Usage:
|
|
75
|
+
* - Simple: `<EffieBackgroundPreview background={...} resolveSource={...} />`
|
|
76
|
+
* - Compound: `<EffieBackgroundPreview.Root>...</EffieBackgroundPreview.Root>`
|
|
77
|
+
*/
|
|
78
|
+
declare const EffieBackgroundPreview: typeof EffieBackgroundPreviewSimple & {
|
|
79
|
+
Root: typeof EffieBackgroundPreviewRoot;
|
|
80
|
+
Media: typeof EffieBackgroundPreviewMedia;
|
|
81
|
+
Info: typeof EffieBackgroundPreviewInfo;
|
|
82
|
+
};
|
|
83
|
+
type EffieLayerPreviewRootProps = {
|
|
84
|
+
className?: string;
|
|
85
|
+
style?: React.CSSProperties;
|
|
86
|
+
children: React.ReactNode;
|
|
87
|
+
};
|
|
88
|
+
declare function EffieLayerPreviewRoot({ className, style, children, }: EffieLayerPreviewRootProps): react_jsx_runtime.JSX.Element;
|
|
89
|
+
type EffieLayerPreviewMediaProps = {
|
|
90
|
+
/** Layer configuration from effie JSON */
|
|
91
|
+
layer: EffieLayer<EffieSources>;
|
|
92
|
+
/** Layer index (0-based) for alt text */
|
|
93
|
+
index: number;
|
|
94
|
+
/** Function to resolve source references */
|
|
95
|
+
resolveSource: EffieSourceResolver;
|
|
96
|
+
/** Resolution for preview */
|
|
97
|
+
resolution: {
|
|
98
|
+
width: number;
|
|
99
|
+
height: number;
|
|
100
|
+
};
|
|
101
|
+
/** Class name for the media element */
|
|
102
|
+
className?: string;
|
|
103
|
+
/** Style for the media element */
|
|
104
|
+
style?: React.CSSProperties;
|
|
105
|
+
};
|
|
106
|
+
declare function EffieLayerPreviewMedia({ layer, index, resolveSource, resolution, className, style, }: EffieLayerPreviewMediaProps): react_jsx_runtime.JSX.Element;
|
|
107
|
+
type EffieLayerPreviewInfoProps = {
|
|
108
|
+
/** Layer configuration from effie JSON */
|
|
109
|
+
layer: EffieLayer<EffieSources>;
|
|
110
|
+
/** Layer index (0-based) */
|
|
111
|
+
index: number;
|
|
112
|
+
/** Class name for the info section */
|
|
113
|
+
className?: string;
|
|
114
|
+
/** Style for the info section */
|
|
115
|
+
style?: React.CSSProperties;
|
|
116
|
+
};
|
|
117
|
+
declare function EffieLayerPreviewInfo({ layer, index, className, style, }: EffieLayerPreviewInfoProps): react_jsx_runtime.JSX.Element;
|
|
118
|
+
type EffieLayerPreviewProps = {
|
|
119
|
+
/** Layer configuration from effie JSON */
|
|
120
|
+
layer: EffieLayer<EffieSources>;
|
|
121
|
+
/** Layer index (0-based) */
|
|
122
|
+
index: number;
|
|
123
|
+
/** Function to resolve source references */
|
|
124
|
+
resolveSource: EffieSourceResolver;
|
|
125
|
+
/** Resolution for preview */
|
|
126
|
+
resolution: {
|
|
127
|
+
width: number;
|
|
128
|
+
height: number;
|
|
129
|
+
};
|
|
130
|
+
/** How to stack info relative to media: "horizontal" (default, info beside) or "vertical" (info below) */
|
|
131
|
+
stacking?: "vertical" | "horizontal";
|
|
132
|
+
/** Class name for the container */
|
|
133
|
+
className?: string;
|
|
134
|
+
/** Style for the container */
|
|
135
|
+
style?: React.CSSProperties;
|
|
136
|
+
};
|
|
137
|
+
declare function EffieLayerPreviewSimple({ layer, index, resolveSource, resolution, stacking, className, style, }: EffieLayerPreviewProps): react_jsx_runtime.JSX.Element;
|
|
138
|
+
/**
|
|
139
|
+
* Displays a preview of a single layer, including its metadata.
|
|
140
|
+
* Uses AnniePlayer for animation layers.
|
|
141
|
+
*
|
|
142
|
+
* Usage:
|
|
143
|
+
* - Simple: `<EffieLayerPreview layer={...} index={...} resolveSource={...} />`
|
|
144
|
+
* - Compound: `<EffieLayerPreview.Root>...</EffieLayerPreview.Root>`
|
|
145
|
+
*/
|
|
146
|
+
declare const EffieLayerPreview: typeof EffieLayerPreviewSimple & {
|
|
147
|
+
Root: typeof EffieLayerPreviewRoot;
|
|
148
|
+
Media: typeof EffieLayerPreviewMedia;
|
|
149
|
+
Info: typeof EffieLayerPreviewInfo;
|
|
150
|
+
};
|
|
151
|
+
type EffieSegmentPreviewRootProps = {
|
|
152
|
+
className?: string;
|
|
153
|
+
style?: React.CSSProperties;
|
|
154
|
+
children: React.ReactNode;
|
|
155
|
+
};
|
|
156
|
+
declare function EffieSegmentPreviewRoot({ className, style, children, }: EffieSegmentPreviewRootProps): react_jsx_runtime.JSX.Element;
|
|
157
|
+
type EffieSegmentPreviewHeaderProps = {
|
|
158
|
+
className?: string;
|
|
159
|
+
style?: React.CSSProperties;
|
|
160
|
+
children: React.ReactNode;
|
|
161
|
+
};
|
|
162
|
+
declare function EffieSegmentPreviewHeader({ className, style, children, }: EffieSegmentPreviewHeaderProps): react_jsx_runtime.JSX.Element;
|
|
163
|
+
type EffieSegmentPreviewLayersProps = {
|
|
164
|
+
className?: string;
|
|
165
|
+
style?: React.CSSProperties;
|
|
166
|
+
children: React.ReactNode;
|
|
167
|
+
};
|
|
168
|
+
declare function EffieSegmentPreviewLayers({ className, style, children, }: EffieSegmentPreviewLayersProps): react_jsx_runtime.JSX.Element;
|
|
169
|
+
type EffieSegmentPreviewProps = {
|
|
170
|
+
/** Segment configuration from effie JSON */
|
|
171
|
+
segment: EffieSegment<EffieSources>;
|
|
172
|
+
/** Segment index (0-based) */
|
|
173
|
+
index: number;
|
|
174
|
+
/** Function to resolve source references */
|
|
175
|
+
resolveSource: EffieSourceResolver;
|
|
176
|
+
/** Resolution for preview */
|
|
177
|
+
resolution: {
|
|
178
|
+
width: number;
|
|
179
|
+
height: number;
|
|
180
|
+
};
|
|
181
|
+
/** How to stack layers: "vertical" (default) or "horizontal" */
|
|
182
|
+
stacking?: "vertical" | "horizontal";
|
|
183
|
+
/** Class name for the container */
|
|
184
|
+
className?: string;
|
|
185
|
+
/** Style for the container */
|
|
186
|
+
style?: React.CSSProperties;
|
|
187
|
+
};
|
|
188
|
+
declare function EffieSegmentPreviewSimple({ segment, index, resolveSource, resolution, stacking, className, style, }: EffieSegmentPreviewProps): react_jsx_runtime.JSX.Element;
|
|
189
|
+
/**
|
|
190
|
+
* Displays a preview of a segment with all its layers.
|
|
191
|
+
*
|
|
192
|
+
* Usage:
|
|
193
|
+
* - Simple: `<EffieSegmentPreview segment={...} index={...} resolveSource={...} />`
|
|
194
|
+
* - Compound: `<EffieSegmentPreview.Root>...</EffieSegmentPreview.Root>`
|
|
195
|
+
*/
|
|
196
|
+
declare const EffieSegmentPreview: typeof EffieSegmentPreviewSimple & {
|
|
197
|
+
Root: typeof EffieSegmentPreviewRoot;
|
|
198
|
+
Header: typeof EffieSegmentPreviewHeader;
|
|
199
|
+
Layers: typeof EffieSegmentPreviewLayers;
|
|
200
|
+
};
|
|
201
|
+
type EffieValidationErrorsProps = {
|
|
202
|
+
/** Error message (e.g., "Invalid effie data") */
|
|
203
|
+
error: string;
|
|
204
|
+
/** List of validation issues */
|
|
205
|
+
issues?: EffieValidationIssue[];
|
|
206
|
+
/** Class name for the container */
|
|
207
|
+
className?: string;
|
|
208
|
+
/** Style for the container */
|
|
209
|
+
style?: React.CSSProperties;
|
|
210
|
+
};
|
|
211
|
+
/**
|
|
212
|
+
* Displays validation errors with detailed issue breakdown.
|
|
213
|
+
* Simple component with built-in inline styles.
|
|
214
|
+
*/
|
|
215
|
+
declare function EffieValidationErrors({ error, issues, className, style, }: EffieValidationErrorsProps): react_jsx_runtime.JSX.Element;
|
|
216
|
+
type UseEffieWarmupResult = {
|
|
217
|
+
state: EffieWarmupState;
|
|
218
|
+
isReady: boolean;
|
|
219
|
+
isWarming: boolean;
|
|
220
|
+
hasError: boolean;
|
|
221
|
+
};
|
|
222
|
+
/**
|
|
223
|
+
* Hook to connect to a warmup SSE stream and track progress.
|
|
224
|
+
*
|
|
225
|
+
* @param streamUrl - The full SSE stream URL returned by the FFS server (null if FFS not configured)
|
|
226
|
+
*/
|
|
227
|
+
declare function useEffieWarmup(streamUrl: string | null): UseEffieWarmupResult;
|
|
228
|
+
|
|
229
|
+
export { EffieBackgroundPreview, type EffieBackgroundPreviewProps, EffieCoverPreview, type EffieCoverPreviewProps, EffieLayerPreview, type EffieLayerPreviewProps, EffieSegmentPreview, type EffieSegmentPreviewProps, EffieValidationErrors, type EffieValidationErrorsProps, type UseEffieWarmupResult, useEffieWarmup };
|