ugcinc-render 1.8.140 → 1.8.141

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.mts CHANGED
@@ -544,6 +544,67 @@ declare function isDeduplicationLevel(input: DeduplicationInput): input is Dedup
544
544
  */
545
545
  declare function resolveDeduplicationConfig(input: DeduplicationInput): DeduplicationConfig;
546
546
 
547
+ /**
548
+ * Simplified public types for Instagram DM composition
549
+ *
550
+ * These are the types exposed to users via the automation node.
551
+ * They provide a simpler interface than the full InstagramDmCompositionProps.
552
+ */
553
+ /** Message sender side */
554
+ type IgDmSender = 'user' | 'recipient';
555
+ /** Theme for the DM composition */
556
+ type IgDmTheme = 'light' | 'dark';
557
+ /**
558
+ * A single message in the conversation (simplified)
559
+ *
560
+ * This is the user-facing message format that gets converted
561
+ * to the full IgMessage type internally.
562
+ */
563
+ interface IgDmMessage {
564
+ /** Message text content */
565
+ text: string;
566
+ /**
567
+ * Who sent this message:
568
+ * - 'user' = sender (right side, gradient bubbles)
569
+ * - 'recipient' = receiver (left side, gray bubbles)
570
+ */
571
+ sender: IgDmSender;
572
+ /**
573
+ * Whether this is a reply to a story.
574
+ * Only valid when sender='user'. Will be ignored for recipient messages.
575
+ */
576
+ isStoryReply?: boolean;
577
+ /**
578
+ * Whether to group with the previous message.
579
+ * When true, uses smaller gap and connected bubble corners.
580
+ */
581
+ groupWithPrevious?: boolean;
582
+ }
583
+ /**
584
+ * Public-facing input params for Instagram DM composition
585
+ *
586
+ * These are what users configure in the automation node.
587
+ * The system converts these to full InstagramDmCompositionProps internally.
588
+ */
589
+ interface InstagramDmPublicInput {
590
+ /** Receiver's username (shown in header) */
591
+ receiverUsername: string;
592
+ /**
593
+ * Receiver's profile picture URL.
594
+ * Used in both the header and next to recipient messages.
595
+ */
596
+ receiverProfilePicUrl: string;
597
+ /** Theme - light or dark mode */
598
+ theme: IgDmTheme;
599
+ /** Messages in the conversation (in chronological order) */
600
+ messages: IgDmMessage[];
601
+ /**
602
+ * Story image URL for story reply messages.
603
+ * Required if any message has isStoryReply=true.
604
+ */
605
+ storyImageUrl?: string;
606
+ }
607
+
547
608
  interface ImageEditorCompositionProps {
548
609
  /** The editor configuration to render (legacy format with pre-resolved segments) */
549
610
  config?: ImageEditorConfig;
@@ -875,6 +936,36 @@ interface InstagramDmCompositionProps {
875
936
  declare const defaultInstagramDmProps: InstagramDmCompositionProps;
876
937
  declare function InstagramDmComposition(props: InstagramDmCompositionProps): react_jsx_runtime.JSX.Element;
877
938
 
939
+ /**
940
+ * Convert simplified public input to full InstagramDmComposition props
941
+ *
942
+ * This module transforms the user-friendly InstagramDmPublicInput
943
+ * into the full InstagramDmCompositionProps used by the composition.
944
+ */
945
+
946
+ /**
947
+ * Validation error returned when input is invalid
948
+ */
949
+ interface ValidationError {
950
+ field: string;
951
+ message: string;
952
+ }
953
+ /**
954
+ * Validate public input before conversion
955
+ *
956
+ * @param input - The public input to validate
957
+ * @returns Array of validation errors (empty if valid)
958
+ */
959
+ declare function validatePublicInput(input: InstagramDmPublicInput): ValidationError[];
960
+ /**
961
+ * Convert simplified public input to full composition props
962
+ *
963
+ * @param input - The simplified public input
964
+ * @returns Full InstagramDmCompositionProps ready for rendering
965
+ * @throws Error if validation fails
966
+ */
967
+ declare function convertPublicToProps(input: InstagramDmPublicInput): InstagramDmCompositionProps;
968
+
878
969
  /**
879
970
  * Platform-agnostic messaging types
880
971
  *
@@ -1352,4 +1443,4 @@ declare function useResolvedPositions(elements: ImageEditorElement[], textValues
1352
1443
 
1353
1444
  declare const RenderRoot: React.FC;
1354
1445
 
1355
- export { type Acceleration, type AudioConfig, type AudioSegment, AutoCaptionComposition, AutoCaptionCompositionProps, AutoCaptionCompositionWithVideo, type BaseBubbleStyle, type BaseEditorConfig, type BaseMessage, type BaseMessageType, type BaseSegment, type BlendMode, BorderRadiusConfig, type BubbleRadii, CaptionOverlay, CaptionOverlayProps, type Channel, type ColorFilterConfig, type ColorShiftConfig, type CropConfig, type CuttingConfig, DEDUPLICATION_LEVELS, type DeduplicationConfig, type DeduplicationInput, type DeduplicationLevel, type DiagonalFilterConfig, type DiagonalFilterType, DynamicCropConfig, type EditorConfig, type EditorSegment, type EnhanceLevel, type EnhancementConfig, FitMode, FontWeight, type FrameManipulationConfig, type GifOverlayConfig, type GifSource, type GradientColor, type GradientOverlayConfig, type IgTheme, ImageEditorComposition, type ImageEditorCompositionProps, type ImageEditorConfig, ImageEditorElement, ImageElement, type ImageElementProps, type ImageMessage, type ImageSegment, type ImageSequenceSegment, InstagramDmComposition, type InstagramDmCompositionProps, LEVEL_1_CONFIG, LEVEL_2_CONFIG, LEVEL_3_CONFIG, LEVEL_4_CONFIG, LEVEL_5_CONFIG, type LensCorrectionConfig, MediaBubble, type MediaBubbleProps, type Message, MessageBubble, type MessageBubbleProps, type MessageGroup, type MessageOrTyping, type MessagePosition, type MessageReaction, type MessageSender, type MobileEncodingConfig, type ParticleOverlayConfig, type PhoneConfig, type PhoneModel, type PhoneType, type PictureSegment, PositionResolutionResult, type PositionedMessage, ProfilePic, type ProfilePicProps, Reaction, type ReactionProps, type ReadReceipt, type ReadReceiptState, RelativePositionConfigX, RelativePositionConfigY, RenderRoot, ScreenshotAnimation, ScreenshotAnimationProps, type Segment, SegmentType, type SpeedConfig, type StaticSegment, TYPING_ANIMATION, TextElement, type TextElementProps, type TextMessage, type TextSegment, TextStyleProperties, TimeValue, type TraceRemovalConfig, TypingIndicator, type TypingIndicatorProps, type TypingIndicatorStyle, type TypingMessage, type UserProfile, type VideoCodec, VideoEditorComposition, type VideoEditorCompositionProps, type VideoEditorConfig, VideoElement, type VideoElementProps, type VideoExtension, type VideoSegment, type VideoSequenceSegment, type VisualAdjustmentsConfig, type VisualSegment, type VisualSegmentUnion, bubbleRadiiToCss, calculateBubbleRadii, defaultInstagramDmProps, flattenGroups, groupMessages, isDeduplicationLevel, resolveDeduplicationConfig, useFontsLoaded, useImageLoader, useImagePreloader, useResolvedPositions };
1446
+ export { type Acceleration, type AudioConfig, type AudioSegment, AutoCaptionComposition, AutoCaptionCompositionProps, AutoCaptionCompositionWithVideo, type BaseBubbleStyle, type BaseEditorConfig, type BaseMessage, type BaseMessageType, type BaseSegment, type BlendMode, BorderRadiusConfig, type BubbleRadii, CaptionOverlay, CaptionOverlayProps, type Channel, type ColorFilterConfig, type ColorShiftConfig, type CropConfig, type CuttingConfig, DEDUPLICATION_LEVELS, type DeduplicationConfig, type DeduplicationInput, type DeduplicationLevel, type DiagonalFilterConfig, type DiagonalFilterType, DynamicCropConfig, type EditorConfig, type EditorSegment, type EnhanceLevel, type EnhancementConfig, FitMode, FontWeight, type FrameManipulationConfig, type GifOverlayConfig, type GifSource, type GradientColor, type GradientOverlayConfig, type IgDmMessage, type IgDmSender, type IgDmTheme, type IgTheme, ImageEditorComposition, type ImageEditorCompositionProps, type ImageEditorConfig, ImageEditorElement, ImageElement, type ImageElementProps, type ImageMessage, type ImageSegment, type ImageSequenceSegment, InstagramDmComposition, type InstagramDmCompositionProps, type InstagramDmPublicInput, LEVEL_1_CONFIG, LEVEL_2_CONFIG, LEVEL_3_CONFIG, LEVEL_4_CONFIG, LEVEL_5_CONFIG, type LensCorrectionConfig, MediaBubble, type MediaBubbleProps, type Message, MessageBubble, type MessageBubbleProps, type MessageGroup, type MessageOrTyping, type MessagePosition, type MessageReaction, type MessageSender, type MobileEncodingConfig, type ParticleOverlayConfig, type PhoneConfig, type PhoneModel, type PhoneType, type PictureSegment, PositionResolutionResult, type PositionedMessage, ProfilePic, type ProfilePicProps, Reaction, type ReactionProps, type ReadReceipt, type ReadReceiptState, RelativePositionConfigX, RelativePositionConfigY, RenderRoot, ScreenshotAnimation, ScreenshotAnimationProps, type Segment, SegmentType, type SpeedConfig, type StaticSegment, TYPING_ANIMATION, TextElement, type TextElementProps, type TextMessage, type TextSegment, TextStyleProperties, TimeValue, type TraceRemovalConfig, TypingIndicator, type TypingIndicatorProps, type TypingIndicatorStyle, type TypingMessage, type UserProfile, type ValidationError, type VideoCodec, VideoEditorComposition, type VideoEditorCompositionProps, type VideoEditorConfig, VideoElement, type VideoElementProps, type VideoExtension, type VideoSegment, type VideoSequenceSegment, type VisualAdjustmentsConfig, type VisualSegment, type VisualSegmentUnion, bubbleRadiiToCss, calculateBubbleRadii, convertPublicToProps, defaultInstagramDmProps, flattenGroups, groupMessages, isDeduplicationLevel, resolveDeduplicationConfig, useFontsLoaded, useImageLoader, useImagePreloader, useResolvedPositions, validatePublicInput };
package/dist/index.d.ts CHANGED
@@ -544,6 +544,67 @@ declare function isDeduplicationLevel(input: DeduplicationInput): input is Dedup
544
544
  */
545
545
  declare function resolveDeduplicationConfig(input: DeduplicationInput): DeduplicationConfig;
546
546
 
547
+ /**
548
+ * Simplified public types for Instagram DM composition
549
+ *
550
+ * These are the types exposed to users via the automation node.
551
+ * They provide a simpler interface than the full InstagramDmCompositionProps.
552
+ */
553
+ /** Message sender side */
554
+ type IgDmSender = 'user' | 'recipient';
555
+ /** Theme for the DM composition */
556
+ type IgDmTheme = 'light' | 'dark';
557
+ /**
558
+ * A single message in the conversation (simplified)
559
+ *
560
+ * This is the user-facing message format that gets converted
561
+ * to the full IgMessage type internally.
562
+ */
563
+ interface IgDmMessage {
564
+ /** Message text content */
565
+ text: string;
566
+ /**
567
+ * Who sent this message:
568
+ * - 'user' = sender (right side, gradient bubbles)
569
+ * - 'recipient' = receiver (left side, gray bubbles)
570
+ */
571
+ sender: IgDmSender;
572
+ /**
573
+ * Whether this is a reply to a story.
574
+ * Only valid when sender='user'. Will be ignored for recipient messages.
575
+ */
576
+ isStoryReply?: boolean;
577
+ /**
578
+ * Whether to group with the previous message.
579
+ * When true, uses smaller gap and connected bubble corners.
580
+ */
581
+ groupWithPrevious?: boolean;
582
+ }
583
+ /**
584
+ * Public-facing input params for Instagram DM composition
585
+ *
586
+ * These are what users configure in the automation node.
587
+ * The system converts these to full InstagramDmCompositionProps internally.
588
+ */
589
+ interface InstagramDmPublicInput {
590
+ /** Receiver's username (shown in header) */
591
+ receiverUsername: string;
592
+ /**
593
+ * Receiver's profile picture URL.
594
+ * Used in both the header and next to recipient messages.
595
+ */
596
+ receiverProfilePicUrl: string;
597
+ /** Theme - light or dark mode */
598
+ theme: IgDmTheme;
599
+ /** Messages in the conversation (in chronological order) */
600
+ messages: IgDmMessage[];
601
+ /**
602
+ * Story image URL for story reply messages.
603
+ * Required if any message has isStoryReply=true.
604
+ */
605
+ storyImageUrl?: string;
606
+ }
607
+
547
608
  interface ImageEditorCompositionProps {
548
609
  /** The editor configuration to render (legacy format with pre-resolved segments) */
549
610
  config?: ImageEditorConfig;
@@ -875,6 +936,36 @@ interface InstagramDmCompositionProps {
875
936
  declare const defaultInstagramDmProps: InstagramDmCompositionProps;
876
937
  declare function InstagramDmComposition(props: InstagramDmCompositionProps): react_jsx_runtime.JSX.Element;
877
938
 
939
+ /**
940
+ * Convert simplified public input to full InstagramDmComposition props
941
+ *
942
+ * This module transforms the user-friendly InstagramDmPublicInput
943
+ * into the full InstagramDmCompositionProps used by the composition.
944
+ */
945
+
946
+ /**
947
+ * Validation error returned when input is invalid
948
+ */
949
+ interface ValidationError {
950
+ field: string;
951
+ message: string;
952
+ }
953
+ /**
954
+ * Validate public input before conversion
955
+ *
956
+ * @param input - The public input to validate
957
+ * @returns Array of validation errors (empty if valid)
958
+ */
959
+ declare function validatePublicInput(input: InstagramDmPublicInput): ValidationError[];
960
+ /**
961
+ * Convert simplified public input to full composition props
962
+ *
963
+ * @param input - The simplified public input
964
+ * @returns Full InstagramDmCompositionProps ready for rendering
965
+ * @throws Error if validation fails
966
+ */
967
+ declare function convertPublicToProps(input: InstagramDmPublicInput): InstagramDmCompositionProps;
968
+
878
969
  /**
879
970
  * Platform-agnostic messaging types
880
971
  *
@@ -1352,4 +1443,4 @@ declare function useResolvedPositions(elements: ImageEditorElement[], textValues
1352
1443
 
1353
1444
  declare const RenderRoot: React.FC;
1354
1445
 
1355
- export { type Acceleration, type AudioConfig, type AudioSegment, AutoCaptionComposition, AutoCaptionCompositionProps, AutoCaptionCompositionWithVideo, type BaseBubbleStyle, type BaseEditorConfig, type BaseMessage, type BaseMessageType, type BaseSegment, type BlendMode, BorderRadiusConfig, type BubbleRadii, CaptionOverlay, CaptionOverlayProps, type Channel, type ColorFilterConfig, type ColorShiftConfig, type CropConfig, type CuttingConfig, DEDUPLICATION_LEVELS, type DeduplicationConfig, type DeduplicationInput, type DeduplicationLevel, type DiagonalFilterConfig, type DiagonalFilterType, DynamicCropConfig, type EditorConfig, type EditorSegment, type EnhanceLevel, type EnhancementConfig, FitMode, FontWeight, type FrameManipulationConfig, type GifOverlayConfig, type GifSource, type GradientColor, type GradientOverlayConfig, type IgTheme, ImageEditorComposition, type ImageEditorCompositionProps, type ImageEditorConfig, ImageEditorElement, ImageElement, type ImageElementProps, type ImageMessage, type ImageSegment, type ImageSequenceSegment, InstagramDmComposition, type InstagramDmCompositionProps, LEVEL_1_CONFIG, LEVEL_2_CONFIG, LEVEL_3_CONFIG, LEVEL_4_CONFIG, LEVEL_5_CONFIG, type LensCorrectionConfig, MediaBubble, type MediaBubbleProps, type Message, MessageBubble, type MessageBubbleProps, type MessageGroup, type MessageOrTyping, type MessagePosition, type MessageReaction, type MessageSender, type MobileEncodingConfig, type ParticleOverlayConfig, type PhoneConfig, type PhoneModel, type PhoneType, type PictureSegment, PositionResolutionResult, type PositionedMessage, ProfilePic, type ProfilePicProps, Reaction, type ReactionProps, type ReadReceipt, type ReadReceiptState, RelativePositionConfigX, RelativePositionConfigY, RenderRoot, ScreenshotAnimation, ScreenshotAnimationProps, type Segment, SegmentType, type SpeedConfig, type StaticSegment, TYPING_ANIMATION, TextElement, type TextElementProps, type TextMessage, type TextSegment, TextStyleProperties, TimeValue, type TraceRemovalConfig, TypingIndicator, type TypingIndicatorProps, type TypingIndicatorStyle, type TypingMessage, type UserProfile, type VideoCodec, VideoEditorComposition, type VideoEditorCompositionProps, type VideoEditorConfig, VideoElement, type VideoElementProps, type VideoExtension, type VideoSegment, type VideoSequenceSegment, type VisualAdjustmentsConfig, type VisualSegment, type VisualSegmentUnion, bubbleRadiiToCss, calculateBubbleRadii, defaultInstagramDmProps, flattenGroups, groupMessages, isDeduplicationLevel, resolveDeduplicationConfig, useFontsLoaded, useImageLoader, useImagePreloader, useResolvedPositions };
1446
+ export { type Acceleration, type AudioConfig, type AudioSegment, AutoCaptionComposition, AutoCaptionCompositionProps, AutoCaptionCompositionWithVideo, type BaseBubbleStyle, type BaseEditorConfig, type BaseMessage, type BaseMessageType, type BaseSegment, type BlendMode, BorderRadiusConfig, type BubbleRadii, CaptionOverlay, CaptionOverlayProps, type Channel, type ColorFilterConfig, type ColorShiftConfig, type CropConfig, type CuttingConfig, DEDUPLICATION_LEVELS, type DeduplicationConfig, type DeduplicationInput, type DeduplicationLevel, type DiagonalFilterConfig, type DiagonalFilterType, DynamicCropConfig, type EditorConfig, type EditorSegment, type EnhanceLevel, type EnhancementConfig, FitMode, FontWeight, type FrameManipulationConfig, type GifOverlayConfig, type GifSource, type GradientColor, type GradientOverlayConfig, type IgDmMessage, type IgDmSender, type IgDmTheme, type IgTheme, ImageEditorComposition, type ImageEditorCompositionProps, type ImageEditorConfig, ImageEditorElement, ImageElement, type ImageElementProps, type ImageMessage, type ImageSegment, type ImageSequenceSegment, InstagramDmComposition, type InstagramDmCompositionProps, type InstagramDmPublicInput, LEVEL_1_CONFIG, LEVEL_2_CONFIG, LEVEL_3_CONFIG, LEVEL_4_CONFIG, LEVEL_5_CONFIG, type LensCorrectionConfig, MediaBubble, type MediaBubbleProps, type Message, MessageBubble, type MessageBubbleProps, type MessageGroup, type MessageOrTyping, type MessagePosition, type MessageReaction, type MessageSender, type MobileEncodingConfig, type ParticleOverlayConfig, type PhoneConfig, type PhoneModel, type PhoneType, type PictureSegment, PositionResolutionResult, type PositionedMessage, ProfilePic, type ProfilePicProps, Reaction, type ReactionProps, type ReadReceipt, type ReadReceiptState, RelativePositionConfigX, RelativePositionConfigY, RenderRoot, ScreenshotAnimation, ScreenshotAnimationProps, type Segment, SegmentType, type SpeedConfig, type StaticSegment, TYPING_ANIMATION, TextElement, type TextElementProps, type TextMessage, type TextSegment, TextStyleProperties, TimeValue, type TraceRemovalConfig, TypingIndicator, type TypingIndicatorProps, type TypingIndicatorStyle, type TypingMessage, type UserProfile, type ValidationError, type VideoCodec, VideoEditorComposition, type VideoEditorCompositionProps, type VideoEditorConfig, VideoElement, type VideoElementProps, type VideoExtension, type VideoSegment, type VideoSequenceSegment, type VisualAdjustmentsConfig, type VisualSegment, type VisualSegmentUnion, bubbleRadiiToCss, calculateBubbleRadii, convertPublicToProps, defaultInstagramDmProps, flattenGroups, groupMessages, isDeduplicationLevel, resolveDeduplicationConfig, useFontsLoaded, useImageLoader, useImagePreloader, useResolvedPositions, validatePublicInput };
package/dist/index.js CHANGED
@@ -79,6 +79,7 @@ __export(index_exports, {
79
79
  calculateScreenshotAnimationDuration: () => calculateScreenshotAnimationDuration,
80
80
  calculateTimelineContentEnd: () => calculateTimelineContentEnd,
81
81
  canSetAsReference: () => canSetAsReference,
82
+ convertPublicToProps: () => convertPublicToProps,
82
83
  debugFontStatus: () => debugFontStatus,
83
84
  defaultInstagramDmProps: () => defaultInstagramDmProps,
84
85
  defaultOffset: () => defaultOffset,
@@ -112,6 +113,7 @@ __export(index_exports, {
112
113
  useImageLoader: () => useImageLoader,
113
114
  useImagePreloader: () => useImagePreloader,
114
115
  useResolvedPositions: () => useResolvedPositions,
116
+ validatePublicInput: () => validatePublicInput,
115
117
  wrapText: () => wrapText
116
118
  });
117
119
  module.exports = __toCommonJS(index_exports);
@@ -4915,6 +4917,100 @@ function InstagramDmComposition(props) {
4915
4917
  );
4916
4918
  }
4917
4919
 
4920
+ // src/compositions/InstagramDmComposition/convertPublicToProps.ts
4921
+ function validatePublicInput(input) {
4922
+ const errors = [];
4923
+ if (!input.receiverUsername?.trim()) {
4924
+ errors.push({
4925
+ field: "receiverUsername",
4926
+ message: "Receiver username is required"
4927
+ });
4928
+ }
4929
+ if (!input.receiverProfilePicUrl?.trim()) {
4930
+ errors.push({
4931
+ field: "receiverProfilePicUrl",
4932
+ message: "Receiver profile picture URL is required"
4933
+ });
4934
+ }
4935
+ if (!input.theme || !["light", "dark"].includes(input.theme)) {
4936
+ errors.push({
4937
+ field: "theme",
4938
+ message: "Theme must be 'light' or 'dark'"
4939
+ });
4940
+ }
4941
+ if (!input.messages || input.messages.length === 0) {
4942
+ errors.push({
4943
+ field: "messages",
4944
+ message: "At least one message is required"
4945
+ });
4946
+ } else {
4947
+ input.messages.forEach((msg, index) => {
4948
+ if (!msg.text?.trim()) {
4949
+ errors.push({
4950
+ field: `messages[${index}].text`,
4951
+ message: `Message ${index + 1}: text is required`
4952
+ });
4953
+ }
4954
+ if (!msg.sender || !["user", "recipient"].includes(msg.sender)) {
4955
+ errors.push({
4956
+ field: `messages[${index}].sender`,
4957
+ message: `Message ${index + 1}: sender must be 'user' or 'recipient'`
4958
+ });
4959
+ }
4960
+ if (msg.isStoryReply && msg.sender !== "user") {
4961
+ errors.push({
4962
+ field: `messages[${index}].isStoryReply`,
4963
+ message: `Message ${index + 1}: story replies are only allowed for sender='user'`
4964
+ });
4965
+ }
4966
+ });
4967
+ const hasStoryReply = input.messages.some((m) => m.isStoryReply && m.sender === "user");
4968
+ if (hasStoryReply && !input.storyImageUrl?.trim()) {
4969
+ errors.push({
4970
+ field: "storyImageUrl",
4971
+ message: "Story image URL is required when any message has isStoryReply=true"
4972
+ });
4973
+ }
4974
+ }
4975
+ return errors;
4976
+ }
4977
+ function convertMessages(messages, storyImageUrl) {
4978
+ return messages.map((msg, index) => {
4979
+ const igMessage = {
4980
+ id: `msg-${index}`,
4981
+ sender: msg.sender,
4982
+ text: msg.text
4983
+ };
4984
+ if (msg.groupWithPrevious) {
4985
+ igMessage.groupWithPrevious = true;
4986
+ }
4987
+ if (msg.isStoryReply && msg.sender === "user" && storyImageUrl) {
4988
+ igMessage.storyReplyImageUrl = storyImageUrl;
4989
+ }
4990
+ return igMessage;
4991
+ });
4992
+ }
4993
+ function convertPublicToProps(input) {
4994
+ const errors = validatePublicInput(input);
4995
+ if (errors.length > 0) {
4996
+ throw new Error(`Invalid input: ${errors.map((e) => e.message).join(", ")}`);
4997
+ }
4998
+ const props = {
4999
+ ...defaultInstagramDmProps,
5000
+ // Override with user input
5001
+ theme: input.theme,
5002
+ senderUsername: input.receiverUsername,
5003
+ profilePicUrl: input.receiverProfilePicUrl,
5004
+ userPfpUrl: input.receiverProfilePicUrl,
5005
+ // Convert messages
5006
+ messages: convertMessages(input.messages, input.storyImageUrl),
5007
+ // Disable debug/reference overlays for production renders
5008
+ showDebugOverlay: false,
5009
+ showReferenceImage: false
5010
+ };
5011
+ return props;
5012
+ }
5013
+
4918
5014
  // src/compositions/messaging/types.ts
4919
5015
  var TYPING_ANIMATION = {
4920
5016
  /** Frames for one complete bounce cycle at 30fps */
@@ -6232,6 +6328,7 @@ var RenderRoot = () => {
6232
6328
  calculateScreenshotAnimationDuration,
6233
6329
  calculateTimelineContentEnd,
6234
6330
  canSetAsReference,
6331
+ convertPublicToProps,
6235
6332
  debugFontStatus,
6236
6333
  defaultInstagramDmProps,
6237
6334
  defaultOffset,
@@ -6265,5 +6362,6 @@ var RenderRoot = () => {
6265
6362
  useImageLoader,
6266
6363
  useImagePreloader,
6267
6364
  useResolvedPositions,
6365
+ validatePublicInput,
6268
6366
  wrapText
6269
6367
  });
package/dist/index.mjs CHANGED
@@ -3984,6 +3984,100 @@ function InstagramDmComposition(props) {
3984
3984
  );
3985
3985
  }
3986
3986
 
3987
+ // src/compositions/InstagramDmComposition/convertPublicToProps.ts
3988
+ function validatePublicInput(input) {
3989
+ const errors = [];
3990
+ if (!input.receiverUsername?.trim()) {
3991
+ errors.push({
3992
+ field: "receiverUsername",
3993
+ message: "Receiver username is required"
3994
+ });
3995
+ }
3996
+ if (!input.receiverProfilePicUrl?.trim()) {
3997
+ errors.push({
3998
+ field: "receiverProfilePicUrl",
3999
+ message: "Receiver profile picture URL is required"
4000
+ });
4001
+ }
4002
+ if (!input.theme || !["light", "dark"].includes(input.theme)) {
4003
+ errors.push({
4004
+ field: "theme",
4005
+ message: "Theme must be 'light' or 'dark'"
4006
+ });
4007
+ }
4008
+ if (!input.messages || input.messages.length === 0) {
4009
+ errors.push({
4010
+ field: "messages",
4011
+ message: "At least one message is required"
4012
+ });
4013
+ } else {
4014
+ input.messages.forEach((msg, index) => {
4015
+ if (!msg.text?.trim()) {
4016
+ errors.push({
4017
+ field: `messages[${index}].text`,
4018
+ message: `Message ${index + 1}: text is required`
4019
+ });
4020
+ }
4021
+ if (!msg.sender || !["user", "recipient"].includes(msg.sender)) {
4022
+ errors.push({
4023
+ field: `messages[${index}].sender`,
4024
+ message: `Message ${index + 1}: sender must be 'user' or 'recipient'`
4025
+ });
4026
+ }
4027
+ if (msg.isStoryReply && msg.sender !== "user") {
4028
+ errors.push({
4029
+ field: `messages[${index}].isStoryReply`,
4030
+ message: `Message ${index + 1}: story replies are only allowed for sender='user'`
4031
+ });
4032
+ }
4033
+ });
4034
+ const hasStoryReply = input.messages.some((m) => m.isStoryReply && m.sender === "user");
4035
+ if (hasStoryReply && !input.storyImageUrl?.trim()) {
4036
+ errors.push({
4037
+ field: "storyImageUrl",
4038
+ message: "Story image URL is required when any message has isStoryReply=true"
4039
+ });
4040
+ }
4041
+ }
4042
+ return errors;
4043
+ }
4044
+ function convertMessages(messages, storyImageUrl) {
4045
+ return messages.map((msg, index) => {
4046
+ const igMessage = {
4047
+ id: `msg-${index}`,
4048
+ sender: msg.sender,
4049
+ text: msg.text
4050
+ };
4051
+ if (msg.groupWithPrevious) {
4052
+ igMessage.groupWithPrevious = true;
4053
+ }
4054
+ if (msg.isStoryReply && msg.sender === "user" && storyImageUrl) {
4055
+ igMessage.storyReplyImageUrl = storyImageUrl;
4056
+ }
4057
+ return igMessage;
4058
+ });
4059
+ }
4060
+ function convertPublicToProps(input) {
4061
+ const errors = validatePublicInput(input);
4062
+ if (errors.length > 0) {
4063
+ throw new Error(`Invalid input: ${errors.map((e) => e.message).join(", ")}`);
4064
+ }
4065
+ const props = {
4066
+ ...defaultInstagramDmProps,
4067
+ // Override with user input
4068
+ theme: input.theme,
4069
+ senderUsername: input.receiverUsername,
4070
+ profilePicUrl: input.receiverProfilePicUrl,
4071
+ userPfpUrl: input.receiverProfilePicUrl,
4072
+ // Convert messages
4073
+ messages: convertMessages(input.messages, input.storyImageUrl),
4074
+ // Disable debug/reference overlays for production renders
4075
+ showDebugOverlay: false,
4076
+ showReferenceImage: false
4077
+ };
4078
+ return props;
4079
+ }
4080
+
3987
4081
  // src/compositions/messaging/types.ts
3988
4082
  var TYPING_ANIMATION = {
3989
4083
  /** Frames for one complete bounce cycle at 30fps */
@@ -5017,6 +5111,7 @@ export {
5017
5111
  calculateScreenshotAnimationDuration,
5018
5112
  calculateTimelineContentEnd,
5019
5113
  canSetAsReference,
5114
+ convertPublicToProps,
5020
5115
  debugFontStatus,
5021
5116
  defaultInstagramDmProps,
5022
5117
  defaultOffset,
@@ -5050,5 +5145,6 @@ export {
5050
5145
  useImageLoader,
5051
5146
  useImagePreloader,
5052
5147
  useResolvedPositions,
5148
+ validatePublicInput,
5053
5149
  wrapText
5054
5150
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ugcinc-render",
3
- "version": "1.8.140",
3
+ "version": "1.8.141",
4
4
  "description": "Unified rendering package for UGC Inc - shared types, components, and compositions for pixel-perfect client/server rendering",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",