ugcinc-render 1.5.11 → 1.5.12

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
@@ -1290,6 +1290,34 @@ declare function generateSegmentId(): string;
1290
1290
  */
1291
1291
  declare function generateOverlayId(): string;
1292
1292
 
1293
+ /**
1294
+ * Emoji utilities for rendering Apple-style emojis consistently
1295
+ * across all platforms using CDN-hosted emoji images.
1296
+ */
1297
+ /**
1298
+ * Convert an emoji character to its unified unicode codepoint format
1299
+ * Example: "😀" -> "1f600", "👨‍👩‍👧" -> "1f468-200d-1f469-200d-1f467"
1300
+ */
1301
+ declare function emojiToUnified(emoji: string): string;
1302
+ /**
1303
+ * Get the Apple emoji CDN URL for a given emoji character
1304
+ */
1305
+ declare function getAppleEmojiUrl(emoji: string): string;
1306
+ /**
1307
+ * Check if a string contains any emoji characters
1308
+ */
1309
+ declare function hasEmoji(text: string): boolean;
1310
+ /**
1311
+ * Split text into segments of text and emojis
1312
+ * Returns an array of segments with type 'text' or 'emoji'
1313
+ */
1314
+ interface TextSegmentPart {
1315
+ type: 'text' | 'emoji';
1316
+ content: string;
1317
+ imageUrl?: string;
1318
+ }
1319
+ declare function splitTextAndEmojis(text: string): TextSegmentPart[];
1320
+
1293
1321
  /**
1294
1322
  * Hook exports for ugcinc-render
1295
1323
  *
@@ -1349,4 +1377,4 @@ declare function useResolvedPositions(elements: ImageEditorElement[], textValues
1349
1377
 
1350
1378
  declare const RenderRoot: React.FC;
1351
1379
 
1352
- export { type AudioSegment, type BaseEditorConfig, type BaseSegment, type BorderRadiusConfig, type Channel, type CropAxisConfig, type CropBoundary, type CropBounds, DIMENSION_PRESETS, type DimensionPreset, type DimensionPresetKey, type DynamicCropConfig, type EditorConfig, type EditorSegment, FONT_FAMILIES, FONT_URLS, type FitDimensions, type FitMode, type FontType, type FontWeight, type HorizontalAnchor, type HorizontalSelfAnchor, type Hyphenation, IMAGE_DEFAULTS, ImageEditorComposition, type ImageEditorCompositionProps, type ImageEditorConfig, type ImageEditorElement, type ImageEditorNodeConfig, ImageElement, type ImageElementProps, type ImageSegment, type PictureSegment, type PositionResolutionError, type PositionResolutionResult, type RelativePositionConfigX, type RelativePositionConfigY, RenderRoot, type Segment, type SegmentTimelinePosition, type SegmentType, type StaticSegment, TEXT_DEFAULTS, type TextAlignment, type TextDirection, TextElement, type TextElementProps, type TextOverflow, type TextSegment, type TextWrap, type TimeMode, type TimeValue, VIDEO_DEFAULTS, VISUAL_DEFAULTS, type VerticalAlignment, type VerticalAnchor, type VerticalSelfAnchor, type VideoEditorAudioSegment, type VideoEditorBaseSegment, type VideoEditorChannel, VideoEditorComposition, type VideoEditorCompositionProps, type VideoEditorConfig, type VideoEditorImageSegment, type VideoEditorNodeConfig, type VideoEditorSegment, type VideoEditorTextSegment, type VideoEditorVideoSegment, type VideoEditorVisualSegment, VideoElement, type VideoElementProps, type VideoSegment, type VisualSegment, type VisualSegmentUnion, type WordBreak, applyImageDefaults, applyTextDefaults, applyVideoDefaults, areFontsLoaded, buildFontString, calculateAutoWidthDimensions, calculateCropBounds, calculateEstimatedDuration, calculateFitDimensions, calculateLineWidth, calculateTimelineContentEnd, canSetAsReference, defaultOffset, formatTime, generateOverlayId, generateSegmentId, getBaseSegments, getBorderRadii, getDependentElements, getFontFamily, getOverlays, getReferenceElementX, getReferenceElementY, getSegmentTimelinePosition, hexToRgba, isDynamicCropEnabled, isSegmentVisibleAtTime, parseHexColor, parseTime, preloadFonts, resolveElementPositions, useFontsLoaded, useImageLoader, useImagePreloader, useResolvedPositions, wrapText };
1380
+ export { type AudioSegment, type BaseEditorConfig, type BaseSegment, type BorderRadiusConfig, type Channel, type CropAxisConfig, type CropBoundary, type CropBounds, DIMENSION_PRESETS, type DimensionPreset, type DimensionPresetKey, type DynamicCropConfig, type EditorConfig, type EditorSegment, FONT_FAMILIES, FONT_URLS, type FitDimensions, type FitMode, type FontType, type FontWeight, type HorizontalAnchor, type HorizontalSelfAnchor, type Hyphenation, IMAGE_DEFAULTS, ImageEditorComposition, type ImageEditorCompositionProps, type ImageEditorConfig, type ImageEditorElement, type ImageEditorNodeConfig, ImageElement, type ImageElementProps, type ImageSegment, type PictureSegment, type PositionResolutionError, type PositionResolutionResult, type RelativePositionConfigX, type RelativePositionConfigY, RenderRoot, type Segment, type SegmentTimelinePosition, type SegmentType, type StaticSegment, TEXT_DEFAULTS, type TextAlignment, type TextDirection, TextElement, type TextElementProps, type TextOverflow, type TextSegment, type TextSegmentPart, type TextWrap, type TimeMode, type TimeValue, VIDEO_DEFAULTS, VISUAL_DEFAULTS, type VerticalAlignment, type VerticalAnchor, type VerticalSelfAnchor, type VideoEditorAudioSegment, type VideoEditorBaseSegment, type VideoEditorChannel, VideoEditorComposition, type VideoEditorCompositionProps, type VideoEditorConfig, type VideoEditorImageSegment, type VideoEditorNodeConfig, type VideoEditorSegment, type VideoEditorTextSegment, type VideoEditorVideoSegment, type VideoEditorVisualSegment, VideoElement, type VideoElementProps, type VideoSegment, type VisualSegment, type VisualSegmentUnion, type WordBreak, applyImageDefaults, applyTextDefaults, applyVideoDefaults, areFontsLoaded, buildFontString, calculateAutoWidthDimensions, calculateCropBounds, calculateEstimatedDuration, calculateFitDimensions, calculateLineWidth, calculateTimelineContentEnd, canSetAsReference, defaultOffset, emojiToUnified, formatTime, generateOverlayId, generateSegmentId, getAppleEmojiUrl, getBaseSegments, getBorderRadii, getDependentElements, getFontFamily, getOverlays, getReferenceElementX, getReferenceElementY, getSegmentTimelinePosition, hasEmoji, hexToRgba, isDynamicCropEnabled, isSegmentVisibleAtTime, parseHexColor, parseTime, preloadFonts, resolveElementPositions, splitTextAndEmojis, useFontsLoaded, useImageLoader, useImagePreloader, useResolvedPositions, wrapText };
package/dist/index.d.ts CHANGED
@@ -1290,6 +1290,34 @@ declare function generateSegmentId(): string;
1290
1290
  */
