ugcinc-render 1.5.24 → 1.5.26
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 +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +73 -6
- package/dist/index.mjs +73 -6
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1239,9 +1239,10 @@ declare function getReferenceElementY(elements: ImageEditorElement[], elementId:
|
|
|
1239
1239
|
* @param dynamicCrop - Crop configuration
|
|
1240
1240
|
* @param canvasWidth - Original canvas width
|
|
1241
1241
|
* @param canvasHeight - Original canvas height
|
|
1242
|
+
* @param textValues - Optional map of textInputId -> text content for height calculation
|
|
1242
1243
|
* @returns CropBounds with x, y, width, height
|
|
1243
1244
|
*/
|
|
1244
|
-
declare function calculateCropBounds(elements: ImageEditorElement[], dynamicCrop: DynamicCropConfig | undefined, canvasWidth: number, canvasHeight: number): CropBounds;
|
|
1245
|
+
declare function calculateCropBounds(elements: ImageEditorElement[], dynamicCrop: DynamicCropConfig | undefined, canvasWidth: number, canvasHeight: number, textValues?: Record<string, string>): CropBounds;
|
|
1245
1246
|
/**
|
|
1246
1247
|
* Check if dynamic crop is enabled (either vertical or horizontal)
|
|
1247
1248
|
*/
|
|
@@ -1364,6 +1365,9 @@ declare function useResolvedPositions(elements: ImageEditorElement[], textValues
|
|
|
1364
1365
|
*
|
|
1365
1366
|
* This file registers all available compositions with the renderer.
|
|
1366
1367
|
* It serves as the entry point for the renderer bundler.
|
|
1368
|
+
*
|
|
1369
|
+
* Uses calculateMetadata for ImageEditorComposition to determine
|
|
1370
|
+
* dynamic crop dimensions in the browser environment (with DOM access).
|
|
1367
1371
|
*/
|
|
1368
1372
|
|
|
1369
1373
|
declare const RenderRoot: React.FC;
|
package/dist/index.d.ts
CHANGED
|
@@ -1239,9 +1239,10 @@ declare function getReferenceElementY(elements: ImageEditorElement[], elementId:
|
|
|
1239
1239
|
* @param dynamicCrop - Crop configuration
|
|
1240
1240
|
* @param canvasWidth - Original canvas width
|
|
1241
1241
|
* @param canvasHeight - Original canvas height
|
|
1242
|
+
* @param textValues - Optional map of textInputId -> text content for height calculation
|
|
1242
1243
|
* @returns CropBounds with x, y, width, height
|
|
1243
1244
|
*/
|
|
1244
|
-
declare function calculateCropBounds(elements: ImageEditorElement[], dynamicCrop: DynamicCropConfig | undefined, canvasWidth: number, canvasHeight: number): CropBounds;
|
|
1245
|
+
declare function calculateCropBounds(elements: ImageEditorElement[], dynamicCrop: DynamicCropConfig | undefined, canvasWidth: number, canvasHeight: number, textValues?: Record<string, string>): CropBounds;
|
|
1245
1246
|
/**
|
|
1246
1247
|
* Check if dynamic crop is enabled (either vertical or horizontal)
|
|
1247
1248
|
*/
|
|
@@ -1364,6 +1365,9 @@ declare function useResolvedPositions(elements: ImageEditorElement[], textValues
|
|
|
1364
1365
|
*
|
|
1365
1366
|
* This file registers all available compositions with the renderer.
|
|
1366
1367
|
* It serves as the entry point for the renderer bundler.
|
|
1368
|
+
*
|
|
1369
|
+
* Uses calculateMetadata for ImageEditorComposition to determine
|
|
1370
|
+
* dynamic crop dimensions in the browser environment (with DOM access).
|
|
1367
1371
|
*/
|
|
1368
1372
|
|
|
1369
1373
|
declare const RenderRoot: React.FC;
|
package/dist/index.js
CHANGED
|
@@ -1167,7 +1167,16 @@ function getReferenceElementY(elements, elementId) {
|
|
|
1167
1167
|
}
|
|
1168
1168
|
|
|
1169
1169
|
// src/utils/cropBounds.ts
|
|
1170
|
-
function
|
|
1170
|
+
function getActualElementHeight(elem, textValues, measureCtx) {
|
|
1171
|
+
if (elem.type !== "text") return elem.height;
|
|
1172
|
+
let textContent = elem.text ?? "Text";
|
|
1173
|
+
if (elem.textInputId && textValues?.[elem.textInputId]) {
|
|
1174
|
+
textContent = textValues[elem.textInputId];
|
|
1175
|
+
}
|
|
1176
|
+
const result = calculateAutoWidthDimensions(elem, textContent, measureCtx);
|
|
1177
|
+
return result?.actualHeight ?? elem.height;
|
|
1178
|
+
}
|
|
1179
|
+
function calculateCropBounds(elements, dynamicCrop, canvasWidth, canvasHeight, textValues) {
|
|
1171
1180
|
if (!dynamicCrop) {
|
|
1172
1181
|
return { x: 0, y: 0, width: canvasWidth, height: canvasHeight };
|
|
1173
1182
|
}
|
|
@@ -1180,6 +1189,12 @@ function calculateCropBounds(elements, dynamicCrop, canvasWidth, canvasHeight) {
|
|
|
1180
1189
|
if (boundary.elementId) return boundary.elementId;
|
|
1181
1190
|
return void 0;
|
|
1182
1191
|
};
|
|
1192
|
+
let measureCtx = null;
|
|
1193
|
+
const hasTextElements = elements.some((e) => e.type === "text");
|
|
1194
|
+
if (hasTextElements && typeof document !== "undefined") {
|
|
1195
|
+
const canvas = document.createElement("canvas");
|
|
1196
|
+
measureCtx = canvas.getContext("2d");
|
|
1197
|
+
}
|
|
1183
1198
|
let cropY = 0;
|
|
1184
1199
|
let cropHeight = canvasHeight;
|
|
1185
1200
|
if (dynamicCrop.vertical?.enabled) {
|
|
@@ -1190,8 +1205,9 @@ function calculateCropBounds(elements, dynamicCrop, canvasWidth, canvasHeight) {
|
|
|
1190
1205
|
let minY = canvasHeight;
|
|
1191
1206
|
let maxY = 0;
|
|
1192
1207
|
for (const elem of elements) {
|
|
1208
|
+
const actualHeight = getActualElementHeight(elem, textValues, measureCtx);
|
|
1193
1209
|
minY = Math.min(minY, elem.y);
|
|
1194
|
-
maxY = Math.max(maxY, elem.y +
|
|
1210
|
+
maxY = Math.max(maxY, elem.y + actualHeight);
|
|
1195
1211
|
}
|
|
1196
1212
|
if (elements.length > 0) {
|
|
1197
1213
|
cropY = Math.max(0, minY - paddingStart);
|
|
@@ -1212,7 +1228,8 @@ function calculateCropBounds(elements, dynamicCrop, canvasWidth, canvasHeight) {
|
|
|
1212
1228
|
if (endElementId) {
|
|
1213
1229
|
const endElem = elementMap.get(endElementId);
|
|
1214
1230
|
if (endElem) {
|
|
1215
|
-
|
|
1231
|
+
const actualHeight = getActualElementHeight(endElem, textValues, measureCtx);
|
|
1232
|
+
bottomY = endElem.y + actualHeight;
|
|
1216
1233
|
}
|
|
1217
1234
|
}
|
|
1218
1235
|
cropY = Math.max(0, topY - paddingStart);
|
|
@@ -1446,8 +1463,8 @@ function ImageEditorComposition({
|
|
|
1446
1463
|
}, [elements, textValues]);
|
|
1447
1464
|
const cropBounds = (0, import_react3.useMemo)(() => {
|
|
1448
1465
|
if (!isDynamicCropEnabled(dynamicCrop) || !resolvedElements) return null;
|
|
1449
|
-
return calculateCropBounds(resolvedElements, dynamicCrop, canvasWidth, canvasHeight);
|
|
1450
|
-
}, [resolvedElements, dynamicCrop, canvasWidth, canvasHeight]);
|
|
1466
|
+
return calculateCropBounds(resolvedElements, dynamicCrop, canvasWidth, canvasHeight, textValues);
|
|
1467
|
+
}, [resolvedElements, dynamicCrop, canvasWidth, canvasHeight, textValues]);
|
|
1451
1468
|
const segmentsFromElements = (0, import_react3.useMemo)(() => {
|
|
1452
1469
|
if (!resolvedElements) return null;
|
|
1453
1470
|
const segments = [];
|
|
@@ -2109,6 +2126,55 @@ var defaultVideoProps = {
|
|
|
2109
2126
|
};
|
|
2110
2127
|
var ImageComp = ImageEditorComposition;
|
|
2111
2128
|
var VideoComp = VideoEditorComposition;
|
|
2129
|
+
var calculateImageMetadata = async ({ props }) => {
|
|
2130
|
+
console.log("[calculateMetadata] Starting metadata calculation...");
|
|
2131
|
+
const canvasWidth = props.width ?? props.config?.width ?? 1080;
|
|
2132
|
+
const canvasHeight = props.height ?? props.config?.height ?? 1920;
|
|
2133
|
+
const defaultResult = {
|
|
2134
|
+
width: canvasWidth,
|
|
2135
|
+
height: canvasHeight,
|
|
2136
|
+
fps: 30,
|
|
2137
|
+
durationInFrames: 1
|
|
2138
|
+
};
|
|
2139
|
+
if (!props.elements || !props.dynamicCrop) {
|
|
2140
|
+
console.log("[calculateMetadata] No elements or dynamicCrop, using default dimensions:", canvasWidth, "x", canvasHeight);
|
|
2141
|
+
return defaultResult;
|
|
2142
|
+
}
|
|
2143
|
+
if (!isDynamicCropEnabled(props.dynamicCrop)) {
|
|
2144
|
+
console.log("[calculateMetadata] Dynamic crop not enabled, using default dimensions:", canvasWidth, "x", canvasHeight);
|
|
2145
|
+
return defaultResult;
|
|
2146
|
+
}
|
|
2147
|
+
console.log("[calculateMetadata] Dynamic crop enabled, loading fonts for accurate measurement...");
|
|
2148
|
+
try {
|
|
2149
|
+
await preloadFonts();
|
|
2150
|
+
console.log("[calculateMetadata] Fonts loaded successfully");
|
|
2151
|
+
} catch (err) {
|
|
2152
|
+
console.error("[calculateMetadata] Font loading failed:", err);
|
|
2153
|
+
}
|
|
2154
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
2155
|
+
console.log("[calculateMetadata] Resolving element positions with DOM measurement...");
|
|
2156
|
+
const { elements: resolvedElements } = resolveElementPositions(
|
|
2157
|
+
props.elements,
|
|
2158
|
+
props.textValues ?? {}
|
|
2159
|
+
);
|
|
2160
|
+
console.log("[calculateMetadata] Element positions resolved");
|
|
2161
|
+
const cropBounds = calculateCropBounds(
|
|
2162
|
+
resolvedElements,
|
|
2163
|
+
props.dynamicCrop,
|
|
2164
|
+
canvasWidth,
|
|
2165
|
+
canvasHeight,
|
|
2166
|
+
props.textValues
|
|
2167
|
+
);
|
|
2168
|
+
const outputWidth = Math.round(cropBounds.width);
|
|
2169
|
+
const outputHeight = Math.round(cropBounds.height);
|
|
2170
|
+
console.log(`[calculateMetadata] Crop bounds calculated: ${canvasWidth}x${canvasHeight} -> ${outputWidth}x${outputHeight} (offset: ${cropBounds.x}, ${cropBounds.y})`);
|
|
2171
|
+
return {
|
|
2172
|
+
width: outputWidth,
|
|
2173
|
+
height: outputHeight,
|
|
2174
|
+
fps: 30,
|
|
2175
|
+
durationInFrames: 1
|
|
2176
|
+
};
|
|
2177
|
+
};
|
|
2112
2178
|
var RenderRoot = () => {
|
|
2113
2179
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
2114
2180
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
@@ -2116,8 +2182,9 @@ var RenderRoot = () => {
|
|
|
2116
2182
|
{
|
|
2117
2183
|
id: "ImageEditorComposition",
|
|
2118
2184
|
component: ImageComp,
|
|
2185
|
+
calculateMetadata: calculateImageMetadata,
|
|
2119
2186
|
durationInFrames: 1,
|
|
2120
|
-
fps:
|
|
2187
|
+
fps: 30,
|
|
2121
2188
|
width: 1080,
|
|
2122
2189
|
height: 1920,
|
|
2123
2190
|
defaultProps: defaultImageProps
|
package/dist/index.mjs
CHANGED
|
@@ -1081,7 +1081,16 @@ function getReferenceElementY(elements, elementId) {
|
|
|
1081
1081
|
}
|
|
1082
1082
|
|
|
1083
1083
|
// src/utils/cropBounds.ts
|
|
1084
|
-
function
|
|
1084
|
+
function getActualElementHeight(elem, textValues, measureCtx) {
|
|
1085
|
+
if (elem.type !== "text") return elem.height;
|
|
1086
|
+
let textContent = elem.text ?? "Text";
|
|
1087
|
+
if (elem.textInputId && textValues?.[elem.textInputId]) {
|
|
1088
|
+
textContent = textValues[elem.textInputId];
|
|
1089
|
+
}
|
|
1090
|
+
const result = calculateAutoWidthDimensions(elem, textContent, measureCtx);
|
|
1091
|
+
return result?.actualHeight ?? elem.height;
|
|
1092
|
+
}
|
|
1093
|
+
function calculateCropBounds(elements, dynamicCrop, canvasWidth, canvasHeight, textValues) {
|
|
1085
1094
|
if (!dynamicCrop) {
|
|
1086
1095
|
return { x: 0, y: 0, width: canvasWidth, height: canvasHeight };
|
|
1087
1096
|
}
|
|
@@ -1094,6 +1103,12 @@ function calculateCropBounds(elements, dynamicCrop, canvasWidth, canvasHeight) {
|
|
|
1094
1103
|
if (boundary.elementId) return boundary.elementId;
|
|
1095
1104
|
return void 0;
|
|
1096
1105
|
};
|
|
1106
|
+
let measureCtx = null;
|
|
1107
|
+
const hasTextElements = elements.some((e) => e.type === "text");
|
|
1108
|
+
if (hasTextElements && typeof document !== "undefined") {
|
|
1109
|
+
const canvas = document.createElement("canvas");
|
|
1110
|
+
measureCtx = canvas.getContext("2d");
|
|
1111
|
+
}
|
|
1097
1112
|
let cropY = 0;
|
|
1098
1113
|
let cropHeight = canvasHeight;
|
|
1099
1114
|
if (dynamicCrop.vertical?.enabled) {
|
|
@@ -1104,8 +1119,9 @@ function calculateCropBounds(elements, dynamicCrop, canvasWidth, canvasHeight) {
|
|
|
1104
1119
|
let minY = canvasHeight;
|
|
1105
1120
|
let maxY = 0;
|
|
1106
1121
|
for (const elem of elements) {
|
|
1122
|
+
const actualHeight = getActualElementHeight(elem, textValues, measureCtx);
|
|
1107
1123
|
minY = Math.min(minY, elem.y);
|
|
1108
|
-
maxY = Math.max(maxY, elem.y +
|
|
1124
|
+
maxY = Math.max(maxY, elem.y + actualHeight);
|
|
1109
1125
|
}
|
|
1110
1126
|
if (elements.length > 0) {
|
|
1111
1127
|
cropY = Math.max(0, minY - paddingStart);
|
|
@@ -1126,7 +1142,8 @@ function calculateCropBounds(elements, dynamicCrop, canvasWidth, canvasHeight) {
|
|
|
1126
1142
|
if (endElementId) {
|
|
1127
1143
|
const endElem = elementMap.get(endElementId);
|
|
1128
1144
|
if (endElem) {
|
|
1129
|
-
|
|
1145
|
+
const actualHeight = getActualElementHeight(endElem, textValues, measureCtx);
|
|
1146
|
+
bottomY = endElem.y + actualHeight;
|
|
1130
1147
|
}
|
|
1131
1148
|
}
|
|
1132
1149
|
cropY = Math.max(0, topY - paddingStart);
|
|
@@ -1360,8 +1377,8 @@ function ImageEditorComposition({
|
|
|
1360
1377
|
}, [elements, textValues]);
|
|
1361
1378
|
const cropBounds = useMemo3(() => {
|
|
1362
1379
|
if (!isDynamicCropEnabled(dynamicCrop) || !resolvedElements) return null;
|
|
1363
|
-
return calculateCropBounds(resolvedElements, dynamicCrop, canvasWidth, canvasHeight);
|
|
1364
|
-
}, [resolvedElements, dynamicCrop, canvasWidth, canvasHeight]);
|
|
1380
|
+
return calculateCropBounds(resolvedElements, dynamicCrop, canvasWidth, canvasHeight, textValues);
|
|
1381
|
+
}, [resolvedElements, dynamicCrop, canvasWidth, canvasHeight, textValues]);
|
|
1365
1382
|
const segmentsFromElements = useMemo3(() => {
|
|
1366
1383
|
if (!resolvedElements) return null;
|
|
1367
1384
|
const segments = [];
|
|
@@ -2023,6 +2040,55 @@ var defaultVideoProps = {
|
|
|
2023
2040
|
};
|
|
2024
2041
|
var ImageComp = ImageEditorComposition;
|
|
2025
2042
|
var VideoComp = VideoEditorComposition;
|
|
2043
|
+
var calculateImageMetadata = async ({ props }) => {
|
|
2044
|
+
console.log("[calculateMetadata] Starting metadata calculation...");
|
|
2045
|
+
const canvasWidth = props.width ?? props.config?.width ?? 1080;
|
|
2046
|
+
const canvasHeight = props.height ?? props.config?.height ?? 1920;
|
|
2047
|
+
const defaultResult = {
|
|
2048
|
+
width: canvasWidth,
|
|
2049
|
+
height: canvasHeight,
|
|
2050
|
+
fps: 30,
|
|
2051
|
+
durationInFrames: 1
|
|
2052
|
+
};
|
|
2053
|
+
if (!props.elements || !props.dynamicCrop) {
|
|
2054
|
+
console.log("[calculateMetadata] No elements or dynamicCrop, using default dimensions:", canvasWidth, "x", canvasHeight);
|
|
2055
|
+
return defaultResult;
|
|
2056
|
+
}
|
|
2057
|
+
if (!isDynamicCropEnabled(props.dynamicCrop)) {
|
|
2058
|
+
console.log("[calculateMetadata] Dynamic crop not enabled, using default dimensions:", canvasWidth, "x", canvasHeight);
|
|
2059
|
+
return defaultResult;
|
|
2060
|
+
}
|
|
2061
|
+
console.log("[calculateMetadata] Dynamic crop enabled, loading fonts for accurate measurement...");
|
|
2062
|
+
try {
|
|
2063
|
+
await preloadFonts();
|
|
2064
|
+
console.log("[calculateMetadata] Fonts loaded successfully");
|
|
2065
|
+
} catch (err) {
|
|
2066
|
+
console.error("[calculateMetadata] Font loading failed:", err);
|
|
2067
|
+
}
|
|
2068
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
2069
|
+
console.log("[calculateMetadata] Resolving element positions with DOM measurement...");
|
|
2070
|
+
const { elements: resolvedElements } = resolveElementPositions(
|
|
2071
|
+
props.elements,
|
|
2072
|
+
props.textValues ?? {}
|
|
2073
|
+
);
|
|
2074
|
+
console.log("[calculateMetadata] Element positions resolved");
|
|
2075
|
+
const cropBounds = calculateCropBounds(
|
|
2076
|
+
resolvedElements,
|
|
2077
|
+
props.dynamicCrop,
|
|
2078
|
+
canvasWidth,
|
|
2079
|
+
canvasHeight,
|
|
2080
|
+
props.textValues
|
|
2081
|
+
);
|
|
2082
|
+
const outputWidth = Math.round(cropBounds.width);
|
|
2083
|
+
const outputHeight = Math.round(cropBounds.height);
|
|
2084
|
+
console.log(`[calculateMetadata] Crop bounds calculated: ${canvasWidth}x${canvasHeight} -> ${outputWidth}x${outputHeight} (offset: ${cropBounds.x}, ${cropBounds.y})`);
|
|
2085
|
+
return {
|
|
2086
|
+
width: outputWidth,
|
|
2087
|
+
height: outputHeight,
|
|
2088
|
+
fps: 30,
|
|
2089
|
+
durationInFrames: 1
|
|
2090
|
+
};
|
|
2091
|
+
};
|
|
2026
2092
|
var RenderRoot = () => {
|
|
2027
2093
|
return /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
2028
2094
|
/* @__PURE__ */ jsx6(
|
|
@@ -2030,8 +2096,9 @@ var RenderRoot = () => {
|
|
|
2030
2096
|
{
|
|
2031
2097
|
id: "ImageEditorComposition",
|
|
2032
2098
|
component: ImageComp,
|
|
2099
|
+
calculateMetadata: calculateImageMetadata,
|
|
2033
2100
|
durationInFrames: 1,
|
|
2034
|
-
fps:
|
|
2101
|
+
fps: 30,
|
|
2035
2102
|
width: 1080,
|
|
2036
2103
|
height: 1920,
|
|
2037
2104
|
defaultProps: defaultImageProps
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ugcinc-render",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.26",
|
|
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",
|