ugcinc-render 1.5.2 → 1.5.4
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 +88 -20
- package/dist/index.mjs +95 -27
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -302,28 +302,70 @@ function calculateAutoWidth({
|
|
|
302
302
|
fontSize,
|
|
303
303
|
fontWeight,
|
|
304
304
|
fontFamily,
|
|
305
|
-
letterSpacing
|
|
305
|
+
letterSpacing,
|
|
306
|
+
lineHeight
|
|
306
307
|
}) {
|
|
307
308
|
if (typeof document === "undefined") {
|
|
308
309
|
throw new Error("calculateAutoWidth requires a browser environment with document available");
|
|
309
310
|
}
|
|
310
|
-
const
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
311
|
+
const container = document.createElement("div");
|
|
312
|
+
container.style.cssText = `
|
|
313
|
+
position: absolute;
|
|
314
|
+
visibility: hidden;
|
|
315
|
+
pointer-events: none;
|
|
316
|
+
width: ${maxWidth}px;
|
|
317
|
+
padding: 0 ${paddingRight}px 0 ${paddingLeft}px;
|
|
318
|
+
box-sizing: border-box;
|
|
319
|
+
font-family: ${fontFamily};
|
|
320
|
+
font-size: ${fontSize}px;
|
|
321
|
+
font-weight: ${fontWeight};
|
|
322
|
+
letter-spacing: ${letterSpacing}px;
|
|
323
|
+
line-height: ${lineHeight};
|
|
324
|
+
white-space: pre-wrap;
|
|
325
|
+
word-break: break-word;
|
|
326
|
+
`;
|
|
327
|
+
container.textContent = text;
|
|
328
|
+
document.body.appendChild(container);
|
|
329
|
+
const totalHeight = container.offsetHeight;
|
|
330
|
+
const lineHeightPx = fontSize * lineHeight;
|
|
331
|
+
const numLines = Math.max(1, Math.round(totalHeight / lineHeightPx));
|
|
332
|
+
if (numLines === 1) {
|
|
333
|
+
const span = document.createElement("span");
|
|
334
|
+
span.style.cssText = `
|
|
335
|
+
font-family: ${fontFamily};
|
|
336
|
+
font-size: ${fontSize}px;
|
|
337
|
+
font-weight: ${fontWeight};
|
|
338
|
+
letter-spacing: ${letterSpacing}px;
|
|
339
|
+
white-space: nowrap;
|
|
340
|
+
`;
|
|
341
|
+
span.textContent = text;
|
|
342
|
+
document.body.appendChild(span);
|
|
343
|
+
const textWidth = span.offsetWidth;
|
|
344
|
+
document.body.removeChild(span);
|
|
345
|
+
document.body.removeChild(container);
|
|
346
|
+
return Math.min(textWidth + paddingLeft + paddingRight, maxWidth);
|
|
314
347
|
}
|
|
315
|
-
ctx.font = `${fontWeight} ${fontSize}px ${fontFamily}`;
|
|
316
|
-
const availableWidth = maxWidth - paddingLeft - paddingRight;
|
|
317
348
|
const words = text.split(" ");
|
|
318
349
|
const lines = [];
|
|
319
350
|
let currentLine = "";
|
|
351
|
+
const measureSpan = document.createElement("span");
|
|
352
|
+
measureSpan.style.cssText = `
|
|
353
|
+
position: absolute;
|
|
354
|
+
visibility: hidden;
|
|
355
|
+
font-family: ${fontFamily};
|
|
356
|
+
font-size: ${fontSize}px;
|
|
357
|
+
font-weight: ${fontWeight};
|
|
358
|
+
letter-spacing: ${letterSpacing}px;
|
|
359
|
+
white-space: nowrap;
|
|
360
|
+
`;
|
|
361
|
+
document.body.appendChild(measureSpan);
|
|
362
|
+
const availableWidth = maxWidth - paddingLeft - paddingRight;
|
|
320
363
|
for (const word of words) {
|
|
321
364
|
if (!word) continue;
|
|
322
365
|
const testLine = currentLine + (currentLine ? " " : "") + word;
|
|
323
|
-
|
|
324
|
-
const
|
|
325
|
-
|
|
326
|
-
if (totalWidth > availableWidth && currentLine) {
|
|
366
|
+
measureSpan.textContent = testLine;
|
|
367
|
+
const testWidth = measureSpan.offsetWidth;
|
|
368
|
+
if (testWidth > availableWidth && currentLine) {
|
|
327
369
|
lines.push(currentLine);
|
|
328
370
|
currentLine = word;
|
|
329
371
|
} else {
|
|
@@ -333,14 +375,11 @@ function calculateAutoWidth({
|
|
|
333
375
|
if (currentLine) lines.push(currentLine);
|
|
334
376
|
let widestLineWidth = 0;
|
|
335
377
|
for (const line of lines) {
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
for (const char of chars) {
|
|
339
|
-
lineWidth += ctx.measureText(char).width + letterSpacing;
|
|
340
|
-
}
|
|
341
|
-
if (chars.length > 0) lineWidth -= letterSpacing;
|
|
342
|
-
widestLineWidth = Math.max(widestLineWidth, lineWidth);
|
|
378
|
+
measureSpan.textContent = line;
|
|
379
|
+
widestLineWidth = Math.max(widestLineWidth, measureSpan.offsetWidth);
|
|
343
380
|
}
|
|
381
|
+
document.body.removeChild(measureSpan);
|
|
382
|
+
document.body.removeChild(container);
|
|
344
383
|
return Math.min(widestLineWidth + paddingLeft + paddingRight, maxWidth);
|
|
345
384
|
}
|
|
346
385
|
function TextElement({ segment, scale = 1 }) {
|
|
@@ -380,9 +419,10 @@ function TextElement({ segment, scale = 1 }) {
|
|
|
380
419
|
fontSize,
|
|
381
420
|
fontWeight,
|
|
382
421
|
fontFamily,
|
|
383
|
-
letterSpacing
|
|
422
|
+
letterSpacing,
|
|
423
|
+
lineHeight
|
|
384
424
|
});
|
|
385
|
-
}, [autoWidth, segment.text, width, paddingLeft, paddingRight, fontSize, fontWeight, fontFamily, letterSpacing]);
|
|
425
|
+
}, [autoWidth, segment.text, width, paddingLeft, paddingRight, fontSize, fontWeight, fontFamily, letterSpacing, lineHeight]);
|
|
386
426
|
const borderRadiusStyle = (0, import_react.useMemo)(() => {
|
|
387
427
|
if (!backgroundBorderRadius) return void 0;
|
|
388
428
|
const radii = getBorderRadii(backgroundBorderRadius);
|
|
@@ -477,6 +517,34 @@ function TextElement({ segment, scale = 1 }) {
|
|
|
477
517
|
autoWidth,
|
|
478
518
|
verticalAlign
|
|
479
519
|
]);
|
|
520
|
+
if (autoWidth && backgroundColor) {
|
|
521
|
+
const bgOffsetX = boxAlign === "center" ? (width - calculatedWidth) / 2 : boxAlign === "right" ? width - calculatedWidth : 0;
|
|
522
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: positioningContainerStyle, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { position: "relative", width }, children: [
|
|
523
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
524
|
+
"div",
|
|
525
|
+
{
|
|
526
|
+
style: {
|
|
527
|
+
position: "absolute",
|
|
528
|
+
left: bgOffsetX,
|
|
529
|
+
top: 0,
|
|
530
|
+
width: calculatedWidth,
|
|
531
|
+
height: "100%",
|
|
532
|
+
backgroundColor: hexToRgba(backgroundColor, backgroundOpacity),
|
|
533
|
+
borderRadius: borderRadiusStyle,
|
|
534
|
+
pointerEvents: "none"
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
),
|
|
538
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: textStyle, children: segment.text })
|
|
539
|
+
] }) });
|
|
540
|
+
}
|
|
541
|
+
if (autoWidth) {
|
|
542
|
+
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: {
|
|
543
|
+
...textStyle,
|
|
544
|
+
width,
|
|
545
|
+
boxSizing: "border-box"
|
|
546
|
+
}, children: segment.text }) }) });
|
|
547
|
+
}
|
|
480
548
|
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 }) }) });
|
|
481
549
|
}
|
|
482
550
|
|
package/dist/index.mjs
CHANGED
|
@@ -219,7 +219,7 @@ function hexToRgba(hex, opacity = 100) {
|
|
|
219
219
|
}
|
|
220
220
|
|
|
221
221
|
// src/components/TextElement.tsx
|
|
222
|
-
import { jsx } from "react/jsx-runtime";
|
|
222
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
223
223
|
function calculateAutoWidth({
|
|
224
224
|
text,
|
|
225
225
|
maxWidth,
|
|
@@ -228,28 +228,70 @@ function calculateAutoWidth({
|
|
|
228
228
|
fontSize,
|
|
229
229
|
fontWeight,
|
|
230
230
|
fontFamily,
|
|
231
|
-
letterSpacing
|
|
231
|
+
letterSpacing,
|
|
232
|
+
lineHeight
|
|
232
233
|
}) {
|
|
233
234
|
if (typeof document === "undefined") {
|
|
234
235
|
throw new Error("calculateAutoWidth requires a browser environment with document available");
|
|
235
236
|
}
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
237
|
+
const container = document.createElement("div");
|
|
238
|
+
container.style.cssText = `
|
|
239
|
+
position: absolute;
|
|
240
|
+
visibility: hidden;
|
|
241
|
+
pointer-events: none;
|
|
242
|
+
width: ${maxWidth}px;
|
|
243
|
+
padding: 0 ${paddingRight}px 0 ${paddingLeft}px;
|
|
244
|
+
box-sizing: border-box;
|
|
245
|
+
font-family: ${fontFamily};
|
|
246
|
+
font-size: ${fontSize}px;
|
|
247
|
+
font-weight: ${fontWeight};
|
|
248
|
+
letter-spacing: ${letterSpacing}px;
|
|
249
|
+
line-height: ${lineHeight};
|
|
250
|
+
white-space: pre-wrap;
|
|
251
|
+
word-break: break-word;
|
|
252
|
+
`;
|
|
253
|
+
container.textContent = text;
|
|
254
|
+
document.body.appendChild(container);
|
|
255
|
+
const totalHeight = container.offsetHeight;
|
|
256
|
+
const lineHeightPx = fontSize * lineHeight;
|
|
257
|
+
const numLines = Math.max(1, Math.round(totalHeight / lineHeightPx));
|
|
258
|
+
if (numLines === 1) {
|
|
259
|
+
const span = document.createElement("span");
|
|
260
|
+
span.style.cssText = `
|
|
261
|
+
font-family: ${fontFamily};
|
|
262
|
+
font-size: ${fontSize}px;
|
|
263
|
+
font-weight: ${fontWeight};
|
|
264
|
+
letter-spacing: ${letterSpacing}px;
|
|
265
|
+
white-space: nowrap;
|
|
266
|
+
`;
|
|
267
|
+
span.textContent = text;
|
|
268
|
+
document.body.appendChild(span);
|
|
269
|
+
const textWidth = span.offsetWidth;
|
|
270
|
+
document.body.removeChild(span);
|
|
271
|
+
document.body.removeChild(container);
|
|
272
|
+
return Math.min(textWidth + paddingLeft + paddingRight, maxWidth);
|
|
240
273
|
}
|
|
241
|
-
ctx.font = `${fontWeight} ${fontSize}px ${fontFamily}`;
|
|
242
|
-
const availableWidth = maxWidth - paddingLeft - paddingRight;
|
|
243
274
|
const words = text.split(" ");
|
|
244
275
|
const lines = [];
|
|
245
276
|
let currentLine = "";
|
|
277
|
+
const measureSpan = document.createElement("span");
|
|
278
|
+
measureSpan.style.cssText = `
|
|
279
|
+
position: absolute;
|
|
280
|
+
visibility: hidden;
|
|
281
|
+
font-family: ${fontFamily};
|
|
282
|
+
font-size: ${fontSize}px;
|
|
283
|
+
font-weight: ${fontWeight};
|
|
284
|
+
letter-spacing: ${letterSpacing}px;
|
|
285
|
+
white-space: nowrap;
|
|
286
|
+
`;
|
|
287
|
+
document.body.appendChild(measureSpan);
|
|
288
|
+
const availableWidth = maxWidth - paddingLeft - paddingRight;
|
|
246
289
|
for (const word of words) {
|
|
247
290
|
if (!word) continue;
|
|
248
291
|
const testLine = currentLine + (currentLine ? " " : "") + word;
|
|
249
|
-
|
|
250
|
-
const
|
|
251
|
-
|
|
252
|
-
if (totalWidth > availableWidth && currentLine) {
|
|
292
|
+
measureSpan.textContent = testLine;
|
|
293
|
+
const testWidth = measureSpan.offsetWidth;
|
|
294
|
+
if (testWidth > availableWidth && currentLine) {
|
|
253
295
|
lines.push(currentLine);
|
|
254
296
|
currentLine = word;
|
|
255
297
|
} else {
|
|
@@ -259,14 +301,11 @@ function calculateAutoWidth({
|
|
|
259
301
|
if (currentLine) lines.push(currentLine);
|
|
260
302
|
let widestLineWidth = 0;
|
|
261
303
|
for (const line of lines) {
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
for (const char of chars) {
|
|
265
|
-
lineWidth += ctx.measureText(char).width + letterSpacing;
|
|
266
|
-
}
|
|
267
|
-
if (chars.length > 0) lineWidth -= letterSpacing;
|
|
268
|
-
widestLineWidth = Math.max(widestLineWidth, lineWidth);
|
|
304
|
+
measureSpan.textContent = line;
|
|
305
|
+
widestLineWidth = Math.max(widestLineWidth, measureSpan.offsetWidth);
|
|
269
306
|
}
|
|
307
|
+
document.body.removeChild(measureSpan);
|
|
308
|
+
document.body.removeChild(container);
|
|
270
309
|
return Math.min(widestLineWidth + paddingLeft + paddingRight, maxWidth);
|
|
271
310
|
}
|
|
272
311
|
function TextElement({ segment, scale = 1 }) {
|
|
@@ -306,9 +345,10 @@ function TextElement({ segment, scale = 1 }) {
|
|
|
306
345
|
fontSize,
|
|
307
346
|
fontWeight,
|
|
308
347
|
fontFamily,
|
|
309
|
-
letterSpacing
|
|
348
|
+
letterSpacing,
|
|
349
|
+
lineHeight
|
|
310
350
|
});
|
|
311
|
-
}, [autoWidth, segment.text, width, paddingLeft, paddingRight, fontSize, fontWeight, fontFamily, letterSpacing]);
|
|
351
|
+
}, [autoWidth, segment.text, width, paddingLeft, paddingRight, fontSize, fontWeight, fontFamily, letterSpacing, lineHeight]);
|
|
312
352
|
const borderRadiusStyle = useMemo(() => {
|
|
313
353
|
if (!backgroundBorderRadius) return void 0;
|
|
314
354
|
const radii = getBorderRadii(backgroundBorderRadius);
|
|
@@ -403,6 +443,34 @@ function TextElement({ segment, scale = 1 }) {
|
|
|
403
443
|
autoWidth,
|
|
404
444
|
verticalAlign
|
|
405
445
|
]);
|
|
446
|
+
if (autoWidth && backgroundColor) {
|
|
447
|
+
const bgOffsetX = boxAlign === "center" ? (width - calculatedWidth) / 2 : boxAlign === "right" ? width - calculatedWidth : 0;
|
|
448
|
+
return /* @__PURE__ */ jsx("div", { style: positioningContainerStyle, children: /* @__PURE__ */ jsxs("div", { style: { position: "relative", width }, children: [
|
|
449
|
+
/* @__PURE__ */ jsx(
|
|
450
|
+
"div",
|
|
451
|
+
{
|
|
452
|
+
style: {
|
|
453
|
+
position: "absolute",
|
|
454
|
+
left: bgOffsetX,
|
|
455
|
+
top: 0,
|
|
456
|
+
width: calculatedWidth,
|
|
457
|
+
height: "100%",
|
|
458
|
+
backgroundColor: hexToRgba(backgroundColor, backgroundOpacity),
|
|
459
|
+
borderRadius: borderRadiusStyle,
|
|
460
|
+
pointerEvents: "none"
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
),
|
|
464
|
+
/* @__PURE__ */ jsx("div", { style: textStyle, children: segment.text })
|
|
465
|
+
] }) });
|
|
466
|
+
}
|
|
467
|
+
if (autoWidth) {
|
|
468
|
+
return /* @__PURE__ */ jsx("div", { style: positioningContainerStyle, children: /* @__PURE__ */ jsx("div", { style: { width: calculatedWidth, maxWidth: width }, children: /* @__PURE__ */ jsx("div", { style: {
|
|
469
|
+
...textStyle,
|
|
470
|
+
width,
|
|
471
|
+
boxSizing: "border-box"
|
|
472
|
+
}, children: segment.text }) }) });
|
|
473
|
+
}
|
|
406
474
|
return /* @__PURE__ */ jsx("div", { style: positioningContainerStyle, children: /* @__PURE__ */ jsx("div", { style: backgroundBoxStyle, children: /* @__PURE__ */ jsx("div", { style: textStyle, children: segment.text }) }) });
|
|
407
475
|
}
|
|
408
476
|
|
|
@@ -910,7 +978,7 @@ function isDynamicCropEnabled(dynamicCrop) {
|
|
|
910
978
|
}
|
|
911
979
|
|
|
912
980
|
// src/compositions/ImageEditorComposition.tsx
|
|
913
|
-
import { jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
981
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
914
982
|
function getSortedSegments(config) {
|
|
915
983
|
const allSegments = [];
|
|
916
984
|
for (const channel of config.channels) {
|
|
@@ -1046,7 +1114,7 @@ function ImageEditorComposition({
|
|
|
1046
1114
|
return void 0;
|
|
1047
1115
|
};
|
|
1048
1116
|
const containerBgColor = backgroundType === "color" && backgroundColor ? backgroundColor : "#000000";
|
|
1049
|
-
return /* @__PURE__ */ jsx3(AbsoluteFill, { style: { backgroundColor: containerBgColor }, children: /* @__PURE__ */
|
|
1117
|
+
return /* @__PURE__ */ jsx3(AbsoluteFill, { style: { backgroundColor: containerBgColor }, children: /* @__PURE__ */ jsxs2(
|
|
1050
1118
|
"div",
|
|
1051
1119
|
{
|
|
1052
1120
|
style: {
|
|
@@ -1220,7 +1288,7 @@ function VideoElement({
|
|
|
1220
1288
|
}
|
|
1221
1289
|
|
|
1222
1290
|
// src/compositions/VideoEditorComposition.tsx
|
|
1223
|
-
import { jsx as jsx5, jsxs as
|
|
1291
|
+
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1224
1292
|
function calculateSegmentTimings(config, fps) {
|
|
1225
1293
|
const timings = [];
|
|
1226
1294
|
const timingsMap = /* @__PURE__ */ new Map();
|
|
@@ -1324,7 +1392,7 @@ function VideoEditorComposition({
|
|
|
1324
1392
|
const audioTimings = useMemo5(() => {
|
|
1325
1393
|
return segmentTimings.filter(({ segment }) => segment.type === "audio");
|
|
1326
1394
|
}, [segmentTimings]);
|
|
1327
|
-
return /* @__PURE__ */
|
|
1395
|
+
return /* @__PURE__ */ jsxs3(AbsoluteFill2, { style: { backgroundColor: "#000000" }, children: [
|
|
1328
1396
|
activeVisualSegments.map(({ segment, startFrame, durationInFrames: durationInFrames2 }) => {
|
|
1329
1397
|
if (segment.type === "text") {
|
|
1330
1398
|
const textSegment = segment;
|
|
@@ -1640,7 +1708,7 @@ function useResolvedPositions(elements, textValues) {
|
|
|
1640
1708
|
|
|
1641
1709
|
// src/Root.tsx
|
|
1642
1710
|
import { Composition } from "remotion";
|
|
1643
|
-
import { Fragment, jsx as jsx6, jsxs as
|
|
1711
|
+
import { Fragment, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1644
1712
|
var defaultImageProps = {
|
|
1645
1713
|
config: {
|
|
1646
1714
|
width: 1080,
|
|
@@ -1664,7 +1732,7 @@ var defaultVideoProps = {
|
|
|
1664
1732
|
var ImageComp = ImageEditorComposition;
|
|
1665
1733
|
var VideoComp = VideoEditorComposition;
|
|
1666
1734
|
var RenderRoot = () => {
|
|
1667
|
-
return /* @__PURE__ */
|
|
1735
|
+
return /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
1668
1736
|
/* @__PURE__ */ jsx6(
|
|
1669
1737
|
Composition,
|
|
1670
1738
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ugcinc-render",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.4",
|
|
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",
|