ugcinc-render 1.8.0 → 1.8.2
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/chunk-6DSZRTLA.mjs +1136 -0
- package/dist/index-C5NlUiZT.d.mts +1065 -0
- package/dist/index-C5NlUiZT.d.ts +1065 -0
- package/dist/index.d.mts +3 -1065
- package/dist/index.d.ts +3 -1065
- package/dist/index.js +34 -0
- package/dist/index.mjs +82 -1091
- package/dist/utils/index.d.mts +1 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1206 -0
- package/dist/utils/index.mjs +94 -0
- package/package.json +7 -2
|
@@ -0,0 +1,1065 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base types used throughout the rendering system
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Time value - can be absolute (milliseconds) or relative (0-1 percentage)
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* // Absolute: 500 milliseconds
|
|
9
|
+
* { type: 'absolute', value: 500 }
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* // Relative: 50% of total duration
|
|
13
|
+
* { type: 'relative', value: 0.5 }
|
|
14
|
+
*/
|
|
15
|
+
interface TimeValue {
|
|
16
|
+
type: 'absolute' | 'relative';
|
|
17
|
+
value: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Border radius configuration for individual corners.
|
|
21
|
+
* All values in pixels, default 0 (no rounding).
|
|
22
|
+
*/
|
|
23
|
+
interface BorderRadiusConfig {
|
|
24
|
+
/** Top-left corner radius in pixels */
|
|
25
|
+
topLeft?: number;
|
|
26
|
+
/** Top-right corner radius in pixels */
|
|
27
|
+
topRight?: number;
|
|
28
|
+
/** Bottom-right corner radius in pixels */
|
|
29
|
+
bottomRight?: number;
|
|
30
|
+
/** Bottom-left corner radius in pixels */
|
|
31
|
+
bottomLeft?: number;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Fit mode for media (images/videos)
|
|
35
|
+
* - cover: Fill the area, cropping if necessary
|
|
36
|
+
* - contain: Fit within the area, letterboxing if necessary
|
|
37
|
+
* - fill: Stretch to fill the area exactly
|
|
38
|
+
*/
|
|
39
|
+
type FitMode = 'cover' | 'contain' | 'fill';
|
|
40
|
+
/**
|
|
41
|
+
* Segment type identifiers
|
|
42
|
+
*/
|
|
43
|
+
type SegmentType = 'video' | 'image' | 'text' | 'audio' | 'editor';
|
|
44
|
+
/**
|
|
45
|
+
* Font type identifiers
|
|
46
|
+
*/
|
|
47
|
+
type FontType = 'arial' | 'tiktok' | 'apple';
|
|
48
|
+
/**
|
|
49
|
+
* Font weight options
|
|
50
|
+
*/
|
|
51
|
+
type FontWeight = 'normal' | 'bold';
|
|
52
|
+
/**
|
|
53
|
+
* Text alignment options
|
|
54
|
+
*/
|
|
55
|
+
type TextAlignment = 'left' | 'center' | 'right' | 'justify';
|
|
56
|
+
/**
|
|
57
|
+
* Vertical alignment options
|
|
58
|
+
*/
|
|
59
|
+
type VerticalAlignment = 'top' | 'middle' | 'bottom';
|
|
60
|
+
/**
|
|
61
|
+
* Text direction
|
|
62
|
+
*/
|
|
63
|
+
type TextDirection = 'ltr' | 'rtl';
|
|
64
|
+
/**
|
|
65
|
+
* Text wrapping mode
|
|
66
|
+
*/
|
|
67
|
+
type TextWrap = 'word' | 'char' | 'none';
|
|
68
|
+
/**
|
|
69
|
+
* Word break behavior
|
|
70
|
+
*/
|
|
71
|
+
type WordBreak = 'normal' | 'break-all' | 'break-word';
|
|
72
|
+
/**
|
|
73
|
+
* Hyphenation mode
|
|
74
|
+
*/
|
|
75
|
+
type Hyphenation = 'none' | 'auto';
|
|
76
|
+
/**
|
|
77
|
+
* Text overflow behavior
|
|
78
|
+
*/
|
|
79
|
+
type TextOverflow = 'clip' | 'ellipsis';
|
|
80
|
+
/**
|
|
81
|
+
* Shared text styling properties used by both render and UI text segments.
|
|
82
|
+
* This ensures feature parity between image editor and video editor text elements.
|
|
83
|
+
*/
|
|
84
|
+
interface TextStyleProperties {
|
|
85
|
+
/** Horizontal alignment (default: 'left') */
|
|
86
|
+
alignment?: TextAlignment;
|
|
87
|
+
/** Vertical alignment within bounds (default: 'top') */
|
|
88
|
+
verticalAlign?: VerticalAlignment;
|
|
89
|
+
/** Text direction (default: 'ltr') */
|
|
90
|
+
direction?: TextDirection;
|
|
91
|
+
/** Inner padding in pixels - uniform for all sides (default: 0) */
|
|
92
|
+
padding?: number;
|
|
93
|
+
/** Top padding in pixels */
|
|
94
|
+
paddingTop?: number;
|
|
95
|
+
/** Right padding in pixels */
|
|
96
|
+
paddingRight?: number;
|
|
97
|
+
/** Bottom padding in pixels */
|
|
98
|
+
paddingBottom?: number;
|
|
99
|
+
/** Left padding in pixels */
|
|
100
|
+
paddingLeft?: number;
|
|
101
|
+
/** Extra top padding added when text has 2+ lines */
|
|
102
|
+
multiLineExtraPaddingTop?: number;
|
|
103
|
+
/** Extra right padding added when text has 2+ lines */
|
|
104
|
+
multiLineExtraPaddingRight?: number;
|
|
105
|
+
/** Extra bottom padding added when text has 2+ lines */
|
|
106
|
+
multiLineExtraPaddingBottom?: number;
|
|
107
|
+
/** Extra left padding added when text has 2+ lines */
|
|
108
|
+
multiLineExtraPaddingLeft?: number;
|
|
109
|
+
/** Font family (default: 'arial') */
|
|
110
|
+
fontType?: FontType;
|
|
111
|
+
/** Font size in pixels (default: 40) */
|
|
112
|
+
fontSize?: number;
|
|
113
|
+
/** Font weight (default: 'normal') */
|
|
114
|
+
fontWeight?: FontWeight;
|
|
115
|
+
/** Line height multiplier (default: 1.2) */
|
|
116
|
+
lineHeight?: number;
|
|
117
|
+
/** Letter spacing in pixels (default: 0) */
|
|
118
|
+
letterSpacing?: number;
|
|
119
|
+
/** How text wraps to new lines (default: 'word') */
|
|
120
|
+
textWrap?: TextWrap;
|
|
121
|
+
/** How words break across lines (default: 'normal') */
|
|
122
|
+
wordBreak?: WordBreak;
|
|
123
|
+
/** Automatic hyphenation (default: 'none') */
|
|
124
|
+
hyphenation?: Hyphenation;
|
|
125
|
+
/** Maximum lines (0 = unlimited) (default: 0) */
|
|
126
|
+
maxLines?: number;
|
|
127
|
+
/** How overflow is handled (default: 'clip') */
|
|
128
|
+
textOverflow?: TextOverflow;
|
|
129
|
+
/** Ellipsis string for overflow (default: '...') */
|
|
130
|
+
ellipsis?: string;
|
|
131
|
+
/** Text color (default: '#000000') */
|
|
132
|
+
color?: string;
|
|
133
|
+
/** Background color in hex format #RRGGBB (default: transparent) */
|
|
134
|
+
backgroundColor?: string;
|
|
135
|
+
/** Background opacity 0-100 (default: 100) */
|
|
136
|
+
backgroundOpacity?: number;
|
|
137
|
+
/** Border radius for background box - individual corners (default: 0) */
|
|
138
|
+
backgroundBorderRadius?: BorderRadiusConfig;
|
|
139
|
+
/** Text outline color (default: none) */
|
|
140
|
+
strokeColor?: string;
|
|
141
|
+
/** Outline width in pixels (default: 0) */
|
|
142
|
+
strokeWidth?: number;
|
|
143
|
+
/** When true, box shrinks to fit content (width becomes max width) */
|
|
144
|
+
autoWidth?: boolean;
|
|
145
|
+
/** Which side the box anchors to when autoWidth is true (default: 'left') */
|
|
146
|
+
boxAlign?: 'left' | 'center' | 'right';
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Position and anchor types for relative element positioning
|
|
151
|
+
*/
|
|
152
|
+
/**
|
|
153
|
+
* Vertical anchor for Y positioning (parent element)
|
|
154
|
+
* Specifies which vertical edge of the reference element to anchor to
|
|
155
|
+
*/
|
|
156
|
+
type VerticalAnchor = 'top' | 'bottom';
|
|
157
|
+
/**
|
|
158
|
+
* Horizontal anchor for X positioning (parent element)
|
|
159
|
+
* Specifies which horizontal edge of the reference element to anchor to
|
|
160
|
+
*/
|
|
161
|
+
type HorizontalAnchor = 'left' | 'right';
|
|
162
|
+
/**
|
|
163
|
+
* Self anchor for X positioning
|
|
164
|
+
* Specifies which horizontal edge of THIS element to use for positioning
|
|
165
|
+
*/
|
|
166
|
+
type HorizontalSelfAnchor = 'left' | 'center' | 'right';
|
|
167
|
+
/**
|
|
168
|
+
* Self anchor for Y positioning
|
|
169
|
+
* Specifies which vertical edge of THIS element to use for positioning
|
|
170
|
+
*/
|
|
171
|
+
type VerticalSelfAnchor = 'top' | 'middle' | 'bottom';
|
|
172
|
+
/**
|
|
173
|
+
* Relative X position configuration
|
|
174
|
+
* When set, the segment's X position is calculated relative to another segment
|
|
175
|
+
*
|
|
176
|
+
* @example
|
|
177
|
+
* // Position this segment to the right of another segment with 10px gap
|
|
178
|
+
* { elementId: 'other-element', anchor: 'right', selfAnchor: 'left', offset: 10 }
|
|
179
|
+
*/
|
|
180
|
+
interface RelativePositionConfigX {
|
|
181
|
+
/** ID of the segment to position relative to */
|
|
182
|
+
elementId: string;
|
|
183
|
+
/** Which horizontal edge of the reference segment to anchor to */
|
|
184
|
+
anchor: HorizontalAnchor;
|
|
185
|
+
/** Which horizontal edge of THIS segment to use (default: opposite of anchor) */
|
|
186
|
+
selfAnchor?: HorizontalSelfAnchor;
|
|
187
|
+
/** Offset in pixels from the anchor point */
|
|
188
|
+
offset: number;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Relative Y position configuration
|
|
192
|
+
* When set, the segment's Y position is calculated relative to another segment
|
|
193
|
+
*
|
|
194
|
+
* @example
|
|
195
|
+
* // Position this segment below another segment with a 10px gap
|
|
196
|
+
* { elementId: 'message-1', anchor: 'bottom', selfAnchor: 'top', offset: 10 }
|
|
197
|
+
*/
|
|
198
|
+
interface RelativePositionConfigY {
|
|
199
|
+
/** ID of the segment to position relative to */
|
|
200
|
+
elementId: string;
|
|
201
|
+
/** Which vertical edge of the reference segment to anchor to */
|
|
202
|
+
anchor: VerticalAnchor;
|
|
203
|
+
/** Which vertical edge of THIS segment to use (default: opposite of anchor) */
|
|
204
|
+
selfAnchor?: VerticalSelfAnchor;
|
|
205
|
+
/** Offset in pixels from the anchor point */
|
|
206
|
+
offset: number;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Dynamic cropping configuration types
|
|
211
|
+
*
|
|
212
|
+
* Dynamic cropping allows the output dimensions to be calculated
|
|
213
|
+
* based on element positions at render time.
|
|
214
|
+
*/
|
|
215
|
+
/**
|
|
216
|
+
* Crop boundary - can be static (element ID) or dynamic (input reference)
|
|
217
|
+
*/
|
|
218
|
+
interface CropBoundary {
|
|
219
|
+
/** Static: reference a specific element by ID */
|
|
220
|
+
elementId?: string;
|
|
221
|
+
/** Variable: get element ID from input (creates an input port) */
|
|
222
|
+
inputRef?: string;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Configuration for cropping along one axis (vertical = height, horizontal = width)
|
|
226
|
+
*/
|
|
227
|
+
interface CropAxisConfig {
|
|
228
|
+
/** Whether cropping is enabled for this axis */
|
|
229
|
+
enabled: boolean;
|
|
230
|
+
/**
|
|
231
|
+
* Crop mode:
|
|
232
|
+
* - 'all-elements': Crop to bounding box of all visible elements
|
|
233
|
+
* - 'between-elements': Crop between specific boundary elements
|
|
234
|
+
*/
|
|
235
|
+
mode: 'all-elements' | 'between-elements';
|
|
236
|
+
/** Top/left element boundary (between-elements mode only) */
|
|
237
|
+
startBoundary?: CropBoundary;
|
|
238
|
+
/** Bottom/right element boundary (between-elements mode only) */
|
|
239
|
+
endBoundary?: CropBoundary;
|
|
240
|
+
/** Padding before (top/left) in pixels */
|
|
241
|
+
paddingStart?: number;
|
|
242
|
+
/** Padding after (bottom/right) in pixels */
|
|
243
|
+
paddingEnd?: number;
|
|
244
|
+
/** Minimum dimension (prevents cropping too small) */
|
|
245
|
+
minSize?: number;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Dynamic crop configuration for image/video editor
|
|
249
|
+
*/
|
|
250
|
+
interface DynamicCropConfig {
|
|
251
|
+
/** Crop height based on elements */
|
|
252
|
+
vertical?: CropAxisConfig;
|
|
253
|
+
/** Crop width based on elements */
|
|
254
|
+
horizontal?: CropAxisConfig;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Result of crop bounds calculation
|
|
258
|
+
*/
|
|
259
|
+
interface CropBounds {
|
|
260
|
+
/** Left edge of crop area */
|
|
261
|
+
x: number;
|
|
262
|
+
/** Top edge of crop area */
|
|
263
|
+
y: number;
|
|
264
|
+
/** Width of cropped output */
|
|
265
|
+
width: number;
|
|
266
|
+
/** Height of cropped output */
|
|
267
|
+
height: number;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Raw element types for editor input
|
|
272
|
+
*
|
|
273
|
+
* These types represent the raw configuration that users define in the editor.
|
|
274
|
+
* They include relative positioning which gets resolved to absolute positions
|
|
275
|
+
* before rendering.
|
|
276
|
+
*/
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Dimension preset keys for image editor
|
|
280
|
+
*/
|
|
281
|
+
type DimensionPresetKey = 'tiktok' | 'instagram-square' | 'instagram-post' | 'youtube' | 'twitter' | 'custom';
|
|
282
|
+
/**
|
|
283
|
+
* Dimension preset configuration
|
|
284
|
+
*/
|
|
285
|
+
interface DimensionPreset {
|
|
286
|
+
width: number;
|
|
287
|
+
height: number;
|
|
288
|
+
label: string;
|
|
289
|
+
ratio: string;
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Standard dimension presets
|
|
293
|
+
*/
|
|
294
|
+
declare const DIMENSION_PRESETS: Record<Exclude<DimensionPresetKey, 'custom'>, DimensionPreset>;
|
|
295
|
+
/**
|
|
296
|
+
* Image editor element - a raw image or text layer in the editor
|
|
297
|
+
*
|
|
298
|
+
* This is the input format that includes relative positioning.
|
|
299
|
+
* It gets resolved to absolute positions before being converted to segments.
|
|
300
|
+
*/
|
|
301
|
+
interface ImageEditorElement {
|
|
302
|
+
/** Unique element identifier */
|
|
303
|
+
id: string;
|
|
304
|
+
/** Element type */
|
|
305
|
+
type: 'image' | 'text';
|
|
306
|
+
/** X position in pixels (may be overridden by relativePositionX) */
|
|
307
|
+
x: number;
|
|
308
|
+
/** Y position in pixels (may be overridden by relativePositionY) */
|
|
309
|
+
y: number;
|
|
310
|
+
/** Width in pixels */
|
|
311
|
+
width: number;
|
|
312
|
+
/** Height in pixels */
|
|
313
|
+
height: number;
|
|
314
|
+
/** Z-index for layering */
|
|
315
|
+
zIndex: number;
|
|
316
|
+
/** Rotation in degrees clockwise */
|
|
317
|
+
rotation?: number;
|
|
318
|
+
/** Whether the element is locked from editing */
|
|
319
|
+
locked?: boolean;
|
|
320
|
+
/** Relative X positioning config - when set, x is calculated from the reference element */
|
|
321
|
+
relativePositionX?: RelativePositionConfigX;
|
|
322
|
+
/** Relative Y positioning config - when set, y is calculated from the reference element */
|
|
323
|
+
relativePositionY?: RelativePositionConfigY;
|
|
324
|
+
/** Text content */
|
|
325
|
+
text?: string;
|
|
326
|
+
/** Maps to text input port for variable text (e.g., "text_1") */
|
|
327
|
+
textInputId?: string;
|
|
328
|
+
/** Text color (hex) */
|
|
329
|
+
color?: string;
|
|
330
|
+
/** Outline width in pixels (0 = no outline) */
|
|
331
|
+
outlineWidth?: number;
|
|
332
|
+
/** Outline color */
|
|
333
|
+
strokeColor?: string;
|
|
334
|
+
/** Font family */
|
|
335
|
+
font?: FontType;
|
|
336
|
+
/** Font size in pixels */
|
|
337
|
+
fontSize?: number;
|
|
338
|
+
/** Font weight */
|
|
339
|
+
fontWeight?: FontWeight;
|
|
340
|
+
/** Line height multiplier */
|
|
341
|
+
lineHeight?: number;
|
|
342
|
+
/** Letter spacing in pixels */
|
|
343
|
+
letterSpacing?: number;
|
|
344
|
+
/** Horizontal text alignment */
|
|
345
|
+
textAlign?: TextAlignment;
|
|
346
|
+
/** Vertical text alignment within bounds */
|
|
347
|
+
verticalAlign?: VerticalAlignment;
|
|
348
|
+
/** Background color for text box (hex) */
|
|
349
|
+
backgroundColor?: string;
|
|
350
|
+
/** Background opacity 0-100 */
|
|
351
|
+
backgroundOpacity?: number;
|
|
352
|
+
/** Corner radius for background box */
|
|
353
|
+
backgroundBorderRadius?: BorderRadiusConfig;
|
|
354
|
+
paddingTop?: number;
|
|
355
|
+
paddingRight?: number;
|
|
356
|
+
paddingBottom?: number;
|
|
357
|
+
paddingLeft?: number;
|
|
358
|
+
multiLineExtraPaddingTop?: number;
|
|
359
|
+
multiLineExtraPaddingRight?: number;
|
|
360
|
+
multiLineExtraPaddingBottom?: number;
|
|
361
|
+
multiLineExtraPaddingLeft?: number;
|
|
362
|
+
/** When true, box shrinks to fit content (width becomes max width) */
|
|
363
|
+
autoWidth?: boolean;
|
|
364
|
+
/** Which side the box anchors to when autoWidth is true */
|
|
365
|
+
boxAlign?: 'left' | 'center' | 'right';
|
|
366
|
+
/** Maps to input port (e.g., "image_1", "image_2") */
|
|
367
|
+
inputId?: string;
|
|
368
|
+
/** How the image fits its container */
|
|
369
|
+
fit?: FitMode;
|
|
370
|
+
/** Opacity percentage 0-100 */
|
|
371
|
+
opacity?: number;
|
|
372
|
+
/** Corner radius - single number for all corners, or object for individual */
|
|
373
|
+
borderRadius?: number | BorderRadiusConfig;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Image editor node configuration
|
|
377
|
+
*
|
|
378
|
+
* This is the complete configuration for an image editor node,
|
|
379
|
+
* including canvas dimensions, elements, and crop settings.
|
|
380
|
+
*/
|
|
381
|
+
interface ImageEditorNodeConfig {
|
|
382
|
+
/** Canvas width in pixels */
|
|
383
|
+
width: number;
|
|
384
|
+
/** Canvas height in pixels */
|
|
385
|
+
height: number;
|
|
386
|
+
/** Aspect ratio string (e.g., "9:16") */
|
|
387
|
+
aspectRatio: string;
|
|
388
|
+
/** Dimension preset key */
|
|
389
|
+
dimensionPreset: DimensionPresetKey;
|
|
390
|
+
/** Elements to render */
|
|
391
|
+
elements: ImageEditorElement[];
|
|
392
|
+
/** Background type: 'image' for image input, 'color' for solid color */
|
|
393
|
+
backgroundType?: 'image' | 'color';
|
|
394
|
+
/** Background color (hex) when backgroundType is 'color' */
|
|
395
|
+
backgroundColor?: string;
|
|
396
|
+
/** How the background image fits the canvas */
|
|
397
|
+
backgroundFit?: FitMode;
|
|
398
|
+
/** Cached background image URL for consistent preview */
|
|
399
|
+
previewBackgroundUrl?: string;
|
|
400
|
+
/** Cached image URLs for image elements (keyed by inputId) */
|
|
401
|
+
previewImageUrls?: Record<string, string>;
|
|
402
|
+
/** Cached text values for text elements (keyed by textInputId) */
|
|
403
|
+
previewTextValues?: Record<string, string>;
|
|
404
|
+
/** Dynamic cropping configuration */
|
|
405
|
+
dynamicCrop?: DynamicCropConfig;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Video editor types for the WEBAPP UI
|
|
410
|
+
*
|
|
411
|
+
* These types include UI-only fields (marked with comments).
|
|
412
|
+
* The renderer uses types from editor.ts and segment.ts instead.
|
|
413
|
+
*
|
|
414
|
+
* UI-only fields are stripped before sending to renderer:
|
|
415
|
+
* - timeMode: UI helper for displaying timing mode
|
|
416
|
+
* - inputRef/textInputRef: Resolved to source/text before rendering
|
|
417
|
+
* - dimensionPreset: Renderer uses width/height directly
|
|
418
|
+
* - previewUrls/previewTextValues: Only for UI preview
|
|
419
|
+
*/
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* UI helper for timing mode - not sent to renderer
|
|
423
|
+
*/
|
|
424
|
+
type TimeMode = 'fixed' | 'flexible';
|
|
425
|
+
/**
|
|
426
|
+
* Base properties for all video editor segments (UI)
|
|
427
|
+
*/
|
|
428
|
+
interface VideoEditorBaseSegment {
|
|
429
|
+
/** Unique segment identifier */
|
|
430
|
+
id: string;
|
|
431
|
+
/** Order in the channel (0-based) */
|
|
432
|
+
order: number;
|
|
433
|
+
/** Time offset from previous segment or absolute position */
|
|
434
|
+
offset: TimeValue;
|
|
435
|
+
/** Segment duration - required for sequential playback */
|
|
436
|
+
duration?: TimeValue;
|
|
437
|
+
/** Trim from start in milliseconds */
|
|
438
|
+
startTrim?: number;
|
|
439
|
+
/** Trim from end in milliseconds */
|
|
440
|
+
endTrim?: number;
|
|
441
|
+
/** UI-only: reference to input for dynamic start trim value - resolved to startTrim before rendering */
|
|
442
|
+
startTrimInputRef?: string;
|
|
443
|
+
/** UI-only: reference to input for dynamic end trim value - resolved to endTrim before rendering */
|
|
444
|
+
endTrimInputRef?: string;
|
|
445
|
+
/** UI-only: helper for timing mode display - stripped before rendering */
|
|
446
|
+
timeMode?: TimeMode;
|
|
447
|
+
/** Parent segment ID for overlays */
|
|
448
|
+
parentId?: string;
|
|
449
|
+
/** Relative start (0-1) within parent for overlays */
|
|
450
|
+
relativeStart?: number;
|
|
451
|
+
/** Relative end (0-1) within parent for overlays */
|
|
452
|
+
relativeEnd?: number;
|
|
453
|
+
/** Fade-in duration in milliseconds */
|
|
454
|
+
fadeIn?: number;
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Base properties for visual segments
|
|
458
|
+
*/
|
|
459
|
+
interface VideoEditorVisualSegment extends VideoEditorBaseSegment {
|
|
460
|
+
xOffset: number;
|
|
461
|
+
yOffset: number;
|
|
462
|
+
width: number;
|
|
463
|
+
height: number;
|
|
464
|
+
zIndex?: number;
|
|
465
|
+
scale?: number;
|
|
466
|
+
rotation?: number;
|
|
467
|
+
opacity?: number;
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Video segment (UI)
|
|
471
|
+
*/
|
|
472
|
+
interface VideoEditorVideoSegment extends VideoEditorVisualSegment {
|
|
473
|
+
type: 'video';
|
|
474
|
+
/** UI-only: reference to input node - resolved to source before rendering */
|
|
475
|
+
inputRef?: string;
|
|
476
|
+
/** Actual source URL (set after inputRef is resolved) */
|
|
477
|
+
source?: string;
|
|
478
|
+
fit?: FitMode;
|
|
479
|
+
speed?: number;
|
|
480
|
+
volume?: number;
|
|
481
|
+
borderRadius?: number | BorderRadiusConfig;
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* Audio segment (UI)
|
|
485
|
+
*/
|
|
486
|
+
interface VideoEditorAudioSegment extends VideoEditorBaseSegment {
|
|
487
|
+
type: 'audio';
|
|
488
|
+
/** UI-only: reference to input node - resolved to source before rendering */
|
|
489
|
+
inputRef?: string;
|
|
490
|
+
/** Actual source URL (set after inputRef is resolved) */
|
|
491
|
+
source?: string;
|
|
492
|
+
volume?: number;
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* Image segment (UI)
|
|
496
|
+
*/
|
|
497
|
+
interface VideoEditorImageSegment extends VideoEditorVisualSegment {
|
|
498
|
+
type: 'image';
|
|
499
|
+
/** UI-only: reference to input node - resolved to source before rendering */
|
|
500
|
+
inputRef?: string;
|
|
501
|
+
/** Actual source URL (set after inputRef is resolved) */
|
|
502
|
+
source?: string;
|
|
503
|
+
fit?: FitMode;
|
|
504
|
+
loop?: boolean;
|
|
505
|
+
borderRadius?: number | BorderRadiusConfig;
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* Text segment (UI)
|
|
509
|
+
*
|
|
510
|
+
* Extends TextStyleProperties which contains all shared text styling options.
|
|
511
|
+
* This ensures feature parity between image editor and video editor text elements.
|
|
512
|
+
*/
|
|
513
|
+
interface VideoEditorTextSegment extends VideoEditorVisualSegment, TextStyleProperties {
|
|
514
|
+
type: 'text';
|
|
515
|
+
/** UI-only: reference to text input - resolved to text before rendering */
|
|
516
|
+
textInputRef?: string;
|
|
517
|
+
/** Actual text content (set after textInputRef is resolved) */
|
|
518
|
+
text?: string;
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* Union of all video editor segment types
|
|
522
|
+
*/
|
|
523
|
+
type VideoEditorSegment = VideoEditorVideoSegment | VideoEditorAudioSegment | VideoEditorImageSegment | VideoEditorTextSegment;
|
|
524
|
+
/**
|
|
525
|
+
* Video editor channel
|
|
526
|
+
*/
|
|
527
|
+
interface VideoEditorChannel {
|
|
528
|
+
id: string;
|
|
529
|
+
name: string;
|
|
530
|
+
segments: VideoEditorSegment[];
|
|
531
|
+
}
|
|
532
|
+
/**
|
|
533
|
+
* Video editor node configuration for WEBAPP UI
|
|
534
|
+
*
|
|
535
|
+
* Duration is NOT stored - it's calculated from segment durations.
|
|
536
|
+
* dimensionPreset, previewUrls, previewTextValues are UI-only.
|
|
537
|
+
*/
|
|
538
|
+
interface VideoEditorNodeConfig {
|
|
539
|
+
/** Canvas width in pixels */
|
|
540
|
+
width: number;
|
|
541
|
+
/** Canvas height in pixels */
|
|
542
|
+
height: number;
|
|
543
|
+
/** Frames per second */
|
|
544
|
+
fps: number;
|
|
545
|
+
/** UI-only: dimension preset selector */
|
|
546
|
+
dimensionPreset: DimensionPresetKey;
|
|
547
|
+
/** Channels containing segments */
|
|
548
|
+
channels: VideoEditorChannel[];
|
|
549
|
+
/** UI-only: preview URLs for displaying in editor */
|
|
550
|
+
previewUrls?: Record<string, string>;
|
|
551
|
+
/** UI-only: preview text values for displaying in editor */
|
|
552
|
+
previewTextValues?: Record<string, string>;
|
|
553
|
+
}
|
|
554
|
+
/**
|
|
555
|
+
* Segment position on timeline (calculated from segment timing properties)
|
|
556
|
+
*/
|
|
557
|
+
interface SegmentTimelinePosition {
|
|
558
|
+
/** Start time in milliseconds */
|
|
559
|
+
startMs: number;
|
|
560
|
+
/** Duration in milliseconds */
|
|
561
|
+
durationMs: number;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
/**
|
|
565
|
+
* Caption types for auto-captioning functionality
|
|
566
|
+
*
|
|
567
|
+
* These types are used by both the CaptionOverlay component (client + server)
|
|
568
|
+
* and the AutoCaptionComposition for rendering captioned videos.
|
|
569
|
+
*/
|
|
570
|
+
/**
|
|
571
|
+
* Caption word with timing information from transcription
|
|
572
|
+
*/
|
|
573
|
+
interface CaptionWord {
|
|
574
|
+
/** The word text */
|
|
575
|
+
word: string;
|
|
576
|
+
/** Start time in milliseconds */
|
|
577
|
+
startMs: number;
|
|
578
|
+
/** End time in milliseconds */
|
|
579
|
+
endMs: number;
|
|
580
|
+
}
|
|
581
|
+
/**
|
|
582
|
+
* Caption page - a group of words displayed together
|
|
583
|
+
*/
|
|
584
|
+
interface CaptionPage {
|
|
585
|
+
/** Words in this page */
|
|
586
|
+
words: CaptionWord[];
|
|
587
|
+
/** Start time of first word in ms */
|
|
588
|
+
startMs: number;
|
|
589
|
+
/** End time of last word in ms */
|
|
590
|
+
endMs: number;
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* Caption style preset names
|
|
594
|
+
*/
|
|
595
|
+
type CaptionPreset = 'hormozi' | 'minimal' | 'bold-pop' | 'clean' | 'neon';
|
|
596
|
+
/**
|
|
597
|
+
* Caption vertical position on screen
|
|
598
|
+
*/
|
|
599
|
+
type CaptionPosition = 'top' | 'center' | 'bottom';
|
|
600
|
+
/**
|
|
601
|
+
* Caption font weight options
|
|
602
|
+
*/
|
|
603
|
+
type CaptionFontWeight = 'normal' | 'bold' | 'black';
|
|
604
|
+
/**
|
|
605
|
+
* Full caption style configuration
|
|
606
|
+
*/
|
|
607
|
+
interface CaptionStyle {
|
|
608
|
+
/** Preset name (if used, provides defaults for other fields) */
|
|
609
|
+
preset?: CaptionPreset;
|
|
610
|
+
/** Google Font name (e.g., 'Montserrat', 'Inter') */
|
|
611
|
+
fontName: string;
|
|
612
|
+
/** Font size in pixels (relative to 1920p height) */
|
|
613
|
+
fontSize: number;
|
|
614
|
+
/** Font weight */
|
|
615
|
+
fontWeight: CaptionFontWeight;
|
|
616
|
+
/** Text color for inactive words */
|
|
617
|
+
fontColor: string;
|
|
618
|
+
/** Text color for the currently active/highlighted word */
|
|
619
|
+
highlightColor: string;
|
|
620
|
+
/** Stroke/outline color */
|
|
621
|
+
strokeColor: string;
|
|
622
|
+
/** Stroke width in pixels */
|
|
623
|
+
strokeWidth: number;
|
|
624
|
+
/** Background color (hex) - omit for transparent */
|
|
625
|
+
backgroundColor?: string;
|
|
626
|
+
/** Background opacity (0-1) */
|
|
627
|
+
backgroundOpacity?: number;
|
|
628
|
+
/** Background border radius in pixels */
|
|
629
|
+
backgroundBorderRadius?: number;
|
|
630
|
+
/** Vertical position on screen */
|
|
631
|
+
position: CaptionPosition;
|
|
632
|
+
/** Vertical offset in pixels from position edge */
|
|
633
|
+
yOffset: number;
|
|
634
|
+
/** Max width as percentage of video width (0-100) */
|
|
635
|
+
maxWidth: number;
|
|
636
|
+
/** Enable bounce/scale animation on active word */
|
|
637
|
+
enableAnimation: boolean;
|
|
638
|
+
/** Maximum words per caption page/screen */
|
|
639
|
+
wordsPerPage: number;
|
|
640
|
+
}
|
|
641
|
+
/**
|
|
642
|
+
* Props for AutoCaptionComposition
|
|
643
|
+
*/
|
|
644
|
+
interface AutoCaptionCompositionProps {
|
|
645
|
+
/** Video source URL */
|
|
646
|
+
videoUrl: string;
|
|
647
|
+
/** Video width in pixels */
|
|
648
|
+
width: number;
|
|
649
|
+
/** Video height in pixels */
|
|
650
|
+
height: number;
|
|
651
|
+
/** Video duration in milliseconds */
|
|
652
|
+
durationMs: number;
|
|
653
|
+
/** Caption words with timing */
|
|
654
|
+
captions: CaptionWord[];
|
|
655
|
+
/** Caption styling configuration */
|
|
656
|
+
style: CaptionStyle;
|
|
657
|
+
}
|
|
658
|
+
/**
|
|
659
|
+
* Props for CaptionOverlay component
|
|
660
|
+
*/
|
|
661
|
+
interface CaptionOverlayProps {
|
|
662
|
+
/** Caption words with timing */
|
|
663
|
+
captions: CaptionWord[];
|
|
664
|
+
/** Caption styling configuration */
|
|
665
|
+
style: CaptionStyle;
|
|
666
|
+
/** Override current time for preview mode (ms) */
|
|
667
|
+
previewTimeMs?: number;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
/**
|
|
671
|
+
* Font utilities for the rendering system
|
|
672
|
+
*/
|
|
673
|
+
|
|
674
|
+
/**
|
|
675
|
+
* Apple Color Emoji font name - used as fallback for emoji characters
|
|
676
|
+
*/
|
|
677
|
+
declare const APPLE_EMOJI_FONT = "\"Apple Color Emoji\"";
|
|
678
|
+
/**
|
|
679
|
+
* Font family CSS strings for each font type
|
|
680
|
+
* These match the fonts registered in the rendering system
|
|
681
|
+
* Apple Color Emoji is added as a fallback for consistent emoji rendering
|
|
682
|
+
*/
|
|
683
|
+
declare const FONT_FAMILIES: Record<FontType, string>;
|
|
684
|
+
/**
|
|
685
|
+
* Get the CSS font family string for a font type
|
|
686
|
+
*/
|
|
687
|
+
declare function getFontFamily(fontType: FontType): string;
|
|
688
|
+
/**
|
|
689
|
+
* Build a CSS font string
|
|
690
|
+
*/
|
|
691
|
+
declare function buildFontString({ fontType, fontSize, fontWeight, }: {
|
|
692
|
+
fontType: FontType;
|
|
693
|
+
fontSize: number;
|
|
694
|
+
fontWeight: 'normal' | 'bold';
|
|
695
|
+
}): string;
|
|
696
|
+
/**
|
|
697
|
+
* Font URLs for loading web fonts
|
|
698
|
+
* These are the public URLs to the font files
|
|
699
|
+
*/
|
|
700
|
+
declare const FONT_URLS: {
|
|
701
|
+
tiktok: {
|
|
702
|
+
regular: string;
|
|
703
|
+
bold: string;
|
|
704
|
+
};
|
|
705
|
+
apple: {
|
|
706
|
+
regular: string;
|
|
707
|
+
};
|
|
708
|
+
emoji: {
|
|
709
|
+
apple: string;
|
|
710
|
+
};
|
|
711
|
+
};
|
|
712
|
+
/**
|
|
713
|
+
* Preload fonts for rendering
|
|
714
|
+
* Call this in your Root component or composition
|
|
715
|
+
*/
|
|
716
|
+
declare function preloadFonts(): Promise<void>;
|
|
717
|
+
/**
|
|
718
|
+
* Check if fonts are loaded
|
|
719
|
+
*/
|
|
720
|
+
declare function areFontsLoaded(): boolean;
|
|
721
|
+
/**
|
|
722
|
+
* Debug utility to log current font status
|
|
723
|
+
*/
|
|
724
|
+
declare function debugFontStatus(): void;
|
|
725
|
+
|
|
726
|
+
/**
|
|
727
|
+
* Fit calculation utilities for media positioning
|
|
728
|
+
*/
|
|
729
|
+
|
|
730
|
+
/**
|
|
731
|
+
* Result of fit dimension calculation
|
|
732
|
+
*/
|
|
733
|
+
interface FitDimensions {
|
|
734
|
+
/** X offset within target area */
|
|
735
|
+
x: number;
|
|
736
|
+
/** Y offset within target area */
|
|
737
|
+
y: number;
|
|
738
|
+
/** Rendered width */
|
|
739
|
+
width: number;
|
|
740
|
+
/** Rendered height */
|
|
741
|
+
height: number;
|
|
742
|
+
/** Source X offset (for cropping) */
|
|
743
|
+
sourceX: number;
|
|
744
|
+
/** Source Y offset (for cropping) */
|
|
745
|
+
sourceY: number;
|
|
746
|
+
/** Source width to use */
|
|
747
|
+
sourceWidth: number;
|
|
748
|
+
/** Source height to use */
|
|
749
|
+
sourceHeight: number;
|
|
750
|
+
}
|
|
751
|
+
/**
|
|
752
|
+
* Calculate dimensions for fit modes (cover, contain, fill)
|
|
753
|
+
*/
|
|
754
|
+
declare function calculateFitDimensions({ sourceWidth, sourceHeight, targetWidth, targetHeight, fit, }: {
|
|
755
|
+
sourceWidth: number;
|
|
756
|
+
sourceHeight: number;
|
|
757
|
+
targetWidth: number;
|
|
758
|
+
targetHeight: number;
|
|
759
|
+
fit: FitMode;
|
|
760
|
+
}): FitDimensions;
|
|
761
|
+
|
|
762
|
+
/**
|
|
763
|
+
* Default values for segment properties
|
|
764
|
+
*
|
|
765
|
+
* These defaults match the server-side rendering defaults exactly
|
|
766
|
+
* to ensure consistent behavior between client preview and server render.
|
|
767
|
+
*/
|
|
768
|
+
|
|
769
|
+
/**
|
|
770
|
+
* Default values for text segments
|
|
771
|
+
*/
|
|
772
|
+
declare const TEXT_DEFAULTS: {
|
|
773
|
+
fontType: FontType;
|
|
774
|
+
fontSize: number;
|
|
775
|
+
fontWeight: FontWeight;
|
|
776
|
+
color: string;
|
|
777
|
+
alignment: TextAlignment;
|
|
778
|
+
verticalAlign: VerticalAlignment;
|
|
779
|
+
direction: TextDirection;
|
|
780
|
+
lineHeight: number;
|
|
781
|
+
letterSpacing: number;
|
|
782
|
+
padding: number;
|
|
783
|
+
textWrap: TextWrap;
|
|
784
|
+
wordBreak: WordBreak;
|
|
785
|
+
hyphenation: Hyphenation;
|
|
786
|
+
maxLines: number;
|
|
787
|
+
textOverflow: TextOverflow;
|
|
788
|
+
ellipsis: string;
|
|
789
|
+
strokeWidth: number;
|
|
790
|
+
backgroundOpacity: number;
|
|
791
|
+
autoWidth: boolean;
|
|
792
|
+
boxAlign: "left";
|
|
793
|
+
};
|
|
794
|
+
/**
|
|
795
|
+
* Default values for image segments
|
|
796
|
+
*/
|
|
797
|
+
declare const IMAGE_DEFAULTS: {
|
|
798
|
+
fit: FitMode;
|
|
799
|
+
opacity: number;
|
|
800
|
+
loop: boolean;
|
|
801
|
+
speed: number;
|
|
802
|
+
};
|
|
803
|
+
/**
|
|
804
|
+
* Default values for video segments
|
|
805
|
+
*/
|
|
806
|
+
declare const VIDEO_DEFAULTS: {
|
|
807
|
+
volume: number;
|
|
808
|
+
fit: FitMode;
|
|
809
|
+
opacity: number;
|
|
810
|
+
loop: boolean;
|
|
811
|
+
speed: number;
|
|
812
|
+
};
|
|
813
|
+
/**
|
|
814
|
+
* Default values for visual segment positioning
|
|
815
|
+
*/
|
|
816
|
+
declare const VISUAL_DEFAULTS: {
|
|
817
|
+
xOffset: number;
|
|
818
|
+
yOffset: number;
|
|
819
|
+
zIndex: number;
|
|
820
|
+
scale: number;
|
|
821
|
+
rotation: number;
|
|
822
|
+
opacity: number;
|
|
823
|
+
};
|
|
824
|
+
/**
|
|
825
|
+
* Apply default values to a text segment
|
|
826
|
+
*/
|
|
827
|
+
declare function applyTextDefaults<T extends Record<string, unknown>>(segment: T): T & typeof TEXT_DEFAULTS;
|
|
828
|
+
/**
|
|
829
|
+
* Apply default values to an image segment
|
|
830
|
+
*/
|
|
831
|
+
declare function applyImageDefaults<T extends Record<string, unknown>>(segment: T): T & typeof IMAGE_DEFAULTS;
|
|
832
|
+
/**
|
|
833
|
+
* Apply default values to a video segment
|
|
834
|
+
*/
|
|
835
|
+
declare function applyVideoDefaults<T extends Record<string, unknown>>(segment: T): T & typeof VIDEO_DEFAULTS;
|
|
836
|
+
|
|
837
|
+
/**
|
|
838
|
+
* Text utilities for measuring and wrapping text
|
|
839
|
+
*/
|
|
840
|
+
|
|
841
|
+
/**
|
|
842
|
+
* Wrap text to fit within a specific width
|
|
843
|
+
* Accounts for letter spacing when measuring text width
|
|
844
|
+
*/
|
|
845
|
+
declare function wrapText({ text, maxWidth, letterSpacing, textWrap, maxLines, measureText, }: {
|
|
846
|
+
text: string;
|
|
847
|
+
maxWidth: number;
|
|
848
|
+
letterSpacing?: number;
|
|
849
|
+
textWrap?: 'word' | 'char' | 'none';
|
|
850
|
+
maxLines?: number;
|
|
851
|
+
measureText: (text: string) => number;
|
|
852
|
+
}): string[];
|
|
853
|
+
/**
|
|
854
|
+
* Calculate line width with letter spacing
|
|
855
|
+
*/
|
|
856
|
+
declare function calculateLineWidth({ line, letterSpacing, measureText, }: {
|
|
857
|
+
line: string;
|
|
858
|
+
letterSpacing: number;
|
|
859
|
+
measureText: (text: string) => number;
|
|
860
|
+
}): number;
|
|
861
|
+
/**
|
|
862
|
+
* Convert borderRadius value to array format for roundRect()
|
|
863
|
+
* Returns [topLeft, topRight, bottomRight, bottomLeft] or null if no rounding needed
|
|
864
|
+
*/
|
|
865
|
+
declare function getBorderRadii(borderRadius: number | BorderRadiusConfig | undefined): number[] | null;
|
|
866
|
+
/**
|
|
867
|
+
* Parse hex color to RGB values
|
|
868
|
+
*/
|
|
869
|
+
declare function parseHexColor(hex: string): {
|
|
870
|
+
r: number;
|
|
871
|
+
g: number;
|
|
872
|
+
b: number;
|
|
873
|
+
};
|
|
874
|
+
/**
|
|
875
|
+
* Convert hex color and opacity to rgba string
|
|
876
|
+
*/
|
|
877
|
+
declare function hexToRgba(hex: string, opacity?: number): string;
|
|
878
|
+
|
|
879
|
+
/**
|
|
880
|
+
* Position Resolution Utility
|
|
881
|
+
*
|
|
882
|
+
* Resolves relative element positions to absolute coordinates.
|
|
883
|
+
* X and Y positions can be independently set to relative or absolute.
|
|
884
|
+
* Handles dependency resolution, circular dependency detection, and cascading updates.
|
|
885
|
+
*/
|
|
886
|
+
|
|
887
|
+
/**
|
|
888
|
+
* Calculate the actual dimensions of a text element when autoWidth is enabled
|
|
889
|
+
* Returns { actualWidth, actualX, actualHeight } where:
|
|
890
|
+
* - actualX is adjusted based on boxAlign
|
|
891
|
+
* - actualHeight is calculated based on the number of wrapped lines
|
|
892
|
+
*/
|
|
893
|
+
declare function calculateAutoWidthDimensions(elem: ImageEditorElement, textContent: string, ctx?: CanvasRenderingContext2D | null): {
|
|
894
|
+
actualWidth: number;
|
|
895
|
+
actualX: number;
|
|
896
|
+
actualHeight: number;
|
|
897
|
+
lineCount: number;
|
|
898
|
+
} | null;
|
|
899
|
+
interface PositionResolutionError {
|
|
900
|
+
elementId: string;
|
|
901
|
+
type: 'circular_dependency' | 'missing_reference' | 'invalid_config';
|
|
902
|
+
message: string;
|
|
903
|
+
/** Which axis the error is for */
|
|
904
|
+
axis?: 'x' | 'y';
|
|
905
|
+
/** For circular dependencies, the cycle path */
|
|
906
|
+
cyclePath?: string[];
|
|
907
|
+
}
|
|
908
|
+
interface PositionResolutionResult {
|
|
909
|
+
/** Elements with resolved absolute positions */
|
|
910
|
+
elements: ImageEditorElement[];
|
|
911
|
+
/** Any errors encountered during resolution */
|
|
912
|
+
errors: PositionResolutionError[];
|
|
913
|
+
}
|
|
914
|
+
/**
|
|
915
|
+
* Resolve all relative positions to absolute coordinates
|
|
916
|
+
*
|
|
917
|
+
* X and Y are resolved independently, allowing:
|
|
918
|
+
* - X absolute, Y relative (common for vertical stacking)
|
|
919
|
+
* - X relative, Y absolute (common for horizontal stacking)
|
|
920
|
+
* - Both relative (can be to different elements)
|
|
921
|
+
* - Both absolute
|
|
922
|
+
*
|
|
923
|
+
* @param elements - Array of elements to resolve
|
|
924
|
+
* @param textValues - Optional map of textInputId -> text content for autoWidth calculation
|
|
925
|
+
*/
|
|
926
|
+
declare function resolveElementPositions(elements: ImageEditorElement[], textValues?: Record<string, string>): PositionResolutionResult;
|
|
927
|
+
/**
|
|
928
|
+
* Check if an element can be set as a reference for another element on a specific axis
|
|
929
|
+
*/
|
|
930
|
+
declare function canSetAsReference(elements: ImageEditorElement[], elementId: string, proposedReferenceId: string, axis: 'x' | 'y'): boolean;
|
|
931
|
+
/**
|
|
932
|
+
* Get all elements that would be affected if a given element's position/size changes
|
|
933
|
+
*/
|
|
934
|
+
declare function getDependentElements(elements: ImageEditorElement[], elementId: string): string[];
|
|
935
|
+
/**
|
|
936
|
+
* Get the element that a given element references for X position (if any)
|
|
937
|
+
*/
|
|
938
|
+
declare function getReferenceElementX(elements: ImageEditorElement[], elementId: string): ImageEditorElement | null;
|
|
939
|
+
/**
|
|
940
|
+
* Get the element that a given element references for Y position (if any)
|
|
941
|
+
*/
|
|
942
|
+
declare function getReferenceElementY(elements: ImageEditorElement[], elementId: string): ImageEditorElement | null;
|
|
943
|
+
|
|
944
|
+
/**
|
|
945
|
+
* Utility functions for calculating dynamic crop bounds
|
|
946
|
+
*/
|
|
947
|
+
|
|
948
|
+
/**
|
|
949
|
+
* Calculate dynamic crop bounds based on element positions
|
|
950
|
+
*
|
|
951
|
+
* @param elements - Array of resolved elements with absolute positions
|
|
952
|
+
* @param dynamicCrop - Crop configuration
|
|
953
|
+
* @param canvasWidth - Original canvas width
|
|
954
|
+
* @param canvasHeight - Original canvas height
|
|
955
|
+
* @param textValues - Optional map of textInputId -> text content for height calculation
|
|
956
|
+
* @returns CropBounds with x, y, width, height
|
|
957
|
+
*/
|
|
958
|
+
declare function calculateCropBounds(elements: ImageEditorElement[], dynamicCrop: DynamicCropConfig | undefined, canvasWidth: number, canvasHeight: number, textValues?: Record<string, string>): CropBounds;
|
|
959
|
+
/**
|
|
960
|
+
* Check if dynamic crop is enabled (either vertical or horizontal)
|
|
961
|
+
*/
|
|
962
|
+
declare function isDynamicCropEnabled(dynamicCrop: DynamicCropConfig | undefined): boolean;
|
|
963
|
+
|
|
964
|
+
/**
|
|
965
|
+
* Timeline utility functions for video editor
|
|
966
|
+
*
|
|
967
|
+
* These functions calculate segment positions on the timeline based on
|
|
968
|
+
* the segment/overlay timing model. Used by both the webapp UI and
|
|
969
|
+
* the VideoEditorComposition for rendering.
|
|
970
|
+
*/
|
|
971
|
+
|
|
972
|
+
/**
|
|
973
|
+
* Create a default TimeValue for segment offsets
|
|
974
|
+
*/
|
|
975
|
+
declare function defaultOffset(mode?: TimeMode): TimeValue;
|
|
976
|
+
/**
|
|
977
|
+
* Get base segments (no parentId) for a channel
|
|
978
|
+
* Base segments are the primary timeline elements that overlays attach to
|
|
979
|
+
*/
|
|
980
|
+
declare function getBaseSegments(channel: VideoEditorChannel): VideoEditorSegment[];
|
|
981
|
+
/**
|
|
982
|
+
* Get overlays for a specific parent segment (or global overlays if parentId is null)
|
|
983
|
+
*/
|
|
984
|
+
declare function getOverlays(channel: VideoEditorChannel, parentId: string | null): VideoEditorSegment[];
|
|
985
|
+
/**
|
|
986
|
+
* Calculate segment position on timeline
|
|
987
|
+
*
|
|
988
|
+
* For base segments:
|
|
989
|
+
* - Position is calculated from offset and previous segments
|
|
990
|
+
* - Duration is from the duration property or default (5 seconds)
|
|
991
|
+
*
|
|
992
|
+
* For overlay segments:
|
|
993
|
+
* - Position is calculated relative to parent using relativeStart/relativeEnd
|
|
994
|
+
* - relativeStart/relativeEnd are fractions (0-1) of parent duration
|
|
995
|
+
*/
|
|
996
|
+
declare function getSegmentTimelinePosition(segment: VideoEditorSegment, baseSegments: VideoEditorSegment[], channel: VideoEditorChannel): SegmentTimelinePosition;
|
|
997
|
+
/**
|
|
998
|
+
* Check if a segment is visible at a given time
|
|
999
|
+
*/
|
|
1000
|
+
declare function isSegmentVisibleAtTime(segment: VideoEditorSegment, time: number, channel: VideoEditorChannel): boolean;
|
|
1001
|
+
/**
|
|
1002
|
+
* Calculate estimated total duration based on segments
|
|
1003
|
+
*/
|
|
1004
|
+
declare function calculateEstimatedDuration(channels: VideoEditorChannel[]): number;
|
|
1005
|
+
/**
|
|
1006
|
+
* Calculate the timeline content end time (used for both ruler and scroll width)
|
|
1007
|
+
*/
|
|
1008
|
+
declare function calculateTimelineContentEnd(channel: VideoEditorChannel): number;
|
|
1009
|
+
/**
|
|
1010
|
+
* Format time in mm:ss.ms
|
|
1011
|
+
*/
|
|
1012
|
+
declare function formatTime(ms: number): string;
|
|
1013
|
+
/**
|
|
1014
|
+
* Parse time string to milliseconds
|
|
1015
|
+
*/
|
|
1016
|
+
declare function parseTime(timeStr: string): number;
|
|
1017
|
+
/**
|
|
1018
|
+
* Generate a unique segment ID
|
|
1019
|
+
*/
|
|
1020
|
+
declare function generateSegmentId(): string;
|
|
1021
|
+
/**
|
|
1022
|
+
* Generate a unique overlay ID
|
|
1023
|
+
*/
|
|
1024
|
+
declare function generateOverlayId(): string;
|
|
1025
|
+
|
|
1026
|
+
/**
|
|
1027
|
+
* Caption style presets and resolution utilities
|
|
1028
|
+
*
|
|
1029
|
+
* Provides TikTok-style caption presets and a function to resolve
|
|
1030
|
+
* partial config into a complete CaptionStyle object.
|
|
1031
|
+
*/
|
|
1032
|
+
|
|
1033
|
+
/**
|
|
1034
|
+
* Predefined caption style presets
|
|
1035
|
+
*
|
|
1036
|
+
* Font sizes are designed for 1920p height and scale proportionally.
|
|
1037
|
+
* maxWidth is a percentage of video width (0-100).
|
|
1038
|
+
*/
|
|
1039
|
+
declare const CAPTION_PRESETS: Record<CaptionPreset, Omit<CaptionStyle, 'preset'>>;
|
|
1040
|
+
/**
|
|
1041
|
+
* Default caption style (used when no preset or custom values provided)
|
|
1042
|
+
*/
|
|
1043
|
+
declare const DEFAULT_CAPTION_STYLE: Omit<CaptionStyle, "preset">;
|
|
1044
|
+
/**
|
|
1045
|
+
* Resolve a partial caption style config into a complete CaptionStyle object
|
|
1046
|
+
*
|
|
1047
|
+
* Priority:
|
|
1048
|
+
* 1. Explicit values in the input style
|
|
1049
|
+
* 2. Preset values (if preset is specified)
|
|
1050
|
+
* 3. Default values (hormozi preset)
|
|
1051
|
+
*
|
|
1052
|
+
* @param style - Partial caption style configuration
|
|
1053
|
+
* @returns Complete CaptionStyle object with all fields populated
|
|
1054
|
+
*/
|
|
1055
|
+
declare function resolveCaptionStyle(style: Partial<CaptionStyle> | undefined): CaptionStyle;
|
|
1056
|
+
/**
|
|
1057
|
+
* Get all available preset names
|
|
1058
|
+
*/
|
|
1059
|
+
declare function getCaptionPresetNames(): CaptionPreset[];
|
|
1060
|
+
/**
|
|
1061
|
+
* Check if a string is a valid caption preset name
|
|
1062
|
+
*/
|
|
1063
|
+
declare function isValidCaptionPreset(name: string): name is CaptionPreset;
|
|
1064
|
+
|
|
1065
|
+
export { FONT_URLS as $, type AutoCaptionCompositionProps as A, type BorderRadiusConfig as B, type CaptionOverlayProps as C, type DynamicCropConfig as D, type SegmentTimelinePosition as E, type FitMode as F, type CropBoundary as G, type Hyphenation as H, type ImageEditorElement as I, type CropAxisConfig as J, type CropBounds as K, type CaptionWord as L, type CaptionPage as M, type CaptionPreset as N, type CaptionPosition as O, type PositionResolutionResult as P, type CaptionFontWeight as Q, type RelativePositionConfigX as R, type SegmentType as S, type TimeValue as T, type CaptionStyle as U, type VerticalAlignment as V, type WordBreak as W, FONT_FAMILIES as X, APPLE_EMOJI_FONT as Y, getFontFamily as Z, buildFontString as _, type RelativePositionConfigY as a, preloadFonts as a0, areFontsLoaded as a1, debugFontStatus as a2, calculateFitDimensions as a3, type FitDimensions as a4, TEXT_DEFAULTS as a5, IMAGE_DEFAULTS as a6, VIDEO_DEFAULTS as a7, VISUAL_DEFAULTS as a8, applyTextDefaults as a9, generateOverlayId as aA, CAPTION_PRESETS as aB, DEFAULT_CAPTION_STYLE as aC, resolveCaptionStyle as aD, getCaptionPresetNames as aE, isValidCaptionPreset as aF, applyImageDefaults as aa, applyVideoDefaults as ab, wrapText as ac, calculateLineWidth as ad, getBorderRadii as ae, parseHexColor as af, hexToRgba as ag, resolveElementPositions as ah, calculateAutoWidthDimensions as ai, canSetAsReference as aj, getDependentElements as ak, getReferenceElementX as al, getReferenceElementY as am, type PositionResolutionError as an, calculateCropBounds as ao, isDynamicCropEnabled as ap, defaultOffset as aq, getBaseSegments as ar, getOverlays as as, getSegmentTimelinePosition as at, isSegmentVisibleAtTime as au, calculateEstimatedDuration as av, calculateTimelineContentEnd as aw, formatTime as ax, parseTime as ay, generateSegmentId as az, type TextStyleProperties as b, type FontType as c, type FontWeight as d, type TextAlignment as e, type TextDirection as f, type TextWrap as g, type TextOverflow as h, type VerticalAnchor as i, type HorizontalAnchor as j, type HorizontalSelfAnchor as k, type VerticalSelfAnchor as l, type ImageEditorNodeConfig as m, type DimensionPresetKey as n, type DimensionPreset as o, DIMENSION_PRESETS as p, type TimeMode as q, type VideoEditorBaseSegment as r, type VideoEditorVisualSegment as s, type VideoEditorVideoSegment as t, type VideoEditorAudioSegment as u, type VideoEditorImageSegment as v, type VideoEditorTextSegment as w, type VideoEditorSegment as x, type VideoEditorChannel as y, type VideoEditorNodeConfig as z };
|