ugcinc-render 1.5.17 → 1.5.19

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.js CHANGED
@@ -420,29 +420,28 @@ function calculateAutoWidthAndLines({
420
420
  white-space: nowrap;
421
421
  `;
422
422
  document.body.appendChild(measureSpan);
423
+ const computedStyle = window.getComputedStyle(measureSpan);
424
+ const computedFontFamily = computedStyle.fontFamily;
425
+ const requestedFontLoaded = typeof document.fonts !== "undefined" ? document.fonts.check(`${fontWeight} ${fontSize}px ${fontFamily.split(",")[0]}`) : "unknown";
423
426
  const measureText = (textToMeasure) => {
424
427
  measureSpan.textContent = textToMeasure;
425
428
  return measureSpan.getBoundingClientRect().width;
426
429
  };
427
430
  measureSpan.textContent = "M";
428
- const charWidth = measureSpan.getBoundingClientRect().width;
431
+ const mWidth = measureSpan.getBoundingClientRect().width;
429
432
  const words = text.split(/(\s+)/);
430
433
  const lines = [];
431
434
  let currentLine = "";
432
435
  for (let i = 0; i < words.length; i++) {
433
436
  const word = words[i];
434
437
  if (word === "\n" || word === "\r\n") {
435
- if (currentLine) {
436
- lines.push(currentLine);
437
- }
438
+ if (currentLine) lines.push(currentLine);
438
439
  currentLine = "";
439
440
  continue;
440
441
  }
441
442
  if (!word) continue;
442
443
  if (/^\s+$/.test(word)) {
443
- if (currentLine) {
444
- currentLine += word;
445
- }
444
+ if (currentLine) currentLine += word;
446
445
  continue;
447
446
  }
448
447
  const testLine = currentLine + word;
@@ -477,12 +476,8 @@ function calculateAutoWidthAndLines({
477
476
  currentLine = testLine;
478
477
  }
479
478
  }
480
- if (currentLine.trim()) {
481
- lines.push(currentLine.trimEnd());
482
- }
483
- if (lines.length === 0) {
484
- lines.push("");
485
- }
479
+ if (currentLine.trim()) lines.push(currentLine.trimEnd());
480
+ if (lines.length === 0) lines.push("");
486
481
  let widestLineWidth = 0;
487
482
  for (const line of lines) {
488
483
  const lineWidth = measureText(line);
@@ -490,18 +485,25 @@ function calculateAutoWidthAndLines({
490
485
  }
491
486
  document.body.removeChild(measureSpan);
492
487
  const calculatedWidth = Math.min(widestLineWidth + paddingLeft + paddingRight, maxWidth);
488
+ console.log("[TextElement] WIDTH_CALC:", JSON.stringify({
489
+ text: text.substring(0, 30),
490
+ fontFamily: fontFamily.split(",")[0],
491
+ computedFont: computedFontFamily.split(",")[0],
492
+ fontLoaded: requestedFontLoaded,
493
+ fontSize,
494
+ fontWeight,
495
+ letterSpacing,
496
+ mWidth: Math.round(mWidth * 100) / 100,
497
+ widestLine: Math.round(widestLineWidth * 100) / 100,
498
+ paddingL: paddingLeft,
499
+ paddingR: paddingRight,
500
+ calcWidth: Math.round(calculatedWidth * 100) / 100,
501
+ maxWidth,
502
+ lines: lines.length
503
+ }));
493
504
  return { width: calculatedWidth, lines };
494
505
  }
495
506
  function TextElement({ segment, scale = 1 }) {
496
- import_react.default.useEffect(() => {
497
- const fontFamily2 = getFontFamily(segment.fontType ?? TEXT_DEFAULTS.fontType);
498
- console.log("[ugcinc-render/TextElement] Rendering with:", {
499
- text: segment.text?.substring(0, 50) + (segment.text?.length > 50 ? "..." : ""),
500
- fontType: segment.fontType ?? TEXT_DEFAULTS.fontType,
501
- fontFamily: fontFamily2,
502
- hasEmojis: /[\u{1F300}-\u{1F9FF}]/u.test(segment.text || "")
503
- });
504
- }, [segment.text, segment.fontType]);
505
507
  const fontType = segment.fontType ?? TEXT_DEFAULTS.fontType;
506
508
  const fontSize = (segment.fontSize ?? TEXT_DEFAULTS.fontSize) * scale;
507
509
  const fontWeight = segment.fontWeight ?? TEXT_DEFAULTS.fontWeight;
@@ -623,24 +625,11 @@ function TextElement({ segment, scale = 1 }) {
623
625
  transformOrigin: "center center",
624
626
  display: "flex",
625
627
  flexDirection: "column",
626
- // Vertical alignment within the container
627
628
  justifyContent: verticalAlign === "top" ? "flex-start" : verticalAlign === "bottom" ? "flex-end" : "center",
628
- // Horizontal alignment (boxAlign) - only applies when autoWidth is enabled
629
629
  alignItems: autoWidth ? boxAlign === "center" ? "center" : boxAlign === "right" ? "flex-end" : "flex-start" : "stretch"
630
630
  }), [x, y, width, height, rotation, verticalAlign, autoWidth, boxAlign]);
631
631
  const backgroundBoxStyle = (0, import_react.useMemo)(() => {
632
- const baseStyle = autoWidth ? {
633
- // Use explicit calculated width instead of fit-content
634
- // This fixes the issue where multi-line text doesn't shrink to widest line
635
- width: calculatedWidth,
636
- maxWidth: width
637
- } : {
638
- // When not autoWidth, let the text div handle everything
639
- display: "flex",
640
- flexDirection: "column",
641
- flex: 1,
642
- minHeight: 0
643
- };
632
+ const baseStyle = autoWidth ? { width: calculatedWidth, maxWidth: width } : { display: "flex", flexDirection: "column", flex: 1, minHeight: 0 };
644
633
  if (!backgroundColor) return baseStyle;
645
634
  return {
646
635
  ...baseStyle,
@@ -655,12 +644,10 @@ function TextElement({ segment, scale = 1 }) {
655
644
  color,
656
645
  lineHeight,
657
646
  letterSpacing,
658
- // textAlign works for multi-line text within the (possibly auto-width) box
659
647
  textAlign: alignment === "justify" ? "justify" : alignment,
660
648
  padding: `${paddingTop}px ${paddingRight}px ${paddingBottom}px ${paddingLeft}px`,
661
649
  whiteSpace: "pre-wrap",
662
650
  wordBreak: "break-word",
663
- // When not autoWidth, handle vertical alignment via flex
664
651
  ...!autoWidth && {
665
652
  display: "flex",
666
653
  flexDirection: "column",
@@ -668,7 +655,6 @@ function TextElement({ segment, scale = 1 }) {
668
655
  flex: 1,
669
656
  minHeight: 0
670
657
  },
671
- // Text stroke using text-shadow for cross-browser support
672
658
  ...strokeWidth > 0 && strokeColor && {
673
659
  textShadow: `
674
660
  -${strokeWidth}px -${strokeWidth}px 0 ${strokeColor},
@@ -680,7 +666,6 @@ function TextElement({ segment, scale = 1 }) {
680
666
  -${strokeWidth}px 0 0 ${strokeColor},
681
667
  ${strokeWidth}px 0 0 ${strokeColor}
682
668
  `,
683
- // Also use WebKit text stroke for better quality where supported
684
669
  WebkitTextStroke: `${strokeWidth}px ${strokeColor}`,
685
670
  paintOrder: "stroke fill"
686
671
  }
@@ -1242,7 +1227,7 @@ function getSortedSegments(config) {
1242
1227
  });
1243
1228
  }
1244
1229
  function elementToTextSegment(elem) {
1245
- return {
1230
+ const segment = {
1246
1231
  id: elem.id,
1247
1232
  type: "text",
1248
1233
  source: "",
@@ -1280,6 +1265,18 @@ function elementToTextSegment(elem) {
1280
1265
  autoWidth: elem.autoWidth,
1281
1266
  boxAlign: elem.boxAlign
1282
1267
  };
1268
+ console.log("[Composition] ELEMENT:", JSON.stringify({
1269
+ id: elem.id,
1270
+ text: (elem.text ?? "").substring(0, 20),
1271
+ w: elem.width,
1272
+ h: elem.height,
1273
+ font: elem.font,
1274
+ fontSize: elem.fontSize,
1275
+ autoWidth: elem.autoWidth,
1276
+ pL: elem.paddingLeft,
1277
+ pR: elem.paddingRight
1278
+ }));
1279
+ return segment;
1283
1280
  }
1284
1281
  function elementToImageSegment(elem, source) {
1285
1282
  return {
package/dist/index.mjs CHANGED
@@ -334,29 +334,28 @@ function calculateAutoWidthAndLines({
334
334
  white-space: nowrap;
335
335
  `;
336
336
  document.body.appendChild(measureSpan);
337
+ const computedStyle = window.getComputedStyle(measureSpan);
338
+ const computedFontFamily = computedStyle.fontFamily;
339
+ const requestedFontLoaded = typeof document.fonts !== "undefined" ? document.fonts.check(`${fontWeight} ${fontSize}px ${fontFamily.split(",")[0]}`) : "unknown";
337
340
  const measureText = (textToMeasure) => {
338
341
  measureSpan.textContent = textToMeasure;
339
342
  return measureSpan.getBoundingClientRect().width;
340
343
  };
341
344
  measureSpan.textContent = "M";
342
- const charWidth = measureSpan.getBoundingClientRect().width;
345
+ const mWidth = measureSpan.getBoundingClientRect().width;
343
346
  const words = text.split(/(\s+)/);
344
347
  const lines = [];
345
348
  let currentLine = "";
346
349
  for (let i = 0; i < words.length; i++) {
347
350
  const word = words[i];
348
351
  if (word === "\n" || word === "\r\n") {
349
- if (currentLine) {
350
- lines.push(currentLine);
351
- }
352
+ if (currentLine) lines.push(currentLine);
352
353
  currentLine = "";
353
354
  continue;
354
355
  }
355
356
  if (!word) continue;
356
357
  if (/^\s+$/.test(word)) {
357
- if (currentLine) {
358
- currentLine += word;
359
- }
358
+ if (currentLine) currentLine += word;
360
359
  continue;
361
360
  }
362
361
  const testLine = currentLine + word;
@@ -391,12 +390,8 @@ function calculateAutoWidthAndLines({
391
390
  currentLine = testLine;
392
391
  }
393
392
  }
394
- if (currentLine.trim()) {
395
- lines.push(currentLine.trimEnd());
396
- }
397
- if (lines.length === 0) {
398
- lines.push("");
399
- }
393
+ if (currentLine.trim()) lines.push(currentLine.trimEnd());
394
+ if (lines.length === 0) lines.push("");
400
395
  let widestLineWidth = 0;
401
396
  for (const line of lines) {
402
397
  const lineWidth = measureText(line);
@@ -404,18 +399,25 @@ function calculateAutoWidthAndLines({
404
399
  }
405
400
  document.body.removeChild(measureSpan);
406
401
  const calculatedWidth = Math.min(widestLineWidth + paddingLeft + paddingRight, maxWidth);
402
+ console.log("[TextElement] WIDTH_CALC:", JSON.stringify({
403
+ text: text.substring(0, 30),
404
+ fontFamily: fontFamily.split(",")[0],
405
+ computedFont: computedFontFamily.split(",")[0],
406
+ fontLoaded: requestedFontLoaded,
407
+ fontSize,
408
+ fontWeight,
409
+ letterSpacing,
410
+ mWidth: Math.round(mWidth * 100) / 100,
411
+ widestLine: Math.round(widestLineWidth * 100) / 100,
412
+ paddingL: paddingLeft,
413
+ paddingR: paddingRight,
414
+ calcWidth: Math.round(calculatedWidth * 100) / 100,
415
+ maxWidth,
416
+ lines: lines.length
417
+ }));
407
418
  return { width: calculatedWidth, lines };
408
419
  }
409
420
  function TextElement({ segment, scale = 1 }) {
410
- React.useEffect(() => {
411
- const fontFamily2 = getFontFamily(segment.fontType ?? TEXT_DEFAULTS.fontType);
412
- console.log("[ugcinc-render/TextElement] Rendering with:", {
413
- text: segment.text?.substring(0, 50) + (segment.text?.length > 50 ? "..." : ""),
414
- fontType: segment.fontType ?? TEXT_DEFAULTS.fontType,
415
- fontFamily: fontFamily2,
416
- hasEmojis: /[\u{1F300}-\u{1F9FF}]/u.test(segment.text || "")
417
- });
418
- }, [segment.text, segment.fontType]);
419
421
  const fontType = segment.fontType ?? TEXT_DEFAULTS.fontType;
420
422
  const fontSize = (segment.fontSize ?? TEXT_DEFAULTS.fontSize) * scale;
421
423
  const fontWeight = segment.fontWeight ?? TEXT_DEFAULTS.fontWeight;
@@ -537,24 +539,11 @@ function TextElement({ segment, scale = 1 }) {
537
539
  transformOrigin: "center center",
538
540
  display: "flex",
539
541
  flexDirection: "column",
540
- // Vertical alignment within the container
541
542
  justifyContent: verticalAlign === "top" ? "flex-start" : verticalAlign === "bottom" ? "flex-end" : "center",
542
- // Horizontal alignment (boxAlign) - only applies when autoWidth is enabled
543
543
  alignItems: autoWidth ? boxAlign === "center" ? "center" : boxAlign === "right" ? "flex-end" : "flex-start" : "stretch"
544
544
  }), [x, y, width, height, rotation, verticalAlign, autoWidth, boxAlign]);
545
545
  const backgroundBoxStyle = useMemo(() => {
546
- const baseStyle = autoWidth ? {
547
- // Use explicit calculated width instead of fit-content
548
- // This fixes the issue where multi-line text doesn't shrink to widest line
549
- width: calculatedWidth,
550
- maxWidth: width
551
- } : {
552
- // When not autoWidth, let the text div handle everything
553
- display: "flex",
554
- flexDirection: "column",
555
- flex: 1,
556
- minHeight: 0
557
- };
546
+ const baseStyle = autoWidth ? { width: calculatedWidth, maxWidth: width } : { display: "flex", flexDirection: "column", flex: 1, minHeight: 0 };
558
547
  if (!backgroundColor) return baseStyle;
559
548
  return {
560
549
  ...baseStyle,
@@ -569,12 +558,10 @@ function TextElement({ segment, scale = 1 }) {
569
558
  color,
570
559
  lineHeight,
571
560
  letterSpacing,
572
- // textAlign works for multi-line text within the (possibly auto-width) box
573
561
  textAlign: alignment === "justify" ? "justify" : alignment,
574
562
  padding: `${paddingTop}px ${paddingRight}px ${paddingBottom}px ${paddingLeft}px`,
575
563
  whiteSpace: "pre-wrap",
576
564
  wordBreak: "break-word",
577
- // When not autoWidth, handle vertical alignment via flex
578
565
  ...!autoWidth && {
579
566
  display: "flex",
580
567
  flexDirection: "column",
@@ -582,7 +569,6 @@ function TextElement({ segment, scale = 1 }) {
582
569
  flex: 1,
583
570
  minHeight: 0
584
571
  },
585
- // Text stroke using text-shadow for cross-browser support
586
572
  ...strokeWidth > 0 && strokeColor && {
587
573
  textShadow: `
588
574
  -${strokeWidth}px -${strokeWidth}px 0 ${strokeColor},
@@ -594,7 +580,6 @@ function TextElement({ segment, scale = 1 }) {
594
580
  -${strokeWidth}px 0 0 ${strokeColor},
595
581
  ${strokeWidth}px 0 0 ${strokeColor}
596
582
  `,
597
- // Also use WebKit text stroke for better quality where supported
598
583
  WebkitTextStroke: `${strokeWidth}px ${strokeColor}`,
599
584
  paintOrder: "stroke fill"
600
585
  }
@@ -1156,7 +1141,7 @@ function getSortedSegments(config) {
1156
1141
  });
1157
1142
  }
1158
1143
  function elementToTextSegment(elem) {
1159
- return {
1144
+ const segment = {
1160
1145
  id: elem.id,
1161
1146
  type: "text",
1162
1147
  source: "",
@@ -1194,6 +1179,18 @@ function elementToTextSegment(elem) {
1194
1179
  autoWidth: elem.autoWidth,
1195
1180
  boxAlign: elem.boxAlign
1196
1181
  };
1182
+ console.log("[Composition] ELEMENT:", JSON.stringify({
1183
+ id: elem.id,
1184
+ text: (elem.text ?? "").substring(0, 20),
1185
+ w: elem.width,
1186
+ h: elem.height,
1187
+ font: elem.font,
1188
+ fontSize: elem.fontSize,
1189
+ autoWidth: elem.autoWidth,
1190
+ pL: elem.paddingLeft,
1191
+ pR: elem.paddingRight
1192
+ }));
1193
+ return segment;
1197
1194
  }
1198
1195
  function elementToImageSegment(elem, source) {
1199
1196
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ugcinc-render",
3
- "version": "1.5.17",
3
+ "version": "1.5.19",
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",