ugcinc 4.27.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,504 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.IMessageDmComposition = exports.defaultIMessageDmProps = exports.convertPropsToElements = void 0;
4
- const jsx_runtime_1 = require("react/jsx-runtime");
5
- /**
6
- * iMessage DM Composition
7
- *
8
- * A fully parameterized iMessage DM conversation renderer.
9
- * Uses BaseDmComposition for shared iOS chrome (status bar, home indicator)
10
- * and zoom/pan/crosshair functionality.
11
- */
12
- const react_1 = require("react");
13
- const remotion_1 = require("remotion");
14
- const ImageEditorComposition_1 = require("../ImageEditorComposition");
15
- const DmComposition_1 = require("../DmComposition");
16
- const convertPropsToElements_1 = require("./convertPropsToElements");
17
- const fonts_1 = require("../../utils/fonts");
18
- const positionResolver_1 = require("../../utils/positionResolver");
19
- const cropBounds_1 = require("../../utils/cropBounds");
20
- // Re-export for crop bounds calculation (convert props to elements for position resolution)
21
- var convertPropsToElements_2 = require("./convertPropsToElements");
22
- Object.defineProperty(exports, "convertPropsToElements", { enumerable: true, get: function () { return convertPropsToElements_2.convertPropsToElements; } });
23
- /**
24
- * Default composition props for registration
25
- */
26
- exports.defaultIMessageDmProps = {
27
- showDebugOverlay: false,
28
- referenceImageUrl: 'https://media.ugc.inc/media/06c3ed1c-eefb-4a60-b0c4-5fb872811ba0/IMG_3189-hUoucNOmBoT8fihIL7ybuEXwoRrngz.png',
29
- showReferenceImage: false,
30
- referenceOpacity: 50,
31
- lightMode: false,
32
- width: 1206,
33
- height: 2622,
34
- durationInFrames: 90,
35
- fps: 30,
36
- // Header defaults
37
- headerTop: 0,
38
- headerBottom: 424,
39
- headerBackgroundColor: '#171717',
40
- // Profile section defaults
41
- profilePicUrl: 'https://media.ugc.inc/media/06c3ed1c-eefb-4a60-b0c4-5fb872811ba0/pinterest-1766175215011-3-ftQGbunlgHOFdfFtr1PdxxmHD9TAf9.jpg',
42
- profilePicTop: 195,
43
- profilePicBottom: 347,
44
- profilePicLeft: 528,
45
- profilePicRight: 680,
46
- username: 'aidan gollan',
47
- usernameTop: 355,
48
- usernameBottom: 404,
49
- usernameLeft: 452,
50
- usernameRight: 752,
51
- usernameFontSize: 36,
52
- usernameLetterSpacing: 0.8,
53
- usernameColor: '#ffffff',
54
- usernameArrowOffsetX: 8,
55
- usernameArrowOffsetY: 2,
56
- usernameArrowWidth: 14,
57
- usernameArrowHeight: 24,
58
- // Back arrow defaults
59
- backArrowTop: 234,
60
- backArrowBottom: 297,
61
- backArrowLeft: 50,
62
- backArrowRight: 87,
63
- // Unread badge defaults
64
- unreadBadgeText: '579',
65
- unreadBadgeTop: 238,
66
- unreadBadgeBottom: 293,
67
- unreadBadgeLeft: 108,
68
- unreadBadgeFontSize: 36,
69
- unreadBadgeLetterSpacing: 0.2,
70
- unreadBadgeTextColor: '#ffffff',
71
- unreadBadgeBorderRadius: 9999,
72
- unreadBadgePaddingLeft: 17,
73
- unreadBadgePaddingRight: 17,
74
- // Camera icon defaults
75
- cameraIconTop: 237,
76
- cameraIconBottom: 292,
77
- cameraIconLeft: 1053,
78
- cameraIconRight: 1134,
79
- // Divider line defaults
80
- dividerLineY: 425,
81
- dividerLineColor: '#262626',
82
- // Background
83
- backgroundColor: '#000000',
84
- // Plus button defaults
85
- plusButtonTop: 2390,
86
- plusButtonBottom: 2491,
87
- plusButtonLeft: 42,
88
- plusButtonRight: 143,
89
- // Footer defaults
90
- footerTop: 2385,
91
- footerBottom: 2495,
92
- footerLeft: 180,
93
- footerRight: 1157,
94
- footerBgColor: '#1c1c1e',
95
- footerBorderRadius: 55,
96
- footerBorderColor: '#3a3a3c',
97
- footerBorderWidth: 2,
98
- // Message text defaults
99
- messageTextTop: 2412,
100
- messageTextBottom: 2468,
101
- messageTextLeft: 220,
102
- messageTextRight: 600,
103
- messageTextFontSize: 48,
104
- messageTextLetterSpacing: 0,
105
- messageTextColor: '#8e8e93',
106
- messageText: 'iMessage',
107
- // Status bar props (passed to BaseDmComposition - same as IG DM)
108
- time: '9:41',
109
- timeRight: 262,
110
- timeBottom: 125,
111
- timeFontSize: 52,
112
- timeLetterSpacing: 1.6,
113
- noNotisTop: 77,
114
- noNotisBottom: 120,
115
- noNotisLeft: 272,
116
- noNotisRight: 312,
117
- cellLevel: 4,
118
- cell1Top: 102,
119
- cell1Bottom: 116,
120
- cell1Left: 865,
121
- cell1Right: 875,
122
- cell2Top: 95,
123
- cell2Bottom: 116,
124
- cell2Left: 881,
125
- cell2Right: 891,
126
- cell3Top: 87,
127
- cell3Bottom: 116,
128
- cell3Left: 897,
129
- cell3Right: 907,
130
- cell4Top: 79,
131
- cell4Bottom: 116,
132
- cell4Left: 913,
133
- cell4Right: 923,
134
- wifiTop: 79,
135
- wifiBottom: 116,
136
- wifiLeft: 945,
137
- wifiRight: 996,
138
- batteryTop: 78,
139
- batteryBottom: 117,
140
- batteryLeft: 1018,
141
- batteryRight: 1100,
142
- // Home indicator defaults (passed to BaseDmComposition)
143
- homeIndicatorTop: 2583,
144
- homeIndicatorBottom: 2597,
145
- homeIndicatorLeft: 387,
146
- homeIndicatorRight: 818,
147
- homeIndicatorColor: '#ffffff',
148
- // Message area bounds
149
- messageAreaTop: 450,
150
- messageAreaBottom: 2310,
151
- // Message colors
152
- senderBubbleColor: '#1a42d5',
153
- recipientBubbleColor: '#303032',
154
- bubbleTextColor: '#ffffff',
155
- recipientTextColor: '#ffffff',
156
- // Message typography
157
- messageFontSize: 53,
158
- messageLineHeight: 60,
159
- messageLetterSpacing: 1.2,
160
- // Message padding (inside bubble)
161
- messagePaddingTop: 23,
162
- messagePaddingBottom: 22,
163
- senderPaddingLeft: 34,
164
- senderPaddingRight: 48,
165
- multiLineSenderPaddingLeft: 34,
166
- recipientPaddingLeft: 37,
167
- recipientPaddingRight: 36,
168
- multiLineRecipientPaddingRight: 48,
169
- // Bubble corner radii
170
- bubbleRadiusNormal: 51,
171
- bubbleRadiusGrouped: 51,
172
- // Message spacing
173
- messageGapInGroup: 3,
174
- messageGapSameUser: 8,
175
- messageGapDifferentUser: 70,
176
- // Bubble positioning
177
- recipientBubbleLeft: 48,
178
- senderBubbleRight: 1158,
179
- bubbleMaxWidth: 900,
180
- // Sender image attachment
181
- senderImageLeft: 336,
182
- senderImageHeight: 1120,
183
- senderImageGapToText: 3,
184
- senderImageBorderRadius: 51,
185
- // Message area header text (above first message)
186
- messageHeaderImessageText: 'iMessage',
187
- messageHeaderTimestampText: 'Today 12:16 PM',
188
- messageHeaderTimestampGap: 30,
189
- messageHeaderImessageGap: 5,
190
- messageHeaderTextColor: '#626167',
191
- messageHeaderFontSize: 34,
192
- messageHeaderLetterSpacing: 1.25,
193
- messageHeaderLeft: 0,
194
- messageHeaderRight: 1206,
195
- // Message tails (SVG-based, on last message in group)
196
- showMessageTails: true,
197
- // Recipient tail anchor points (offsets from message left & bottom)
198
- recipientTailSideY: -53, // Y where tail meets bubble (top of straight line)
199
- recipientTailCurveStartY: -28, // Y where straight line ends and top curve begins
200
- recipientTailTipX: -16,
201
- recipientTailTipY: -1,
202
- recipientTailBottomX: 19, // X where bottom curve ends (connects to bubble)
203
- recipientTailBottomY: -12, // Y where bottom curve ends (connects to bubble)
204
- // Recipient tail curve bend (-1 to 1, negative = inward, positive = outward)
205
- recipientTailTopBend: -0.32, // Top curve bends inward
206
- recipientTailBottomBend: 0.3, // Bottom curve bends outward
207
- // Sender tail anchor points (offsets from message right & bottom)
208
- senderTailSideY: -53, // Y where tail meets bubble (top of straight line)
209
- senderTailCurveStartY: -28, // Y where straight line ends and top curve begins
210
- senderTailTipX: 16,
211
- senderTailTipY: -1,
212
- senderTailBottomX: -19, // X where bottom curve ends (connects to bubble)
213
- senderTailBottomY: -12, // Y where bottom curve ends (connects to bubble)
214
- // Sender tail curve bend (-1 to 1, negative = inward, positive = outward)
215
- senderTailTopBend: -0.32, // Top curve bends inward
216
- senderTailBottomBend: 0.3, // Bottom curve bends outward
217
- // Read receipt (under last sender message)
218
- showReadReceipt: true,
219
- readReceiptText: 'Read 12:16 PM',
220
- readReceiptGap: 52,
221
- readReceiptFontSize: 35,
222
- readReceiptLetterSpacing: 0.9,
223
- readReceiptColor: '#626167',
224
- readReceiptLeft: 0,
225
- readReceiptRight: 1158,
226
- // Example messages
227
- messages: [
228
- { id: 'msg-1', sender: 'user', text: 'heyyy fae, help me slide on this baddie pls 🙏', imageUrl: 'https://media.ugc.inc/media/06c3ed1c-eefb-4a60-b0c4-5fb872811ba0/pinterest-1766175214139-0-JpXmGIxVWdjEJ3qxGyoC4DAi2KAZrg.jpg' },
229
- { id: 'msg-2', sender: 'recipient', text: 'don\'t worry king, i gotchu' },
230
- { id: 'msg-3', sender: 'recipient', text: 'that is indeed a cute kitty', groupWithPrevious: true },
231
- { id: 'msg-4', sender: 'recipient', text: 'try this line out for speed: are you a kitty? because you deserve pets', groupWithPrevious: true },
232
- ],
233
- };
234
- /**
235
- * iMessage DM Composition Component
236
- */
237
- const IMessageDmComposition = (props) => {
238
- const [fontsLoaded, setFontsLoaded] = (0, react_1.useState)(false);
239
- // Load fonts before text measurement - required for accurate line breaks
240
- (0, react_1.useEffect)(() => {
241
- const handle = (0, remotion_1.delayRender)('Loading fonts for IMessageDmComposition');
242
- const loadFonts = async () => {
243
- await (0, fonts_1.preloadFonts)();
244
- // Wait for document.fonts.ready to ensure fonts are fully available for DOM measurement
245
- if (typeof document !== 'undefined' && document.fonts?.ready) {
246
- await document.fonts.ready;
247
- }
248
- // Give the browser an extra frame to actually apply the fonts for measurement
249
- // This is necessary because fonts.ready resolves before fonts are visually applied
250
- await new Promise((resolve) => {
251
- if (typeof requestAnimationFrame !== 'undefined') {
252
- requestAnimationFrame(() => {
253
- requestAnimationFrame(() => {
254
- resolve();
255
- });
256
- });
257
- }
258
- else {
259
- resolve();
260
- }
261
- });
262
- };
263
- loadFonts()
264
- .then(() => {
265
- setFontsLoaded(true);
266
- (0, remotion_1.continueRender)(handle);
267
- })
268
- .catch((err) => {
269
- console.error('[IMessageDmComposition] Failed to load fonts:', err);
270
- // Continue anyway to avoid hanging
271
- setFontsLoaded(true);
272
- (0, remotion_1.continueRender)(handle);
273
- });
274
- }, []);
275
- // Merge props with defaults
276
- const mergedProps = (0, react_1.useMemo)(() => ({
277
- ...exports.defaultIMessageDmProps,
278
- ...props,
279
- }), [props]);
280
- // Convert props to elements (for messages only) - only after fonts are loaded
281
- const conversionResult = (0, react_1.useMemo)(() => {
282
- // Return empty elements until fonts are loaded to avoid incorrect text measurement
283
- if (!fontsLoaded) {
284
- return { elements: [], imageUrls: {}, tails: [], width: mergedProps.width ?? 1206, height: mergedProps.height ?? 2622 };
285
- }
286
- // Apply light mode colors for message bubbles
287
- const propsWithEffectiveColors = {
288
- ...mergedProps,
289
- recipientBubbleColor: mergedProps.lightMode ? '#dfdfe1' : (mergedProps.recipientBubbleColor ?? '#303032'),
290
- recipientTextColor: mergedProps.lightMode ? '#000000' : (mergedProps.recipientTextColor ?? '#ffffff'),
291
- };
292
- return (0, convertPropsToElements_1.convertPropsToElements)(propsWithEffectiveColors);
293
- }, [mergedProps, fontsLoaded]);
294
- // Resolve element positions and compute crop bounds when dynamic crop enabled
295
- const cropBounds = (0, react_1.useMemo)(() => {
296
- const elements = conversionResult.elements;
297
- if (!elements.length || !(0, cropBounds_1.isDynamicCropEnabled)(mergedProps.dynamicCrop)) {
298
- return undefined;
299
- }
300
- const result = (0, positionResolver_1.resolveElementPositions)(elements, {});
301
- const resolved = result.elements;
302
- if (!resolved)
303
- return undefined;
304
- const w = mergedProps.width ?? 1206;
305
- const h = mergedProps.height ?? 2622;
306
- return (0, cropBounds_1.calculateCropBounds)(resolved, mergedProps.dynamicCrop, w, h);
307
- }, [conversionResult.elements, mergedProps.dynamicCrop, mergedProps.width, mergedProps.height]);
308
- // Extract values with defaults
309
- const { width = 1206, height = 2622, backgroundColor = '#000000', headerBackgroundColor = '#171717', headerBottom = 424, lightMode = false,
310
- // Profile section
311
- profilePicUrl, profilePicTop = 195, profilePicBottom = 347, profilePicLeft = 528, profilePicRight = 680, username = 'aidan gollan', usernameTop = 355, usernameBottom = 404, usernameLeft = 429, usernameRight = 752, usernameFontSize = 36, usernameLetterSpacing = 0.8, usernameColor = '#ffffff', usernameArrowOffsetX = -57, usernameArrowOffsetY = 2, usernameArrowWidth = 14, usernameArrowHeight = 24,
312
- // Back arrow
313
- backArrowTop = 234, backArrowBottom = 297, backArrowLeft = 50, backArrowRight = 87,
314
- // Unread badge
315
- unreadBadgeText = '579', unreadBadgeTop = 238, unreadBadgeBottom = 293, unreadBadgeLeft = 108, unreadBadgeFontSize = 36, unreadBadgeLetterSpacing = 0.2, unreadBadgeTextColor = '#ffffff', unreadBadgeBorderRadius = 9999, unreadBadgePaddingLeft = 17, unreadBadgePaddingRight = 17,
316
- // Camera icon
317
- cameraIconTop = 237, cameraIconBottom = 292, cameraIconLeft = 1053, cameraIconRight = 1134, dividerLineY = 425, dividerLineColor = '#262626', showDebugOverlay = false, referenceImageUrl, showReferenceImage = false, referenceOpacity = 50,
318
- // Status bar props (passed to BaseDmComposition)
319
- time = '9:41', timeRight = 262, timeBottom = 125, timeFontSize = 52, timeLetterSpacing = 1.6, noNotisTop = 77, noNotisBottom = 120, noNotisLeft = 272, noNotisRight = 312, cellLevel = 4, cell1Top = 102, cell1Bottom = 116, cell1Left = 865, cell1Right = 875, cell2Top = 95, cell2Bottom = 116, cell2Left = 881, cell2Right = 891, cell3Top = 87, cell3Bottom = 116, cell3Left = 897, cell3Right = 907, cell4Top = 79, cell4Bottom = 116, cell4Left = 913, cell4Right = 923, wifiTop = 79, wifiBottom = 116, wifiLeft = 945, wifiRight = 996, batteryTop = 78, batteryBottom = 117, batteryLeft = 1018, batteryRight = 1100,
320
- // Home indicator props (passed to BaseDmComposition)
321
- homeIndicatorTop = 2583, homeIndicatorBottom = 2597, homeIndicatorLeft = 387, homeIndicatorRight = 818, homeIndicatorColor = '#ffffff',
322
- // Plus button
323
- plusButtonTop = 2390, plusButtonBottom = 2491, plusButtonLeft = 42, plusButtonRight = 143,
324
- // Footer
325
- footerTop = 2385, footerBottom = 2495, footerLeft = 180, footerRight = 1157, footerBgColor = '#1c1c1e', footerBorderRadius = 55, footerBorderColor = '#3a3a3c', footerBorderWidth = 2,
326
- // Bubble colors
327
- senderBubbleColor = '#1a42d5', recipientBubbleColor = '#303032',
328
- // Tail props - recipient (offsets from message left & bottom)
329
- recipientTailSideY = -53, recipientTailCurveStartY = -28, recipientTailTipX = -16, recipientTailTipY = -1, recipientTailBottomX = 19, recipientTailBottomY = -12, recipientTailTopBend = -0.32, recipientTailBottomBend = 0.3,
330
- // Tail props - sender (offsets from message right & bottom)
331
- senderTailSideY = -53, senderTailCurveStartY = -28, senderTailTipX = 16, senderTailTipY = -1, senderTailBottomX = -19, senderTailBottomY = -12, senderTailTopBend = -0.32, senderTailBottomBend = 0.3, } = mergedProps;
332
- // Compute effective colors based on light mode
333
- const effectiveBackgroundColor = lightMode ? '#ffffff' : backgroundColor;
334
- const effectiveHeaderBgColor = lightMode ? '#f7f7f7' : headerBackgroundColor;
335
- const effectiveRecipientBubbleColor = lightMode ? '#dfdfe1' : recipientBubbleColor;
336
- const effectiveRecipientTextColor = lightMode ? '#000000' : '#ffffff';
337
- const effectiveUsernameColor = lightMode ? '#000000' : usernameColor;
338
- const effectiveHomeIndicatorColor = lightMode ? '#000000' : homeIndicatorColor;
339
- const effectiveStatusBarColor = lightMode ? '#000000' : '#ffffff';
340
- return ((0, jsx_runtime_1.jsxs)(DmComposition_1.BaseDmComposition, { width: width, height: height, cropBounds: cropBounds, backgroundColor: effectiveBackgroundColor, showDebugOverlay: showDebugOverlay, referenceImageUrl: referenceImageUrl, showReferenceImage: showReferenceImage, referenceOpacity: referenceOpacity, currentProps: { ...mergedProps },
341
- // Status bar props
342
- time: time, timeRight: timeRight, timeBottom: timeBottom, timeFontSize: timeFontSize, timeLetterSpacing: timeLetterSpacing, noNotisTop: noNotisTop, noNotisBottom: noNotisBottom, noNotisLeft: noNotisLeft, noNotisRight: noNotisRight, cellLevel: cellLevel, cell1Top: cell1Top, cell1Bottom: cell1Bottom, cell1Left: cell1Left, cell1Right: cell1Right, cell2Top: cell2Top, cell2Bottom: cell2Bottom, cell2Left: cell2Left, cell2Right: cell2Right, cell3Top: cell3Top, cell3Bottom: cell3Bottom, cell3Left: cell3Left, cell3Right: cell3Right, cell4Top: cell4Top, cell4Bottom: cell4Bottom, cell4Left: cell4Left, cell4Right: cell4Right, wifiTop: wifiTop, wifiBottom: wifiBottom, wifiLeft: wifiLeft, wifiRight: wifiRight, batteryTop: batteryTop, batteryBottom: batteryBottom, batteryLeft: batteryLeft, batteryRight: batteryRight,
343
- // Home indicator props
344
- homeIndicatorTop: homeIndicatorTop, homeIndicatorBottom: homeIndicatorBottom, homeIndicatorLeft: homeIndicatorLeft, homeIndicatorRight: homeIndicatorRight, homeIndicatorColor: effectiveHomeIndicatorColor,
345
- // Status bar color for light mode
346
- statusBarColor: effectiveStatusBarColor, children: [(0, jsx_runtime_1.jsx)("div", { style: {
347
- position: 'absolute',
348
- top: 0,
349
- left: 0,
350
- width,
351
- height,
352
- backgroundColor: effectiveBackgroundColor,
353
- zIndex: 0,
354
- } }), (0, jsx_runtime_1.jsx)("div", { style: {
355
- position: 'absolute',
356
- top: 0,
357
- left: 0,
358
- width,
359
- height: headerBottom,
360
- backgroundColor: effectiveHeaderBgColor,
361
- zIndex: 25,
362
- } }), (0, jsx_runtime_1.jsx)(remotion_1.Img, { src: (0, remotion_1.staticFile)(lightMode ? 'imsg-light-header-left-arrow.png' : 'imsg-header-left-arrow.png'), style: {
363
- position: 'absolute',
364
- top: backArrowTop,
365
- left: backArrowLeft,
366
- width: backArrowRight - backArrowLeft,
367
- height: backArrowBottom - backArrowTop,
368
- zIndex: 26,
369
- } }), (0, jsx_runtime_1.jsx)("div", { style: {
370
- position: 'absolute',
371
- top: unreadBadgeTop,
372
- left: unreadBadgeLeft,
373
- height: unreadBadgeBottom - unreadBadgeTop,
374
- display: 'flex',
375
- alignItems: 'center',
376
- justifyContent: 'center',
377
- backgroundColor: senderBubbleColor,
378
- borderRadius: unreadBadgeBorderRadius,
379
- paddingLeft: unreadBadgePaddingLeft,
380
- paddingRight: unreadBadgePaddingRight,
381
- zIndex: 26,
382
- }, children: (0, jsx_runtime_1.jsx)("span", { style: {
383
- fontFamily: '"SF Pro Display", "Apple Color Emoji", sans-serif',
384
- fontWeight: 400,
385
- fontSize: unreadBadgeFontSize,
386
- letterSpacing: unreadBadgeLetterSpacing,
387
- color: unreadBadgeTextColor,
388
- whiteSpace: 'nowrap',
389
- }, children: unreadBadgeText }) }), (0, jsx_runtime_1.jsx)(remotion_1.Img, { src: (0, remotion_1.staticFile)(lightMode ? 'imsg-light-header-camera.png' : 'imsg-header-camera.png'), style: {
390
- position: 'absolute',
391
- top: cameraIconTop,
392
- left: cameraIconLeft,
393
- width: cameraIconRight - cameraIconLeft,
394
- height: cameraIconBottom - cameraIconTop,
395
- zIndex: 26,
396
- } }), (0, jsx_runtime_1.jsx)("div", { style: {
397
- position: 'absolute',
398
- top: dividerLineY,
399
- left: 0,
400
- width,
401
- height: 1,
402
- backgroundColor: dividerLineColor,
403
- zIndex: 25,
404
- } }), profilePicUrl && ((0, jsx_runtime_1.jsx)(remotion_1.Img, { src: profilePicUrl, style: {
405
- position: 'absolute',
406
- top: profilePicTop,
407
- left: profilePicLeft,
408
- width: profilePicRight - profilePicLeft,
409
- height: profilePicBottom - profilePicTop,
410
- borderRadius: '50%',
411
- objectFit: 'cover',
412
- zIndex: 26,
413
- } })), username && ((0, jsx_runtime_1.jsxs)("div", { style: {
414
- position: 'absolute',
415
- top: usernameTop,
416
- left: usernameLeft,
417
- width: usernameRight - usernameLeft,
418
- height: usernameBottom - usernameTop,
419
- display: 'flex',
420
- alignItems: 'center',
421
- justifyContent: 'center',
422
- zIndex: 26,
423
- }, children: [(0, jsx_runtime_1.jsx)("span", { style: {
424
- fontFamily: '"SF Pro Display", "Apple Color Emoji", sans-serif',
425
- fontWeight: 400,
426
- fontSize: usernameFontSize,
427
- letterSpacing: usernameLetterSpacing,
428
- color: effectiveUsernameColor,
429
- whiteSpace: 'nowrap',
430
- }, children: username }), (0, jsx_runtime_1.jsx)(remotion_1.Img, { src: (0, remotion_1.staticFile)('imsg-name-right-arrow.png'), style: {
431
- marginLeft: usernameArrowOffsetX,
432
- marginTop: usernameArrowOffsetY,
433
- width: usernameArrowWidth,
434
- height: usernameArrowHeight,
435
- } })] })), (0, jsx_runtime_1.jsx)(remotion_1.Img, { src: (0, remotion_1.staticFile)(lightMode ? 'imsg-light-footer-plus.png' : 'imsg-footer-plus.png'), style: {
436
- position: 'absolute',
437
- top: plusButtonTop,
438
- left: plusButtonLeft,
439
- width: plusButtonRight - plusButtonLeft,
440
- height: plusButtonBottom - plusButtonTop,
441
- zIndex: 20,
442
- } }), (0, jsx_runtime_1.jsx)(remotion_1.Img, { src: (0, remotion_1.staticFile)(lightMode ? 'imsg-light-main-footer.png' : 'imsg-main-footer.png'), style: {
443
- position: 'absolute',
444
- top: footerTop,
445
- left: footerLeft,
446
- width: footerRight - footerLeft,
447
- height: footerBottom - footerTop,
448
- zIndex: 20,
449
- } }), conversionResult.tails.map((tail) => {
450
- // Reference point: bubble edge (left for recipient, right for sender) and bottom
451
- const refX = tail.isUser ? tail.messageRight : tail.messageLeft;
452
- const refY = tail.messageBottom;
453
- // Get the appropriate offsets
454
- const sideY = refY + (tail.isUser ? senderTailSideY : recipientTailSideY);
455
- const curveStartY = refY + (tail.isUser ? senderTailCurveStartY : recipientTailCurveStartY);
456
- const tipX = refX + (tail.isUser ? senderTailTipX : recipientTailTipX);
457
- const tipY = refY + (tail.isUser ? senderTailTipY : recipientTailTipY);
458
- const bottomX = refX + (tail.isUser ? senderTailBottomX : recipientTailBottomX);
459
- const bottomY = refY + (tail.isUser ? senderTailBottomY : recipientTailBottomY);
460
- const topBend = tail.isUser ? senderTailTopBend : recipientTailTopBend;
461
- const bottomBend = tail.isUser ? senderTailBottomBend : recipientTailBottomBend;
462
- // Side X is always at the bubble edge (refX)
463
- const sideX = refX;
464
- const curveStartX = refX;
465
- // Calculate control points based on bend values
466
- // For top curve: from curveStart to tip
467
- const topMidX = (curveStartX + tipX) / 2;
468
- const topMidY = (curveStartY + tipY) / 2;
469
- // Perpendicular direction (rotated 90 degrees)
470
- const topDx = tipX - curveStartX;
471
- const topDy = tipY - curveStartY;
472
- const topLen = Math.sqrt(topDx * topDx + topDy * topDy);
473
- // Perpendicular unit vector (for recipient: positive bend = outward/left, for sender: positive bend = outward/right)
474
- const topPerpX = tail.isUser ? (topDy / topLen) : (-topDy / topLen);
475
- const topPerpY = tail.isUser ? (-topDx / topLen) : (topDx / topLen);
476
- const topCurveX = topMidX + topPerpX * topBend * topLen;
477
- const topCurveY = topMidY + topPerpY * topBend * topLen;
478
- // For bottom curve: from tip to bottom
479
- const bottomMidX = (tipX + bottomX) / 2;
480
- const bottomMidY = (tipY + bottomY) / 2;
481
- const bottomDx = bottomX - tipX;
482
- const bottomDy = bottomY - tipY;
483
- const bottomLen = Math.sqrt(bottomDx * bottomDx + bottomDy * bottomDy);
484
- // Perpendicular unit vector
485
- const bottomPerpX = tail.isUser ? (bottomDy / bottomLen) : (-bottomDy / bottomLen);
486
- const bottomPerpY = tail.isUser ? (-bottomDx / bottomLen) : (bottomDx / bottomLen);
487
- const bottomCurveX = bottomMidX + bottomPerpX * bottomBend * bottomLen;
488
- const bottomCurveY = bottomMidY + bottomPerpY * bottomBend * bottomLen;
489
- const fillColor = tail.isUser ? senderBubbleColor : effectiveRecipientBubbleColor;
490
- // SVG path: Side -> straight down to curveStart -> curve to Tip -> curve to Bottom -> close
491
- const pathD = `M ${sideX} ${sideY} L ${curveStartX} ${curveStartY} Q ${topCurveX} ${topCurveY} ${tipX} ${tipY} Q ${bottomCurveX} ${bottomCurveY} ${bottomX} ${bottomY} Z`;
492
- return ((0, jsx_runtime_1.jsx)("svg", { style: {
493
- position: 'absolute',
494
- top: 0,
495
- left: 0,
496
- width,
497
- height,
498
- zIndex: 4,
499
- pointerEvents: 'none',
500
- }, children: (0, jsx_runtime_1.jsx)("path", { d: pathD, fill: fillColor }) }, tail.id));
501
- }), (0, jsx_runtime_1.jsx)(ImageEditorComposition_1.ImageEditorComposition, { width: width, height: height, elements: conversionResult.elements, imageUrls: conversionResult.imageUrls, backgroundType: "color", backgroundColor: "transparent" })] }));
502
- };
503
- exports.IMessageDmComposition = IMessageDmComposition;
504
- exports.default = exports.IMessageDmComposition;