1291
1291
  declare function generateOverlayId(): string;
1292
1292
 
1293
+ /**
1294
+ * Emoji utilities for rendering Apple-style emojis consistently
1295
+ * across all platforms using CDN-hosted emoji images.
1296
+ */
1297
+ /**
1298
+ * Convert an emoji character to its unified unicode codepoint format
1299
+ * Example: "😀" -> "1f600", "👨‍👩‍👧" -> "1f468-200d-1f469-200d-1f467"
1300
+ */
1301
+ declare function emojiToUnified(emoji: string): string;
1302
+ /**
1303
+ * Get the Apple emoji CDN URL for a given emoji character
1304
+ */
1305
+ declare function getAppleEmojiUrl(emoji: string): string;
1306
+ /**
1307
+ * Check if a string contains any emoji characters
1308
+ */
1309
+ declare function hasEmoji(text: string): boolean;
1310
+ /**
1311
+ * Split text into segments of text and emojis
1312
+ * Returns an array of segments with type 'text' or 'emoji'
1313
+ */
1314
+ interface TextSegmentPart {
1315
+ type: 'text' | 'emoji';
1316
+ content: string;
1317
+ imageUrl?: string;
1318
+ }
1319
+ declare function splitTextAndEmojis(text: string): TextSegmentPart[];
1320
+
1293
1321
  /**
1294
1322
  * Hook exports for ugcinc-render
1295
1323
  *
@@ -1349,4 +1377,4 @@ declare function useResolvedPositions(elements: ImageEditorElement[], textValues
1349
1377
 
1350
1378
  declare const RenderRoot: React.FC;
1351
1379
 
1352
- export { type AudioSegment, type BaseEditorConfig, type BaseSegment, type BorderRadiusConfig, type Channel, type CropAxisConfig, type CropBoundary, type CropBounds, DIMENSION_PRESETS, type DimensionPreset, type DimensionPresetKey, type DynamicCropConfig, type EditorConfig, type EditorSegment, FONT_FAMILIES, FONT_URLS, type FitDimensions, type FitMode, type FontType, type FontWeight, type HorizontalAnchor, type HorizontalSelfAnchor, type Hyphenation, IMAGE_DEFAULTS, ImageEditorComposition, type ImageEditorCompositionProps, type ImageEditorConfig, type ImageEditorElement, type ImageEditorNodeConfig, ImageElement, type ImageElementProps, type ImageSegment, type PictureSegment, type PositionResolutionError, type PositionResolutionResult, type RelativePositionConfigX, type RelativePositionConfigY, RenderRoot, type Segment, type SegmentTimelinePosition, type SegmentType, type StaticSegment, TEXT_DEFAULTS, type TextAlignment, type TextDirection, TextElement, type TextElementProps, type TextOverflow, type TextSegment, type TextWrap, type TimeMode, type TimeValue, VIDEO_DEFAULTS, VISUAL_DEFAULTS, type VerticalAlignment, type VerticalAnchor, type VerticalSelfAnchor, type VideoEditorAudioSegment, type VideoEditorBaseSegment, type VideoEditorChannel, VideoEditorComposition, type VideoEditorCompositionProps, type VideoEditorConfig, type VideoEditorImageSegment, type VideoEditorNodeConfig, type VideoEditorSegment, type VideoEditorTextSegment, type VideoEditorVideoSegment, type VideoEditorVisualSegment, VideoElement, type VideoElementProps, type VideoSegment, type VisualSegment, type VisualSegmentUnion, type WordBreak, applyImageDefaults, applyTextDefaults, applyVideoDefaults, areFontsLoaded, buildFontString, calculateAutoWidthDimensions, calculateCropBounds, calculateEstimatedDuration, calculateFitDimensions, calculateLineWidth, calculateTimelineContentEnd, canSetAsReference, defaultOffset, formatTime, generateOverlayId, generateSegmentId, getBaseSegments, getBorderRadii, getDependentElements, getFontFamily, getOverlays, getReferenceElementX, getReferenceElementY, getSegmentTimelinePosition, hexToRgba, isDynamicCropEnabled, isSegmentVisibleAtTime, parseHexColor, parseTime, preloadFonts, resolveElementPositions, useFontsLoaded, useImageLoader, useImagePreloader, useResolvedPositions, wrapText };
1380
+ export { type AudioSegment, type BaseEditorConfig, type BaseSegment, type BorderRadiusConfig, type Channel, type CropAxisConfig, type CropBoundary, type CropBounds, DIMENSION_PRESETS, type DimensionPreset, type DimensionPresetKey, type DynamicCropConfig, type EditorConfig, type EditorSegment, FONT_FAMILIES, FONT_URLS, type FitDimensions, type FitMode, type FontType, type FontWeight, type HorizontalAnchor, type HorizontalSelfAnchor, type Hyphenation, IMAGE_DEFAULTS, ImageEditorComposition, type ImageEditorCompositionProps, type ImageEditorConfig, type ImageEditorElement, type ImageEditorNodeConfig, ImageElement, type ImageElementProps, type ImageSegment, type PictureSegment, type PositionResolutionError, type PositionResolutionResult, type RelativePositionConfigX, type RelativePositionConfigY, RenderRoot, type Segment, type SegmentTimelinePosition, type SegmentType, type StaticSegment, TEXT_DEFAULTS, type TextAlignment, type TextDirection, TextElement, type TextElementProps, type TextOverflow, type TextSegment, type TextSegmentPart, type TextWrap, type TimeMode, type TimeValue, VIDEO_DEFAULTS, VISUAL_DEFAULTS, type VerticalAlignment, type VerticalAnchor, type VerticalSelfAnchor, type VideoEditorAudioSegment, type VideoEditorBaseSegment, type VideoEditorChannel, VideoEditorComposition, type VideoEditorCompositionProps, type VideoEditorConfig, type VideoEditorImageSegment, type VideoEditorNodeConfig, type VideoEditorSegment, type VideoEditorTextSegment, type VideoEditorVideoSegment, type VideoEditorVisualSegment, VideoElement, type VideoElementProps, type VideoSegment, type VisualSegment, type VisualSegmentUnion, type WordBreak, applyImageDefaults, applyTextDefaults, applyVideoDefaults, areFontsLoaded, buildFontString, calculateAutoWidthDimensions, calculateCropBounds, calculateEstimatedDuration, calculateFitDimensions, calculateLineWidth, calculateTimelineContentEnd, canSetAsReference, defaultOffset, emojiToUnified, formatTime, generateOverlayId, generateSegmentId, getAppleEmojiUrl, getBaseSegments, getBorderRadii, getDependentElements, getFontFamily, getOverlays, getReferenceElementX, getReferenceElementY, getSegmentTimelinePosition, hasEmoji, hexToRgba, isDynamicCropEnabled, isSegmentVisibleAtTime, parseHexColor, parseTime, preloadFonts, resolveElementPositions, splitTextAndEmojis, useFontsLoaded, useImageLoader, useImagePreloader, useResolvedPositions, wrapText };
package/dist/index.js CHANGED
@@ -56,9 +56,11 @@ __export(index_exports, {
56
56
  calculateTimelineContentEnd: () => calculateTimelineContentEnd,
57
57
  canSetAsReference: () => canSetAsReference,
58
58
  defaultOffset: () => defaultOffset,
59
+ emojiToUnified: () => emojiToUnified,
59
60
  formatTime: () => formatTime,
60
61
  generateOverlayId: () => generateOverlayId,
61
62
  generateSegmentId: () => generateSegmentId,
63
+ getAppleEmojiUrl: () => getAppleEmojiUrl,
62
64
  getBaseSegments: () => getBaseSegments,
63
65
  getBorderRadii: () => getBorderRadii,
64
66
  getDependentElements: () => getDependentElements,
@@ -67,6 +69,7 @@ __export(index_exports, {
67
69
  getReferenceElementX: () => getReferenceElementX,
68
70
  getReferenceElementY: () => getReferenceElementY,
69
71
  getSegmentTimelinePosition: () => getSegmentTimelinePosition,
72
+ hasEmoji: () => hasEmoji,
70
73
  hexToRgba: () => hexToRgba,
71
74
  isDynamicCropEnabled: () => isDynamicCropEnabled,
72
75
  isSegmentVisibleAtTime: () => isSegmentVisibleAtTime,
@@ -74,6 +77,7 @@ __export(index_exports, {
74
77
  parseTime: () => parseTime,
75
78
  preloadFonts: () => preloadFonts,
76
79
  resolveElementPositions: () => resolveElementPositions,
80
+ splitTextAndEmojis: () => splitTextAndEmojis,
77
81
  useFontsLoaded: () => useFontsLoaded,
78
82
  useImageLoader: () => useImageLoader,
79
83
  useImagePreloader: () => useImagePreloader,
@@ -302,6 +306,54 @@ function hexToRgba(hex, opacity = 100) {
302
306
  return `rgba(${r}, ${g}, ${b}, ${opacity / 100})`;
303
307
  }
304
308
 
309
+ // src/utils/emoji.ts
310
+ var APPLE_EMOJI_CDN_BASE = "https://cdn.jsdelivr.net/npm/emoji-datasource-apple/img/apple/64/";
311
+ function emojiToUnified(emoji) {
312
+ const codePoints = [];
313
+ for (const codePoint of emoji) {
314
+ const hex = codePoint.codePointAt(0)?.toString(16);
315
+ if (hex) {
316
+ codePoints.push(hex);
317
+ }
318
+ }
319
+ return codePoints.join("-");
320
+ }
321
+ function getAppleEmojiUrl(emoji) {
322
+ const unified = emojiToUnified(emoji);
323
+ return `${APPLE_EMOJI_CDN_BASE}${unified}.png`;
324
+ }
325
+ var EMOJI_REGEX = /(?:\p{Emoji_Presentation}|\p{Emoji}\uFE0F)(?:\p{Emoji_Modifier}|\uFE0F|\u200D(?:\p{Emoji_Presentation}|\p{Emoji}\uFE0F)(?:\p{Emoji_Modifier})?)*|\p{Regional_Indicator}{2}/gu;
326
+ function hasEmoji(text) {
327
+ return EMOJI_REGEX.test(text);
328
+ }
329
+ function splitTextAndEmojis(text) {
330
+ const segments = [];
331
+ let lastIndex = 0;
332
+ EMOJI_REGEX.lastIndex = 0;
333
+ let match;
334
+ while ((match = EMOJI_REGEX.exec(text)) !== null) {
335
+ if (match.index > lastIndex) {
336
+ segments.push({
337
+ type: "text",
338
+ content: text.slice(lastIndex, match.index)
339
+ });
340
+ }
341
+ segments.push({
342
+ type: "emoji",
343
+ content: match[0],
344
+ imageUrl: getAppleEmojiUrl(match[0])
345
+ });
346
+ lastIndex = match.index + match[0].length;
347
+ }
348
+ if (lastIndex < text.length) {
349
+ segments.push({
350
+ type: "text",
351
+ content: text.slice(lastIndex)
352
+ });
353
+ }
354
+ return segments;
355
+ }
356
+
305
357
  // src/components/TextElement.tsx
306
358
  var import_jsx_runtime = require("react/jsx-runtime");
307
359
  function calculateAutoWidthAndLines({
@@ -604,9 +656,35 @@ function TextElement({ segment, scale = 1 }) {
604
656
  autoWidth,
605
657
  verticalAlign
606
658
  ]);
659
+ const renderTextWithEmojis = (text) => {
660
+ if (!hasEmoji(text)) {
661
+ return text;
662
+ }
663
+ const segments = splitTextAndEmojis(text);
664
+ return segments.map((segment2, i) => {
665
+ if (segment2.type === "emoji" && segment2.imageUrl) {
666
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
667
+ "img",
668
+ {
669
+ src: segment2.imageUrl,
670
+ alt: segment2.content,
671
+ style: {
672
+ height: "1em",
673
+ width: "1em",
674
+ verticalAlign: "-0.1em",
675
+ display: "inline"
676
+ },
677
+ draggable: false
678
+ },
679
+ i
680
+ );
681
+ }
682
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react.default.Fragment, { children: segment2.content }, i);
683
+ });
684
+ };
607
685
  if (autoWidth) {
608
686
  const textContent = calculatedLines.map((line, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react.default.Fragment, { children: [
609
- line,
687
+ renderTextWithEmojis(line),
610
688
  index < calculatedLines.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("br", {})
611
689
  ] }, index));
612
690
  if (backgroundColor) {
@@ -625,7 +703,7 @@ function TextElement({ segment, scale = 1 }) {
625
703
  }
626
704
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: positioningContainerStyle, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { width: calculatedWidth, maxWidth: width }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: textStyle, children: textContent }) }) });
627
705
  }
628
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: positioningContainerStyle, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: backgroundBoxStyle, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: textStyle, children: segment.text }) }) });
706
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: positioningContainerStyle, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: backgroundBoxStyle, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: textStyle, children: renderTextWithEmojis(segment.text) }) }) });
629
707
  }
630
708
 
631
709
  // src/components/ImageElement.tsx
@@ -1945,9 +2023,11 @@ var RenderRoot = () => {
1945
2023
  calculateTimelineContentEnd,
1946
2024
  canSetAsReference,
1947
2025
  defaultOffset,
2026
+ emojiToUnified,
1948
2027
  formatTime,
1949
2028
  generateOverlayId,
1950
2029
  generateSegmentId,
2030
+ getAppleEmojiUrl,
1951
2031
  getBaseSegments,
1952
2032
  getBorderRadii,
1953
2033
  getDependentElements,
@@ -1956,6 +2036,7 @@ var RenderRoot = () => {
1956
2036
  getReferenceElementX,
1957
2037
  getReferenceElementY,
1958
2038
  getSegmentTimelinePosition,
2039
+ hasEmoji,
1959
2040
  hexToRgba,
1960
2041
  isDynamicCropEnabled,
1961
2042
  isSegmentVisibleAtTime,
@@ -1963,6 +2044,7 @@ var RenderRoot = () => {
1963
2044
  parseTime,
1964
2045
  preloadFonts,
1965
2046
  resolveElementPositions,
2047
+ splitTextAndEmojis,
1966
2048
  useFontsLoaded,
1967
2049
  useImageLoader,
1968
2050
  useImagePreloader,
package/dist/index.mjs CHANGED
@@ -218,6 +218,54 @@ function hexToRgba(hex, opacity = 100) {
218
218
  return `rgba(${r}, ${g}, ${b}, ${opacity / 100})`;
219
219
  }
220
220
 
221
+ // src/utils/emoji.ts
222
+ var APPLE_EMOJI_CDN_BASE = "https://cdn.jsdelivr.net/npm/emoji-datasource-apple/img/apple/64/";
223
+ function emojiToUnified(emoji) {
224
+ const codePoints = [];
225
+ for (const codePoint of emoji) {
226
+ const hex = codePoint.codePointAt(0)?.toString(16);
227
+ if (hex) {
228
+ codePoints.push(hex);
229
+ }
230
+ }
231
+ return codePoints.join("-");
232
+ }
233
+ function getAppleEmojiUrl(emoji) {
234
+ const unified = emojiToUnified(emoji);
235
+ return `${APPLE_EMOJI_CDN_BASE}${unified}.png`;
236
+ }
237
+ var EMOJI_REGEX = /(?:\p{Emoji_Presentation}|\p{Emoji}\uFE0F)(?:\p{Emoji_Modifier}|\uFE0F|\u200D(?:\p{Emoji_Presentation}|\p{Emoji}\uFE0F)(?:\p{Emoji_Modifier})?)*|\p{Regional_Indicator}{2}/gu;
238
+ function hasEmoji(text) {
239
+ return EMOJI_REGEX.test(text);
240
+ }
241
+ function splitTextAndEmojis(text) {
242
+ const segments = [];
243
+ let lastIndex = 0;
244
+ EMOJI_REGEX.lastIndex = 0;
245
+ let match;
246
+ while ((match = EMOJI_REGEX.exec(text)) !== null) {
247
+ if (match.index > lastIndex) {
248
+ segments.push({
249
+ type: "text",
250
+ content: text.slice(lastIndex, match.index)
251
+ });
252
+ }
253
+ segments.push({
254
+ type: "emoji",
255
+ content: match[0],
256
+ imageUrl: getAppleEmojiUrl(match[0])
257
+ });
258
+ lastIndex = match.index + match[0].length;
259
+ }
260
+ if (lastIndex < text.length) {
261
+ segments.push({
262
+ type: "text",
263
+ content: text.slice(lastIndex)
264
+ });
265
+ }
266
+ return segments;
267
+ }
268
+
221
269
  // src/components/TextElement.tsx
222
270
  import { jsx, jsxs } from "react/jsx-runtime";
223
271
  function calculateAutoWidthAndLines({
@@ -520,9 +568,35 @@ function TextElement({ segment, scale = 1 }) {
520
568
  autoWidth,
521
569
  verticalAlign
522
570
  ]);
571
+ const renderTextWithEmojis = (text) => {
572
+ if (!hasEmoji(text)) {
573
+ return text;
574
+ }
575
+ const segments = splitTextAndEmojis(text);
576
+ return segments.map((segment2, i) => {
577
+ if (segment2.type === "emoji" && segment2.imageUrl) {
578
+ return /* @__PURE__ */ jsx(
579
+ "img",
580
+ {
581
+ src: segment2.imageUrl,
582
+ alt: segment2.content,
583
+ style: {
584
+ height: "1em",
585
+ width: "1em",
586
+ verticalAlign: "-0.1em",
587
+ display: "inline"
588
+ },
589
+ draggable: false
590
+ },
591
+ i
592
+ );
593
+ }
594
+ return /* @__PURE__ */ jsx(React.Fragment, { children: segment2.content }, i);
595
+ });
596
+ };
523
597
  if (autoWidth) {
524
598
  const textContent = calculatedLines.map((line, index) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
525
- line,
599
+ renderTextWithEmojis(line),
526
600
  index < calculatedLines.length - 1 && /* @__PURE__ */ jsx("br", {})
527
601
  ] }, index));
