ugcinc-render 1.8.218 → 1.8.220

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
@@ -926,6 +926,7 @@ function TextElement({ segment, scale = 1 }) {
926
926
  borderRadius: borderRadiusStyle
927
927
  };
928
928
  }, [autoWidth, calculatedWidth, width, backgroundColor, backgroundOpacity, borderRadiusStyle]);
929
+ const hasStroke = strokeWidth > 0 && !!strokeColor;
929
930
  const textStyle = (0, import_react.useMemo)(() => ({
930
931
  fontFamily,
931
932
  fontSize,
@@ -944,20 +945,7 @@ function TextElement({ segment, scale = 1 }) {
944
945
  flex: 1,
945
946
  minHeight: 0
946
947
  },
947
- ...strokeWidth > 0 && strokeColor && {
948
- textShadow: `
949
- -${strokeWidth}px -${strokeWidth}px 0 ${strokeColor},
950
- ${strokeWidth}px -${strokeWidth}px 0 ${strokeColor},
951
- -${strokeWidth}px ${strokeWidth}px 0 ${strokeColor},
952
- ${strokeWidth}px ${strokeWidth}px 0 ${strokeColor},
953
- 0 -${strokeWidth}px 0 ${strokeColor},
954
- 0 ${strokeWidth}px 0 ${strokeColor},
955
- -${strokeWidth}px 0 0 ${strokeColor},
956
- ${strokeWidth}px 0 0 ${strokeColor}
957
- `,
958
- WebkitTextStroke: `${strokeWidth}px ${strokeColor}`,
959
- paintOrder: "stroke fill"
960
- }
948
+ ...hasStroke && { position: "relative" }
961
949
  }), [
962
950
  fontFamily,
963
951
  fontSize,
@@ -970,33 +958,52 @@ function TextElement({ segment, scale = 1 }) {
970
958
  paddingRight,
971
959
  paddingBottom,
972
960
  paddingLeft,
973
- strokeWidth,
974
- strokeColor,
975
961
  autoWidth,
976
- verticalAlign
962
+ verticalAlign,
963
+ hasStroke
977
964
  ]);
965
+ const strokeTextStyle = (0, import_react.useMemo)(() => {
966
+ if (!hasStroke) return void 0;
967
+ return {
968
+ ...textStyle,
969
+ color: strokeColor,
970
+ WebkitTextStroke: `${strokeWidth * 2}px ${strokeColor}`,
971
+ position: "absolute",
972
+ inset: 0
973
+ };
974
+ }, [hasStroke, textStyle, strokeColor, strokeWidth]);
978
975
  if (autoWidth) {
979
976
  const textContent = calculatedLines.map((line, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react.default.Fragment, { children: [
980
977
  line,
981
978
  index < calculatedLines.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("br", {})
982
979
  ] }, index));
983
980
  if (backgroundColor) {
984
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: positioningContainerStyle, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
981
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: positioningContainerStyle, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
985
982
  "div",
986
983
  {
987
984
  style: {
988
985
  width: calculatedWidth,
989
986
  maxWidth: width,
990
987
  backgroundColor: hexToRgba(backgroundColor, backgroundOpacity),
991
- borderRadius: borderRadiusStyle
988
+ borderRadius: borderRadiusStyle,
989
+ ...hasStroke && { position: "relative" }
992
990
  },
993
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: textStyle, children: textContent })
991
+ children: [
992
+ strokeTextStyle && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: strokeTextStyle, "aria-hidden": "true", children: textContent }),
993
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: textStyle, children: textContent })
994
+ ]
994
995
  }
995
996
  ) });
996
997
  }
997
- 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 }) }) });
998
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: positioningContainerStyle, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { width: calculatedWidth, maxWidth: width, ...hasStroke && { position: "relative" } }, children: [
999
+ strokeTextStyle && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: strokeTextStyle, "aria-hidden": "true", children: textContent }),
1000
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: textStyle, children: textContent })
1001
+ ] }) });
998
1002
  }
999
- 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 }) }) });
1003
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: positioningContainerStyle, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { ...backgroundBoxStyle, ...hasStroke && { position: "relative" } }, children: [
1004
+ strokeTextStyle && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: strokeTextStyle, "aria-hidden": "true", children: segment.text }),
1005
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: textStyle, children: segment.text })
1006
+ ] }) });
1000
1007
  }
1001
1008
 
