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

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 {
@@ -444,15 +464,11 @@ export { CropSchema }
444
464
 
445
465
  export declare type Destination = components["schemas"]["Destinations"];
446
466
 
447
- export declare const DestinationSchema: z.ZodUnion<readonly [z.ZodIntersection<z.ZodObject<{
448
- destinations: z.ZodOptional<z.ZodLiteral<"shotstackDestination_ShotstackDestination">>;
449
- }, z.core.$strip>, z.ZodObject<{
450
- provider: z.ZodDefault<z.ZodString>;
467
+ export declare const DestinationSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
468
+ provider: z.ZodLiteral<"shotstack">;
451
469
  exclude: z.ZodOptional<z.ZodBoolean>;
452
- }, z.core.$strip>>, z.ZodIntersection<z.ZodObject<{
453
- destinations: z.ZodOptional<z.ZodLiteral<"muxDestination_MuxDestination">>;
454
470
  }, z.core.$strip>, z.ZodObject<{
455
- provider: z.ZodDefault<z.ZodString>;
471
+ provider: z.ZodLiteral<"mux">;
456
472
  options: z.ZodOptional<z.ZodObject<{
457
473
  playbackPolicy: z.ZodOptional<z.ZodArray<z.ZodEnum<{
458
474
  public: "public";
@@ -460,10 +476,8 @@ export declare const DestinationSchema: z.ZodUnion<readonly [z.ZodIntersection<z
460
476
  }>>>;
461
477
  passthrough: z.ZodOptional<z.ZodString>;
462
478
  }, z.core.$strip>>;
463
- }, z.core.$strip>>, z.ZodIntersection<z.ZodObject<{
464
- destinations: z.ZodOptional<z.ZodLiteral<"s3Destination_S3Destination">>;
465
479
  }, z.core.$strip>, z.ZodObject<{
466
- provider: z.ZodDefault<z.ZodString>;
480
+ provider: z.ZodLiteral<"s3">;
467
481
  options: z.ZodOptional<z.ZodObject<{
468
482
  region: z.ZodString;
469
483
  bucket: z.ZodString;
@@ -471,27 +485,21 @@ export declare const DestinationSchema: z.ZodUnion<readonly [z.ZodIntersection<z
471
485
  filename: z.ZodOptional<z.ZodString>;
472
486
  acl: z.ZodOptional<z.ZodString>;
473
487
  }, z.core.$strip>>;
474
- }, z.core.$strip>>, z.ZodIntersection<z.ZodObject<{
475
- destinations: z.ZodOptional<z.ZodLiteral<"googleCloudStorageDestination_GoogleCloudStorageDestination">>;
476
488
  }, z.core.$strip>, z.ZodObject<{
477
- provider: z.ZodDefault<z.ZodString>;
489
+ provider: z.ZodLiteral<"google-cloud-storage">;
478
490
  options: z.ZodOptional<z.ZodObject<{
479
491
  bucket: z.ZodString;
480
492
  prefix: z.ZodOptional<z.ZodString>;
481
493
  filename: z.ZodOptional<z.ZodString>;
482
494
  }, z.core.$strip>>;
483
- }, z.core.$strip>>, z.ZodIntersection<z.ZodObject<{
484
- destinations: z.ZodOptional<z.ZodLiteral<"googleDriveDestination_GoogleDriveDestination">>;
485
495
  }, z.core.$strip>, z.ZodObject<{
486
- provider: z.ZodDefault<z.ZodString>;
496
+ provider: z.ZodLiteral<"google-drive">;
487
497
  options: z.ZodObject<{
488
498
  folderId: z.ZodString;
489
499
  filename: z.ZodOptional<z.ZodString>;
490
500
  }, z.core.$strip>;
491
- }, z.core.$strip>>, z.ZodIntersection<z.ZodObject<{
492
- destinations: z.ZodOptional<z.ZodLiteral<"vimeoDestination_VimeoDestination">>;
493
501
  }, z.core.$strip>, z.ZodObject<{
494
- provider: z.ZodDefault<z.ZodString>;
502
+ provider: z.ZodLiteral<"vimeo">;
495
503
  options: z.ZodOptional<z.ZodObject<{
496
504
  name: z.ZodOptional<z.ZodString>;
497
505
  description: z.ZodOptional<z.ZodString>;
@@ -513,13 +521,13 @@ export declare const DestinationSchema: z.ZodUnion<readonly [z.ZodIntersection<z
513
521
  nobody: "nobody";
514
522
  contacts: "contacts";
515
523
  }>>;
524
+ download: z.ZodOptional<z.ZodBoolean>;
525
+ add: z.ZodOptional<z.ZodBoolean>;
516
526
  }, z.core.$strip>>;
517
527
  folderUri: z.ZodOptional<z.ZodString>;
518
528
  }, z.core.$strip>>;
519
- }, z.core.$strip>>, z.ZodIntersection<z.ZodObject<{
520
- destinations: z.ZodOptional<z.ZodLiteral<"tiktokDestination_TiktokDestination">>;
521
529
  }, z.core.$strip>, z.ZodObject<{
522
- provider: z.ZodDefault<z.ZodString>;
530
+ provider: z.ZodLiteral<"tiktok">;
523
531
  options: z.ZodOptional<z.ZodObject<{
524
532
  title: z.ZodOptional<z.ZodString>;
525
533
  privacyLevel: z.ZodOptional<z.ZodEnum<{
@@ -531,7 +539,9 @@ export declare const DestinationSchema: z.ZodUnion<readonly [z.ZodIntersection<z
531
539
  disableStitch: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
532
540
  disableComment: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
533
541
  }, z.core.$strip>>;
534
- }, z.core.$strip>>]>;
542
+ }, z.core.$strip>], "provider">;
543
+
544
+ declare type DocumentClipType = Clip;
535
545
 
536
546
  export declare class Edit extends Entity {
537
547
  private static readonly ZIndexPadding;
@@ -952,6 +962,185 @@ declare type EditCommand = {
952
962
  /** Alias for Edit type to avoid conflicts with SDK's Edit class */
953
963
  export declare type EditConfig = Edit_2;
954
964
 
965
+ declare class EditDocument {
966
+ private data;
967
+ constructor(edit: Edit_2);
968
+ /**
969
+ * Get the raw timeline configuration
970
+ */
971
+ getTimeline(): Edit_2["timeline"];
972
+ /**
973
+ * Get timeline background color
974
+ */
975
+ getBackground(): string | undefined;
976
+ /**
977
+ * Get all tracks (raw, unresolved)
978
+ */
979
+ getTracks(): Track[];
980
+ /**
981
+ * Get a specific track by index
982
+ */
983
+ getTrack(index: number): Track | null;
984
+ /**
985
+ * Get total number of tracks
986
+ */
987
+ getTrackCount(): number;
988
+ /**
989
+ * Get soundtrack configuration
990
+ */
991
+ getSoundtrack(): Soundtrack | undefined;
992
+ /**
993
+ * Get a specific clip by track and clip index
994
+ */
995
+ getClip(trackIndex: number, clipIndex: number): Clip | null;
996
+ /**
997
+ * Get all clips in a track
998
+ */
999
+ getClipsInTrack(trackIndex: number): Clip[];
1000
+ /**
1001
+ * Get total number of clips across all tracks
1002
+ */
1003
+ getClipCount(): number;
1004
+ /**
1005
+ * Get clip count in a specific track
1006
+ */
1007
+ getClipCountInTrack(trackIndex: number): number;
1008
+ /**
1009
+ * Get the raw output configuration
1010
+ */
1011
+ getOutput(): Edit_2["output"];
1012
+ /**
1013
+ * Get output size (width/height)
1014
+ * @throws Error if size is not defined
1015
+ */
1016
+ getSize(): Size;
1017
+ /**
1018
+ * Get output format (mp4, gif, etc.)
1019
+ */
1020
+ getFormat(): Edit_2["output"]["format"];
1021
+ /**
1022
+ * Get output FPS
1023
+ */
1024
+ getFps(): number | undefined;
1025
+ /**
1026
+ * Get output resolution preset
1027
+ */
1028
+ getResolution(): Edit_2["output"]["resolution"];
1029
+ /**
1030
+ * Get output aspect ratio
1031
+ */
1032
+ getAspectRatio(): Edit_2["output"]["aspectRatio"];
1033
+ /**
1034
+ * Get merge field definitions
1035
+ */
1036
+ getMergeFields(): Edit_2["merge"];
1037
+ /**
1038
+ * Add a new track at the specified index
1039
+ * @returns The added track
1040
+ */
1041
+ addTrack(index: number, track?: Track): Track;
1042
+ /**
1043
+ * Remove a track at the specified index
1044
+ * @returns The removed track, or null if index invalid
1045
+ */
1046
+ removeTrack(index: number): Track | null;
1047
+ /**
1048
+ * Add a clip to a track
1049
+ * @returns The added clip
1050
+ */
1051
+ addClip(trackIndex: number, clip: Clip, clipIndex?: number): Clip;
1052
+ /**
1053
+ * Remove a clip from a track
1054
+ * @returns The removed clip, or null if indices invalid
1055
+ */
1056
+ removeClip(trackIndex: number, clipIndex: number): Clip | null;
1057
+ /**
1058
+ * Update a clip's properties (partial update)
1059
+ */
1060
+ updateClip(trackIndex: number, clipIndex: number, updates: Partial<Clip>): void;
1061
+ /**
1062
+ * Replace a clip entirely
1063
+ */
1064
+ replaceClip(trackIndex: number, clipIndex: number, newClip: Clip): Clip | null;
1065
+ /**
1066
+ * Set timeline background color
1067
+ */
1068
+ setBackground(color: string): void;
1069
+ /**
1070
+ * Set soundtrack
1071
+ */
1072
+ setSoundtrack(soundtrack: Soundtrack | undefined): void;
1073
+ /**
1074
+ * Get timeline fonts
1075
+ */
1076
+ getFonts(): Array<{
1077
+ src: string;
1078
+ }>;
1079
+ /**
1080
+ * Add a font to the timeline (if not already present)
1081
+ */
1082
+ addFont(src: string): void;
1083
+ /**
1084
+ * Remove a font from the timeline
1085
+ */
1086
+ removeFont(src: string): void;
1087
+ /**
1088
+ * Set all timeline fonts (replaces existing)
1089
+ */
1090
+ setFonts(fonts: Array<{
1091
+ src: string;
1092
+ }>): void;
1093
+ /**
1094
+ * Set output size
1095
+ */
1096
+ setSize(size: Size): void;
1097
+ /**
1098
+ * Set output format
1099
+ */
1100
+ setFormat(format: Edit_2["output"]["format"]): void;
1101
+ /**
1102
+ * Set output FPS (must be a valid FPS value)
1103
+ */
1104
+ setFps(fps: Edit_2["output"]["fps"]): void;
1105
+ /**
1106
+ * Set output resolution preset
1107
+ */
1108
+ setResolution(resolution: Edit_2["output"]["resolution"]): void;
1109
+ /**
1110
+ * Clear output resolution preset
1111
+ */
1112
+ clearResolution(): void;
1113
+ /**
1114
+ * Set output aspect ratio
1115
+ */
1116
+ setAspectRatio(aspectRatio: Edit_2["output"]["aspectRatio"]): void;
1117
+ /**
1118
+ * Clear output aspect ratio
1119
+ */
1120
+ clearAspectRatio(): void;
1121
+ /**
1122
+ * Clear output size (for use when setting resolution/aspectRatio)
1123
+ */
1124
+ clearSize(): void;
1125
+ /**
1126
+ * Set merge field definitions
1127
+ */
1128
+ setMergeFields(mergeFields: Edit_2["merge"]): void;
1129
+ /**
1130
+ * Export the document as raw Edit JSON (preserves "auto", "end", placeholders)
1131
+ * This is what gets sent to the backend API.
1132
+ */
1133
+ toJSON(): Edit_2;
1134
+ /**
1135
+ * Create an EditDocument from raw Edit JSON
1136
+ */
1137
+ static fromJSON(json: Edit_2): EditDocument;
1138
+ /**
1139
+ * Create a deep clone of this document
1140
+ */
1141
+ clone(): EditDocument;
1142
+ }
1143
+
955
1144
  export declare const EditEvent: {
956
1145
  readonly PlaybackPlay: "playback:play";
957
1146
  readonly PlaybackPause: "playback:pause";
@@ -1240,6 +1429,7 @@ export declare class MediaToolbar extends BaseToolbar {
1240
1429
  private fitLabel;
1241
1430
  private volumeSlider;
1242
1431
  private volumeValue;
1432
+ private volumeDisplayInput;
1243
1433
  private volumeSection;
1244
1434
  private visualSection;
1245
1435
  private audioSection;
@@ -1264,6 +1454,18 @@ export declare class MediaToolbar extends BaseToolbar {
1264
1454
  private handleOpacityChange;
1265
1455
  private handleScaleChange;
1266
1456
  private handleVolumeChange;
1457
+ /**
1458
+ * Parse and commit the value from the volume text input.
1459
+ */
1460
+ private commitVolumeInputValue;
1461
+ /**
1462
+ * Revert the volume text input to match the current slider value.
1463
+ */
1464
+ private revertVolumeInputValue;
1465
+ /**
1466
+ * Parse user input, strip non-numeric chars, clamp to 0-100.
1467
+ */
1468
+ private parseVolumeInputValue;
1267
1469
  private applyTransitionUpdate;
1268
1470
  private applyEffect;
1269
1471
  private handleAudioFadeSelect;
@@ -1439,12 +1641,8 @@ declare interface PlaybackHealth {
1439
1641
  * Base class for all visual content players in the canvas.
1440
1642
  *
1441
1643
  * 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.
1644
+ * and applying keyframe animations.
1445
1645
  *
1446
- * This separation allows Canvas to be used as a pure preview renderer
1447
- * without any interactive overlays.
1448
1646
  */
1449
1647
  declare abstract class Player extends Entity {
1450
1648
  private static readonly DiscardedFrameCount;
@@ -1466,7 +1664,6 @@ declare abstract class Player extends Entity {
1466
1664
  protected contentContainer: pixi.Container;
1467
1665
  /**
1468
1666
  * Tracks which properties came from merge field templates.
1469
- * Key: property path (e.g., "asset.src"), Value: binding info
1470
1667
  */
1471
1668
  private mergeFieldBindings;
1472
1669
  constructor(edit: Edit, clipConfiguration: ResolvedClip, playerType: PlayerType);
@@ -1490,10 +1687,8 @@ declare abstract class Player extends Entity {
1490
1687
  setTimingIntent(intent: Partial<TimingIntent>): void;
1491
1688
  getResolvedTiming(): ResolvedTiming;
1492
1689
  setResolvedTiming(timing: ResolvedTiming): void;
1493
- convertToFixedTiming(): void;
1494
1690
  /**
1495
1691
  * Set a merge field binding for a property path.
1496
- * Called when a property is resolved from a merge field template.
1497
1692
  */
1498
1693
  setMergeFieldBinding(path: string, binding: MergeFieldBinding): void;
1499
1694
  /**
@@ -1514,20 +1709,15 @@ declare abstract class Player extends Entity {
1514
1709
  setInitialBindings(bindings: Map<string, MergeFieldBinding>): void;
1515
1710
  /**
1516
1711
  * 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
1712
  */
1520
1713
  getExportableClip(): Clip;
1521
1714
  /**
1522
1715
  * Get the playback time relative to clip start, in seconds.
1523
- * Used for keyframe animation calculations.
1524
1716
  */
1525
1717
  getPlaybackTime(): number;
1526
1718
  abstract getSize(): Size;
1527
1719
  /**
1528
1720
  * 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
1721
  */
1532
1722
  getContentSize(): Size;
1533
1723
  getOpacity(): number;
@@ -1578,6 +1768,20 @@ declare enum PlayerType {
1578
1768
 
1579
1769
  declare type ResolutionChangeCallback = (width: number, height: number) => void;
1580
1770
 
1771
+ /**
1772
+ * Context required to resolve timing intent to concrete values.
1773
+ *
1774
+ * @see resolveTimingIntent - the pure function that uses this context
1775
+ */
1776
+ declare interface ResolutionContext {
1777
+ /** End time of previous clip on same track (for start: "auto") */
1778
+ readonly previousClipEnd: Seconds;
1779
+ /** Total duration of timeline excluding "end" clips (for length: "end") */
1780
+ readonly timelineEnd: Seconds;
1781
+ /** Intrinsic duration from asset metadata, null if not yet loaded (for length: "auto") */
1782
+ readonly intrinsicDuration: Seconds | null;
1783
+ }
1784
+
1581
1785
  declare type ResolvedClip = Omit<Clip, "start" | "length"> & {
1582
1786
  start: Seconds;
1583
1787
  length: Seconds;