528
602
  if (backgroundColor) {
@@ -541,7 +615,7 @@ function TextElement({ segment, scale = 1 }) {
541
615
  }
542
616
  return /* @__PURE__ */ jsx("div", { style: positioningContainerStyle, children: /* @__PURE__ */ jsx("div", { style: { width: calculatedWidth, maxWidth: width }, children: /* @__PURE__ */ jsx("div", { style: textStyle, children: textContent }) }) });
543
617
  }
544
- return /* @__PURE__ */ jsx("div", { style: positioningContainerStyle, children: /* @__PURE__ */ jsx("div", { style: backgroundBoxStyle, children: /* @__PURE__ */ jsx("div", { style: textStyle, children: segment.text }) }) });
618
+ return /* @__PURE__ */ jsx("div", { style: positioningContainerStyle, children: /* @__PURE__ */ jsx("div", { style: backgroundBoxStyle, children: /* @__PURE__ */ jsx("div", { style: textStyle, children: renderTextWithEmojis(segment.text) }) }) });
545
619
  }
546
620
 
547
621
  // src/components/ImageElement.tsx
@@ -1860,9 +1934,11 @@ export {
1860
1934
  calculateTimelineContentEnd,
1861
1935
  canSetAsReference,
1862
1936
  defaultOffset,
1937
+ emojiToUnified,
1863
1938
  formatTime,
1864
1939
  generateOverlayId,
1865
1940
  generateSegmentId,
1941
+ getAppleEmojiUrl,
1866
1942
  getBaseSegments,
1867
1943
  getBorderRadii,
1868
1944
  getDependentElements,
@@ -1871,6 +1947,7 @@ export {
1871
1947
  getReferenceElementX,
1872
1948
  getReferenceElementY,
1873
1949
  getSegmentTimelinePosition,
1950
+ hasEmoji,
1874
1951
  hexToRgba,
1875
1952
  isDynamicCropEnabled,
1876
1953
  isSegmentVisibleAtTime,
@@ -1878,6 +1955,7 @@ export {
1878
1955
  parseTime,
1879
1956
  preloadFonts,
1880
1957
  resolveElementPositions,
1958
+ splitTextAndEmojis,
1881
1959
  useFontsLoaded,
1882
1960
  useImageLoader,
1883
1961
  useImagePreloader,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ugcinc-render",
3
- "version": "1.5.11",
3
+ "version": "1.5.12",
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",