1002
1009
  // src/components/ImageElement.tsx
@@ -2373,32 +2380,17 @@ function CaptionOverlay({ captions, style, previewTimeMs }) {
2373
2380
  borderRadius: scaledBorderRadius
2374
2381
  };
2375
2382
  const numericFontWeight = style.fontWeight === "black" ? 900 : style.fontWeight === "bold" ? 700 : 400;
2376
- const buildStrokeShadow = () => {
2377
- if (scaledStrokeWidth <= 0) return "none";
2378
- const sw = scaledStrokeWidth;
2379
- const sc = style.strokeColor;
2380
- return `
2381
- -${sw}px -${sw}px 0 ${sc},
2382
- ${sw}px -${sw}px 0 ${sc},
2383
- -${sw}px ${sw}px 0 ${sc},
2384
- ${sw}px ${sw}px 0 ${sc},
2385
- 0 -${sw}px 0 ${sc},
2386
- 0 ${sw}px 0 ${sc},
2387
- -${sw}px 0 0 ${sc},
2388
- ${sw}px 0 0 ${sc}
2389
- `;
2390
- };
2391
2383
  const textContainerStyles = {
2392
2384
  fontFamily: `"${style.fontName}", sans-serif`,
2393
2385
  fontSize: scaledFontSize,
2394
2386
  fontWeight: numericFontWeight,
2395
2387
  lineHeight: 1.2,
2396
- wordBreak: "break-word",
2397
- textShadow: buildStrokeShadow()
2388
+ wordBreak: "break-word"
2398
2389
  };
2399
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: containerStyles, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: textContainerStyles, children: currentPage.words.map((word, index) => {
2390
+ const hasStroke = scaledStrokeWidth > 0;
2391
+ const renderWords = ({ isStrokeLayer }) => currentPage.words.map((word, index) => {
2400
2392
  const isActive = currentMs >= word.startMs && currentMs <= word.endMs;
2401
- const color = isActive ? style.highlightColor : style.fontColor;
2393
+ const color = isStrokeLayer ? style.strokeColor : isActive ? style.highlightColor : style.fontColor;
2402
2394
  let scale = 1;
2403
2395
  if (style.enableAnimation && isActive) {
2404
2396
  const wordDuration = word.endMs - word.startMs;
@@ -2423,14 +2415,21 @@ function CaptionOverlay({ captions, style, previewTimeMs }) {
2423
2415
  color,
2424
2416
  display: "inline-block",
2425
2417
  transform: `scale(${scale})`,
2426
- transformOrigin: "center center"
2418
+ transformOrigin: "center center",
2419
+ ...isStrokeLayer && {
2420
+ WebkitTextStroke: `${scaledStrokeWidth * 2}px ${style.strokeColor}`
2421
+ }
2427
2422
  },
2428
2423
  children: word.word
2429
2424
  }
2430
2425
  ),
2431
2426
  index < currentPage.words.length - 1 && " "
2432
2427
  ] }, `${word.word}-${word.startMs}-${index}`);
2433
- }) }) });
2428
+ });
2429
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: containerStyles, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { position: "relative" }, children: [
2430
+ hasStroke && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { ...textContainerStyles, position: "absolute", inset: 0 }, "aria-hidden": "true", children: renderWords({ isStrokeLayer: true }) }),
2431
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { ...textContainerStyles, ...hasStroke && { position: "relative" } }, children: renderWords({ isStrokeLayer: false }) })
2432
+ ] }) });
2434
2433
  }
2435
2434
 
2436
2435
  // src/compositions/AutoCaptionComposition.tsx
package/dist/index.mjs CHANGED
@@ -489,6 +489,7 @@ function TextElement({ segment, scale = 1 }) {
489
489
  borderRadius: borderRadiusStyle
490
490
  };
491
491
  }, [autoWidth, calculatedWidth, width, backgroundColor, backgroundOpacity, borderRadiusStyle]);
