@shotstack/shotstack-studio 2.0.0-beta.16 → 2.0.0-beta.17

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/index.d.ts CHANGED
@@ -375,7 +375,9 @@ declare interface ClipStats {
375
375
  export declare class ClipToolbar extends BaseToolbar {
376
376
  private startControl;
377
377
  private lengthControl;
378
+ private editChangedListener;
378
379
  mount(parent: HTMLElement): void;
380
+ private setupEventListeners;
379
381
  private mountComponents;
380
382
  private applyTimingUpdate;
381
383
  protected syncState(): void;
@@ -424,6 +426,24 @@ declare type CommandContext = {
424
426
  setOutputFps(fps: number): void;
425
427
  getTimelineBackground(): string;
426
428
  setTimelineBackground(color: string): void;
429
+ getDocument(): EditDocument | null;
430
+ /** Update a clip's properties in the document (source of truth) */
431
+ documentUpdateClip(trackIdx: number, clipIdx: number, updates: Partial<DocumentClipType>): void;
432
+ /** Add a clip to the document, returns the added clip */
433
+ documentAddClip(trackIdx: number, clip: DocumentClipType, clipIdx?: number): DocumentClipType;
434
+ /** Remove a clip from the document, returns the removed clip or null */
435
+ documentRemoveClip(trackIdx: number, clipIdx: number): DocumentClipType | null;
436
+ /** Derive runtime Player state from document clip (applies document data to Player) */
437
+ derivePlayerFromDocument(trackIdx: number, clipIdx: number): void;
438
+ /**
439
+ * Build resolution context for a clip at the given position.
440
+ * Extracts all dependencies upfront so resolution can be pure.
441
+ *
442
+ * @param trackIdx - Track index
443
+ * @param clipIdx - Clip index on that track
444
+ * @returns Context with previousClipEnd, timelineEnd, intrinsicDuration
445
+ */
446
+ buildResolutionContext(trackIdx: number, clipIdx: number): ResolutionContext;
427
447
  };
428
448
 
429
449
  export declare class Controls {
@@ -533,6 +553,8 @@ export declare const DestinationSchema: z.ZodUnion<readonly [z.ZodIntersection<z
533
553
  }, z.core.$strip>>;
534
554
  }, z.core.$strip>>]>;
535
555
 
556
+ declare type DocumentClipType = Clip;
557
+
536
558
  export declare class Edit extends Entity {
537
559
  private static readonly ZIndexPadding;
538
560
  /**
@@ -952,6 +974,185 @@ declare type EditCommand = {
952
974
  /** Alias for Edit type to avoid conflicts with SDK's Edit class */
953
975
  export declare type EditConfig = Edit_2;
954
976
 
977
+ declare class EditDocument {
978
+ private data;
979
+ constructor(edit: Edit_2);
980
+ /**
981
+ * Get the raw timeline configuration
982
+ */
983
+ getTimeline(): Edit_2["timeline"];
984
+ /**
985
+ * Get timeline background color
986
+ */
987
+ getBackground(): string | undefined;
988
+ /**
989
+ * Get all tracks (raw, unresolved)
990
+ */
991
+ getTracks(): Track[];
992
+ /**
993
+ * Get a specific track by index
994
+ */
995
+ getTrack(index: number): Track | null;
996
+ /**
997
+ * Get total number of tracks
998
+ */
999
+ getTrackCount(): number;
1000
+ /**
1001
+ * Get soundtrack configuration
1002
+ */
1003
+ getSoundtrack(): Soundtrack | undefined;
1004
+ /**
1005
+ * Get a specific clip by track and clip index
1006
+ */
1007
+ getClip(trackIndex: number, clipIndex: number): Clip | null;
1008
+ /**
1009
+ * Get all clips in a track
1010
+ */
1011
+ getClipsInTrack(trackIndex: number): Clip[];
1012
+ /**
1013
+ * Get total number of clips across all tracks
1014
+ */
1015
+ getClipCount(): number;
1016
+ /**
1017
+ * Get clip count in a specific track
1018
+ */
1019
+ getClipCountInTrack(trackIndex: number): number;
1020
+ /**
1021
+ * Get the raw output configuration
1022
+ */
1023
+ getOutput(): Edit_2["output"];
1024
+ /**
1025
+ * Get output size (width/height)
1026
+ * @throws Error if size is not defined
1027
+ */
1028
+ getSize(): Size;
1029
+ /**
1030
+ * Get output format (mp4, gif, etc.)
1031
+ */
1032
+ getFormat(): Edit_2["output"]["format"];
1033
+ /**
1034
+ * Get output FPS
1035
+ */
1036
+ getFps(): number | undefined;
1037
+ /**
1038
+ * Get output resolution preset
1039
+ */
1040
+ getResolution(): Edit_2["output"]["resolution"];
1041
+ /**
1042
+ * Get output aspect ratio
1043
+ */
1044
+ getAspectRatio(): Edit_2["output"]["aspectRatio"];
1045
+ /**
1046
+ * Get merge field definitions
1047
+ */
1048
+ getMergeFields(): Edit_2["merge"];
1049
+ /**
1050
+ * Add a new track at the specified index
1051
+ * @returns The added track
1052
+ */
1053
+ addTrack(index: number, track?: Track): Track;
1054
+ /**
1055
+ * Remove a track at the specified index
1056
+ * @returns The removed track, or null if index invalid
1057
+ */
1058
+ removeTrack(index: number): Track | null;
1059
+ /**
1060
+ * Add a clip to a track
1061
+ * @returns The added clip
1062
+ */
1063
+ addClip(trackIndex: number, clip: Clip, clipIndex?: number): Clip;
1064
+ /**
1065
+ * Remove a clip from a track
1066
+ * @returns The removed clip, or null if indices invalid
1067
+ */
1068
+ removeClip(trackIndex: number, clipIndex: number): Clip | null;
1069
+ /**
1070
+ * Update a clip's properties (partial update)
1071
+ */
1072
+ updateClip(trackIndex: number, clipIndex: number, updates: Partial<Clip>): void;
1073
+ /**
1074
+ * Replace a clip entirely
1075
+ */
1076
+ replaceClip(trackIndex: number, clipIndex: number, newClip: Clip): Clip | null;
1077
+ /**
1078
+ * Set timeline background color
1079
+ */
1080
+ setBackground(color: string): void;
1081
+ /**
1082
+ * Set soundtrack
1083
+ */
1084
+ setSoundtrack(soundtrack: Soundtrack | undefined): void;
1085
+ /**
1086
+ * Get timeline fonts
1087
+ */
1088
+ getFonts(): Array<{
1089
+ src: string;
1090
+ }>;
1091
+ /**
1092
+ * Add a font to the timeline (if not already present)
1093
+ */
1094
+ addFont(src: string): void;
1095
+ /**
1096
+ * Remove a font from the timeline
1097
+ */
1098
+ removeFont(src: string): void;
1099
+ /**
1100
+ * Set all timeline fonts (replaces existing)
1101
+ */
1102
+ setFonts(fonts: Array<{
1103
+ src: string;
1104
+ }>): void;
1105
+ /**
1106
+ * Set output size
1107
+ */
1108
+ setSize(size: Size): void;
1109
+ /**
1110
+ * Set output format
1111
+ */
1112
+ setFormat(format: Edit_2["output"]["format"]): void;
1113
+ /**
1114
+ * Set output FPS (must be a valid FPS value)
1115
+ */
1116
+ setFps(fps: Edit_2["output"]["fps"]): void;
1117
+ /**
1118
+ * Set output resolution preset
1119
+ */
1120
+ setResolution(resolution: Edit_2["output"]["resolution"]): void;
1121
+ /**
1122
+ * Clear output resolution preset
1123
+ */
1124
+ clearResolution(): void;
1125
+ /**
1126
+ * Set output aspect ratio
1127
+ */
1128
+ setAspectRatio(aspectRatio: Edit_2["output"]["aspectRatio"]): void;
1129
+ /**
1130
+ * Clear output aspect ratio
1131
+ */
1132
+ clearAspectRatio(): void;
1133
+ /**
1134
+ * Clear output size (for use when setting resolution/aspectRatio)
1135
+ */
1136
+ clearSize(): void;
1137
+ /**
1138
+ * Set merge field definitions
1139
+ */
1140
+ setMergeFields(mergeFields: Edit_2["merge"]): void;
1141
+ /**
1142
+ * Export the document as raw Edit JSON (preserves "auto", "end", placeholders)
1143
+ * This is what gets sent to the backend API.
1144
+ */
1145
+ toJSON(): Edit_2;
1146
+ /**
1147
+ * Create an EditDocument from raw Edit JSON
1148
+ */
1149
+ static fromJSON(json: Edit_2): EditDocument;
1150
+ /**
1151
+ * Create a deep clone of this document
1152
+ */
1153
+ clone(): EditDocument;
1154
+ }
1155
+
955
1156
  export declare const EditEvent: {
956
1157
  readonly PlaybackPlay: "playback:play";
957
1158
  readonly PlaybackPause: "playback:pause";
@@ -1240,6 +1441,7 @@ export declare class MediaToolbar extends BaseToolbar {
1240
1441
  private fitLabel;
1241
1442
  private volumeSlider;
1242
1443
  private volumeValue;
1444
+ private volumeDisplayInput;
1243
1445
  private volumeSection;
1244
1446
  private visualSection;
1245
1447
  private audioSection;
@@ -1264,6 +1466,18 @@ export declare class MediaToolbar extends BaseToolbar {
1264
1466
  private handleOpacityChange;
1265
1467
  private handleScaleChange;
1266
1468
  private handleVolumeChange;
1469
+ /**
1470
+ * Parse and commit the value from the volume text input.
1471
+ */
1472
+ private commitVolumeInputValue;
1473
+ /**
1474
+ * Revert the volume text input to match the current slider value.
1475
+ */
1476
+ private revertVolumeInputValue;
1477
+ /**
1478
+ * Parse user input, strip non-numeric chars, clamp to 0-100.
1479
+ */
1480
+ private parseVolumeInputValue;
1267
1481
  private applyTransitionUpdate;
1268
1482
  private applyEffect;
1269
1483
  private handleAudioFadeSelect;
@@ -1439,12 +1653,8 @@ declare interface PlaybackHealth {
1439
1653
  * Base class for all visual content players in the canvas.
1440
1654
  *
1441
1655
  * Player is responsible for rendering clip content (video, image, text, etc.)
1442
- * and applying keyframe animations. It does NOT handle selection UI or
1443
- * drag/resize/rotate interactions - those are handled by SelectionHandles
1444
- * when registered via UIController.
1656
+ * and applying keyframe animations.
1445
1657
  *
1446
- * This separation allows Canvas to be used as a pure preview renderer
1447
- * without any interactive overlays.
1448
1658
  */
1449
1659
  declare abstract class Player extends Entity {
1450
1660
  private static readonly DiscardedFrameCount;
@@ -1466,7 +1676,6 @@ declare abstract class Player extends Entity {
1466
1676
  protected contentContainer: pixi.Container;
1467
1677
  /**
1468
1678
  * Tracks which properties came from merge field templates.
1469
- * Key: property path (e.g., "asset.src"), Value: binding info
1470
1679
  */
1471
1680
  private mergeFieldBindings;
1472
1681
  constructor(edit: Edit, clipConfiguration: ResolvedClip, playerType: PlayerType);
@@ -1490,10 +1699,8 @@ declare abstract class Player extends Entity {
1490
1699
  setTimingIntent(intent: Partial<TimingIntent>): void;
1491
1700
  getResolvedTiming(): ResolvedTiming;
1492
1701
  setResolvedTiming(timing: ResolvedTiming): void;
1493
- convertToFixedTiming(): void;
1494
1702
  /**
1495
1703
  * Set a merge field binding for a property path.
1496
- * Called when a property is resolved from a merge field template.
1497
1704
  */
1498
1705
  setMergeFieldBinding(path: string, binding: MergeFieldBinding): void;
1499
1706
  /**
@@ -1514,20 +1721,15 @@ declare abstract class Player extends Entity {
1514
1721
  setInitialBindings(bindings: Map<string, MergeFieldBinding>): void;
1515
1722
  /**
1516
1723
  * Get the exportable clip configuration with merge field placeholders restored.
1517
- * For properties that haven't changed from their resolved value, the original
1518
- * placeholder (e.g., "{{ HERO_IMAGE }}") is restored for export.
1519
1724
  */
1520
1725
  getExportableClip(): Clip;
1521
1726
  /**
1522
1727
  * Get the playback time relative to clip start, in seconds.
1523
- * Used for keyframe animation calculations.
1524
1728
  */
1525
1729
  getPlaybackTime(): number;
1526
1730
  abstract getSize(): Size;
1527
1731
  /**
1528
1732
  * Returns the source content dimensions (before fit scaling).
1529
- * Override in subclasses that have different source vs output sizes.
1530
- * Default implementation returns getSize().
1531
1733
  */
1532
1734
  getContentSize(): Size;
1533
1735
  getOpacity(): number;
@@ -1578,6 +1780,20 @@ declare enum PlayerType {
1578
1780
 
1579
1781
  declare type ResolutionChangeCallback = (width: number, height: number) => void;
1580
1782
 
1783
+ /**
1784
+ * Context required to resolve timing intent to concrete values.
1785
+ *
1786
+ * @see resolveTimingIntent - the pure function that uses this context
1787
+ */
1788
+ declare interface ResolutionContext {
1789
+ /** End time of previous clip on same track (for start: "auto") */
1790
+ readonly previousClipEnd: Seconds;
1791
+ /** Total duration of timeline excluding "end" clips (for length: "end") */
1792
+ readonly timelineEnd: Seconds;
1793
+ /** Intrinsic duration from asset metadata, null if not yet loaded (for length: "auto") */
1794
+ readonly intrinsicDuration: Seconds | null;
1795
+ }
1796
+
1581
1797
  declare type ResolvedClip = Omit<Clip, "start" | "length"> & {
1582
1798
  start: Seconds;
1583
1799
  length: Seconds;