492
+ const hasStroke = strokeWidth > 0 && !!strokeColor;
492
493
  const textStyle = useMemo(() => ({
493
494
  fontFamily,
494
495
  fontSize,
@@ -507,20 +508,7 @@ function TextElement({ segment, scale = 1 }) {
507
508
  flex: 1,
508
509
  minHeight: 0
509
510
  },
510
- ...strokeWidth > 0 && strokeColor && {
511
- textShadow: `
512
- -${strokeWidth}px -${strokeWidth}px 0 ${strokeColor},
513
- ${strokeWidth}px -${strokeWidth}px 0 ${strokeColor},
514
- -${strokeWidth}px ${strokeWidth}px 0 ${strokeColor},
515
- ${strokeWidth}px ${strokeWidth}px 0 ${strokeColor},
516
- 0 -${strokeWidth}px 0 ${strokeColor},
517
- 0 ${strokeWidth}px 0 ${strokeColor},
518
- -${strokeWidth}px 0 0 ${strokeColor},
519
- ${strokeWidth}px 0 0 ${strokeColor}
520
- `,
521
- WebkitTextStroke: `${strokeWidth}px ${strokeColor}`,
522
- paintOrder: "stroke fill"
523
- }
511
+ ...hasStroke && { position: "relative" }
524
512
  }), [
525
513
  fontFamily,
526
514
  fontSize,
@@ -533,33 +521,52 @@ function TextElement({ segment, scale = 1 }) {
533
521
  paddingRight,
534
522
  paddingBottom,
535
523
  paddingLeft,
536
- strokeWidth,
537
- strokeColor,
538
524
  autoWidth,
539
- verticalAlign
525
+ verticalAlign,
526
+ hasStroke
540
527
  ]);
528
+ const strokeTextStyle = useMemo(() => {
529
+ if (!hasStroke) return void 0;
530
+ return {
531
+ ...textStyle,
532
+ color: strokeColor,
533
+ WebkitTextStroke: `${strokeWidth * 2}px ${strokeColor}`,
534
+ position: "absolute",
535
+ inset: 0
536
+ };
537
+ }, [hasStroke, textStyle, strokeColor, strokeWidth]);
541
538
  if (autoWidth) {
542
539
  const textContent = calculatedLines.map((line, index) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
543
540
  line,
544
541
  index < calculatedLines.length - 1 && /* @__PURE__ */ jsx("br", {})
545
542
  ] }, index));
546
543
  if (backgroundColor) {
547
- return /* @__PURE__ */ jsx("div", { style: positioningContainerStyle, children: /* @__PURE__ */ jsx(
544
+ return /* @__PURE__ */ jsx("div", { style: positioningContainerStyle, children: /* @__PURE__ */ jsxs(
548
545
  "div",
549
546
  {
550
547
  style: {
551
548
  width: calculatedWidth,
552
549
  maxWidth: width,
553
550
  backgroundColor: hexToRgba(backgroundColor, backgroundOpacity),
554
- borderRadius: borderRadiusStyle
551
+ borderRadius: borderRadiusStyle,
552
+ ...hasStroke && { position: "relative" }
555
553
  },
556
- children: /* @__PURE__ */ jsx("div", { style: textStyle, children: textContent })
554
+ children: [
555
+ strokeTextStyle && /* @__PURE__ */ jsx("div", { style: strokeTextStyle, "aria-hidden": "true", children: textContent }),
556
+ /* @__PURE__ */ jsx("div", { style: textStyle, children: textContent })
557
+ ]
557
558
  }
558
559
  ) });
559
560
  }
560
- return /* @__PURE__ */ jsx("div", { style: positioningContainerStyle, children: /* @__PURE__ */ jsx("div", { style: { width: calculatedWidth, maxWidth: width }, children: /* @__PURE__ */ jsx("div", { style: textStyle, children: textContent }) }) });
561
+ return /* @__PURE__ */ jsx("div", { style: positioningContainerStyle, children: /* @__PURE__ */ jsxs("div", { style: { width: calculatedWidth, maxWidth: width, ...hasStroke && { position: "relative" } }, children: [
562
+ strokeTextStyle && /* @__PURE__ */ jsx("div", { style: strokeTextStyle, "aria-hidden": "true", children: textContent }),
563
+ /* @__PURE__ */ jsx("div", { style: textStyle, children: textContent })
564
+ ] }) });
561
565
  }
562
- return /* @__PURE__ */ jsx("div", { style: positioningContainerStyle, children: /* @__PURE__ */ jsx("div", { style: backgroundBoxStyle, children: /* @__PURE__ */ jsx("div", { style: textStyle, children: segment.text }) }) });
566
+ return /* @__PURE__ */ jsx("div", { style: positioningContainerStyle, children: /* @__PURE__ */ jsxs("div", { style: { ...backgroundBoxStyle, ...hasStroke && { position: "relative" } }, children: [
567
+ strokeTextStyle && /* @__PURE__ */ jsx("div", { style: strokeTextStyle, "aria-hidden": "true", children: segment.text }),
568
+ /* @__PURE__ */ jsx("div", { style: textStyle, children: segment.text })
569
+ ] }) });
563
570
  }
564
571
 
565
572
  // src/components/ImageElement.tsx
@@ -1418,32 +1425,17 @@ function CaptionOverlay({ captions, style, previewTimeMs }) {
1418
1425
  borderRadius: scaledBorderRadius
1419
1426
  };
1420
1427
  const numericFontWeight = style.fontWeight === "black" ? 900 : style.fontWeight === "bold" ? 700 : 400;
1421
- const buildStrokeShadow = () => {
1422
- if (scaledStrokeWidth <= 0) return "none";
1423
- const sw = scaledStrokeWidth;
1424
- const sc = style.strokeColor;
1425
- return `
1426
- -${sw}px -${sw}px 0 ${sc},
1427
- ${sw}px -${sw}px 0 ${sc},
1428
- -${sw}px ${sw}px 0 ${sc},
1429
- ${sw}px ${sw}px 0 ${sc},
1430
- 0 -${sw}px 0 ${sc},
1431
- 0 ${sw}px 0 ${sc},
1432
- -${sw}px 0 0 ${sc},
1433
- ${sw}px 0 0 ${sc}
1434
- `;
1435
- };
1436
1428
  const textContainerStyles = {
1437
1429
  fontFamily: `"${style.fontName}", sans-serif`,
1438
1430
  fontSize: scaledFontSize,
1439
1431
  fontWeight: numericFontWeight,
1440
1432
  lineHeight: 1.2,
1441
- wordBreak: "break-word",
1442
- textShadow: buildStrokeShadow()
1433
+ wordBreak: "break-word"
1443
1434
  };
1444
- return /* @__PURE__ */ jsx6("div", { style: containerStyles, children: /* @__PURE__ */ jsx6("div", { style: textContainerStyles, children: currentPage.words.map((word, index) => {
1435
+ const hasStroke = scaledStrokeWidth > 0;
1436
+ const renderWords = ({ isStrokeLayer }) => currentPage.words.map((word, index) => {
1445
1437
  const isActive = currentMs >= word.startMs && currentMs <= word.endMs;
1446
- const color = isActive ? style.highlightColor : style.fontColor;
1438
+ const color = isStrokeLayer ? style.strokeColor : isActive ? style.highlightColor : style.fontColor;
1447
1439
  let scale = 1;
1448
1440
  if (style.enableAnimation && isActive) {
1449
1441
  const wordDuration = word.endMs - word.startMs;
@@ -1468,14 +1460,21 @@ function CaptionOverlay({ captions, style, previewTimeMs }) {
1468
1460
  color,
1469
1461
  display: "inline-block",
1470
1462
  transform: `scale(${scale})`,
1471
- transformOrigin: "center center"
1463
+ transformOrigin: "center center",
1464
+ ...isStrokeLayer && {
1465
+ WebkitTextStroke: `${scaledStrokeWidth * 2}px ${style.strokeColor}`
1466
+ }
1472
1467
  },
1473
1468
  children: word.word
1474
1469
  }
1475
1470
  ),
1476
1471
  index < currentPage.words.length - 1 && " "
1477
1472
  ] }, `${word.word}-${word.startMs}-${index}`);
1478
- }) }) });
1473
+ });
1474
+ return /* @__PURE__ */ jsx6("div", { style: containerStyles, children: /* @__PURE__ */ jsxs4("div", { style: { position: "relative" }, children: [
1475
+ hasStroke && /* @__PURE__ */ jsx6("div", { style: { ...textContainerStyles, position: "absolute", inset: 0 }, "aria-hidden": "true", children: renderWords({ isStrokeLayer: true }) }),
1476
+ /* @__PURE__ */ jsx6("div", { style: { ...textContainerStyles, ...hasStroke && { position: "relative" } }, children: renderWords({ isStrokeLayer: false }) })
1477
+ ] }) });
1479
1478
  }
1480
1479
 
1481
1480
  // src/compositions/AutoCaptionComposition.tsx
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ugcinc-render",
3
- "version": "1.8.218",
3
+ "version": "1.8.220",
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",