ugcinc-render 1.5.23 → 1.5.25
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 +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +66 -32
- package/dist/index.mjs +66 -32
- 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
|
*/
|
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
|
*/
|
package/dist/index.js
CHANGED
|
@@ -944,38 +944,40 @@ function topologicalSortForAxis(elements, axis) {
|
|
|
944
944
|
}
|
|
945
945
|
return { sorted, errors };
|
|
946
946
|
}
|
|
947
|
-
function getSelfAnchorOffsetX(element, selfAnchor) {
|
|
947
|
+
function getSelfAnchorOffsetX(element, selfAnchor, actualWidth) {
|
|
948
|
+
const width = actualWidth ?? element.width;
|
|
948
949
|
switch (selfAnchor) {
|
|
949
950
|
case "left":
|
|
950
951
|
return 0;
|
|
951
952
|
case "center":
|
|
952
|
-
return
|
|
953
|
+
return width / 2;
|
|
953
954
|
case "right":
|
|
954
|
-
return
|
|
955
|
+
return width;
|
|
955
956
|
default:
|
|
956
957
|
return 0;
|
|
957
958
|
}
|
|
958
959
|
}
|
|
959
|
-
function getSelfAnchorOffsetY(element, selfAnchor) {
|
|
960
|
+
function getSelfAnchorOffsetY(element, selfAnchor, actualHeight) {
|
|
961
|
+
const height = actualHeight ?? element.height;
|
|
960
962
|
switch (selfAnchor) {
|
|
961
963
|
case "top":
|
|
962
964
|
return 0;
|
|
963
965
|
case "middle":
|
|
964
|
-
return
|
|
966
|
+
return height / 2;
|
|
965
967
|
case "bottom":
|
|
966
|
-
return
|
|
968
|
+
return height;
|
|
967
969
|
default:
|
|
968
970
|
return 0;
|
|
969
971
|
}
|
|
970
972
|
}
|
|
971
|
-
function calculateAbsoluteX(element, referenceElement, anchor, selfAnchor, offset) {
|
|
973
|
+
function calculateAbsoluteX(element, referenceElement, anchor, selfAnchor, offset, actualWidth) {
|
|
972
974
|
const refX = anchor === "left" ? referenceElement.x : referenceElement.x + referenceElement.width;
|
|
973
|
-
const selfOffset = getSelfAnchorOffsetX(element, selfAnchor);
|
|
975
|
+
const selfOffset = getSelfAnchorOffsetX(element, selfAnchor, actualWidth);
|
|
974
976
|
return refX + offset - selfOffset;
|
|
975
977
|
}
|
|
976
|
-
function calculateAbsoluteY(element, referenceElement, anchor, selfAnchor, offset) {
|
|
978
|
+
function calculateAbsoluteY(element, referenceElement, anchor, selfAnchor, offset, actualHeight) {
|
|
977
979
|
const refY = anchor === "top" ? referenceElement.y : referenceElement.y + referenceElement.height;
|
|
978
|
-
const selfOffset = getSelfAnchorOffsetY(element, selfAnchor);
|
|
980
|
+
const selfOffset = getSelfAnchorOffsetY(element, selfAnchor, actualHeight);
|
|
979
981
|
return refY + offset - selfOffset;
|
|
980
982
|
}
|
|
981
983
|
function resolveElementPositions(elements, textValues) {
|
|
@@ -1033,26 +1035,37 @@ function resolveElementPositions(elements, textValues) {
|
|
|
1033
1035
|
if (refPosition) {
|
|
1034
1036
|
const defaultSelfAnchor = elem.relativePositionX.anchor === "right" ? "left" : "right";
|
|
1035
1037
|
const selfAnchor = elem.relativePositionX.selfAnchor ?? defaultSelfAnchor;
|
|
1038
|
+
let actualWidth;
|
|
1039
|
+
let autoResult = null;
|
|
1040
|
+
if (elem.type === "text") {
|
|
1041
|
+
const textContent = getTextContent(elem);
|
|
1042
|
+
autoResult = calculateAutoWidthDimensions(elem, textContent, measureCtx);
|
|
1043
|
+
if (autoResult && elem.autoWidth) {
|
|
1044
|
+
actualWidth = autoResult.actualWidth;
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1036
1047
|
const newX = calculateAbsoluteX(
|
|
1037
1048
|
elem,
|
|
1038
1049
|
refPosition,
|
|
1039
1050
|
elem.relativePositionX.anchor,
|
|
1040
1051
|
selfAnchor,
|
|
1041
|
-
elem.relativePositionX.offset
|
|
1052
|
+
elem.relativePositionX.offset,
|
|
1053
|
+
actualWidth
|
|
1054
|
+
// Use actual width for self anchor calculation
|
|
1042
1055
|
);
|
|
1043
1056
|
resolvedX.set(elem.id, { x: newX, width: elem.width });
|
|
1044
|
-
if (
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1057
|
+
if (autoResult) {
|
|
1058
|
+
if (elem.autoWidth) {
|
|
1059
|
+
const updatedResult = calculateAutoWidthDimensions({ ...elem, x: newX }, getTextContent(elem), measureCtx);
|
|
1060
|
+
if (updatedResult) {
|
|
1061
|
+
referenceX.set(elem.id, { x: updatedResult.actualX, width: updatedResult.actualWidth });
|
|
1062
|
+
referenceY.set(elem.id, { y: referenceY.get(elem.id)?.y ?? elem.y, height: updatedResult.actualHeight });
|
|
1050
1063
|
} else {
|
|
1051
1064
|
referenceX.set(elem.id, { x: newX, width: elem.width });
|
|
1052
1065
|
}
|
|
1053
|
-
referenceY.set(elem.id, { y: referenceY.get(elem.id)?.y ?? elem.y, height: autoResult.actualHeight });
|
|
1054
1066
|
} else {
|
|
1055
1067
|
referenceX.set(elem.id, { x: newX, width: elem.width });
|
|
1068
|
+
referenceY.set(elem.id, { y: referenceY.get(elem.id)?.y ?? elem.y, height: autoResult.actualHeight });
|
|
1056
1069
|
}
|
|
1057
1070
|
} else {
|
|
1058
1071
|
referenceX.set(elem.id, { x: newX, width: elem.width });
|
|
@@ -1067,22 +1080,26 @@ function resolveElementPositions(elements, textValues) {
|
|
|
1067
1080
|
if (refPosition) {
|
|
1068
1081
|
const defaultSelfAnchor = elem.relativePositionY.anchor === "bottom" ? "top" : "bottom";
|
|
1069
1082
|
const selfAnchor = elem.relativePositionY.selfAnchor ?? defaultSelfAnchor;
|
|
1083
|
+
let actualHeight;
|
|
1084
|
+
if (elem.type === "text") {
|
|
1085
|
+
const textContent = getTextContent(elem);
|
|
1086
|
+
const autoResult = calculateAutoWidthDimensions(elem, textContent, measureCtx);
|
|
1087
|
+
if (autoResult) {
|
|
1088
|
+
actualHeight = autoResult.actualHeight;
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1070
1091
|
const newY = calculateAbsoluteY(
|
|
1071
1092
|
elem,
|
|
1072
1093
|
refPosition,
|
|
1073
1094
|
elem.relativePositionY.anchor,
|
|
1074
1095
|
selfAnchor,
|
|
1075
|
-
elem.relativePositionY.offset
|
|
1096
|
+
elem.relativePositionY.offset,
|
|
1097
|
+
actualHeight
|
|
1098
|
+
// Use actual height for self anchor calculation
|
|
1076
1099
|
);
|
|
1077
1100
|
resolvedY.set(elem.id, { y: newY, height: elem.height });
|
|
1078
|
-
if (
|
|
1079
|
-
|
|
1080
|
-
const autoResult = calculateAutoWidthDimensions({ ...elem, y: newY }, textContent, measureCtx);
|
|
1081
|
-
if (autoResult) {
|
|
1082
|
-
referenceY.set(elem.id, { y: newY, height: autoResult.actualHeight });
|
|
1083
|
-
} else {
|
|
1084
|
-
referenceY.set(elem.id, { y: newY, height: elem.height });
|
|
1085
|
-
}
|
|
1101
|
+
if (actualHeight !== void 0) {
|
|
1102
|
+
referenceY.set(elem.id, { y: newY, height: actualHeight });
|
|
1086
1103
|
} else {
|
|
1087
1104
|
referenceY.set(elem.id, { y: newY, height: elem.height });
|
|
1088
1105
|
}
|
|
@@ -1150,7 +1167,16 @@ function getReferenceElementY(elements, elementId) {
|
|
|
1150
1167
|
}
|
|
1151
1168
|
|
|
1152
1169
|
// src/utils/cropBounds.ts
|
|
1153
|
-
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) {
|
|
1154
1180
|
if (!dynamicCrop) {
|
|
1155
1181
|
return { x: 0, y: 0, width: canvasWidth, height: canvasHeight };
|
|
1156
1182
|
}
|
|
@@ -1163,6 +1189,12 @@ function calculateCropBounds(elements, dynamicCrop, canvasWidth, canvasHeight) {
|
|
|
1163
1189
|
if (boundary.elementId) return boundary.elementId;
|
|
1164
1190
|
return void 0;
|
|
1165
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
|
+
}
|
|
1166
1198
|
let cropY = 0;
|
|
1167
1199
|
let cropHeight = canvasHeight;
|
|
1168
1200
|
if (dynamicCrop.vertical?.enabled) {
|
|
@@ -1173,8 +1205,9 @@ function calculateCropBounds(elements, dynamicCrop, canvasWidth, canvasHeight) {
|
|
|
1173
1205
|
let minY = canvasHeight;
|
|
1174
1206
|
let maxY = 0;
|
|
1175
1207
|
for (const elem of elements) {
|
|
1208
|
+
const actualHeight = getActualElementHeight(elem, textValues, measureCtx);
|
|
1176
1209
|
minY = Math.min(minY, elem.y);
|
|
1177
|
-
maxY = Math.max(maxY, elem.y +
|
|
1210
|
+
maxY = Math.max(maxY, elem.y + actualHeight);
|
|
1178
1211
|
}
|
|
1179
1212
|
if (elements.length > 0) {
|
|
1180
1213
|
cropY = Math.max(0, minY - paddingStart);
|
|
@@ -1195,7 +1228,8 @@ function calculateCropBounds(elements, dynamicCrop, canvasWidth, canvasHeight) {
|
|
|
1195
1228
|
if (endElementId) {
|
|
1196
1229
|
const endElem = elementMap.get(endElementId);
|
|
1197
1230
|
if (endElem) {
|
|
1198
|
-
|
|
1231
|
+
const actualHeight = getActualElementHeight(endElem, textValues, measureCtx);
|
|
1232
|
+
bottomY = endElem.y + actualHeight;
|
|
1199
1233
|
}
|
|
1200
1234
|
}
|
|
1201
1235
|
cropY = Math.max(0, topY - paddingStart);
|
|
@@ -1429,8 +1463,8 @@ function ImageEditorComposition({
|
|
|
1429
1463
|
}, [elements, textValues]);
|
|
1430
1464
|
const cropBounds = (0, import_react3.useMemo)(() => {
|
|
1431
1465
|
if (!isDynamicCropEnabled(dynamicCrop) || !resolvedElements) return null;
|
|
1432
|
-
return calculateCropBounds(resolvedElements, dynamicCrop, canvasWidth, canvasHeight);
|
|
1433
|
-
}, [resolvedElements, dynamicCrop, canvasWidth, canvasHeight]);
|
|
1466
|
+
return calculateCropBounds(resolvedElements, dynamicCrop, canvasWidth, canvasHeight, textValues);
|
|
1467
|
+
}, [resolvedElements, dynamicCrop, canvasWidth, canvasHeight, textValues]);
|
|
1434
1468
|
const segmentsFromElements = (0, import_react3.useMemo)(() => {
|
|
1435
1469
|
if (!resolvedElements) return null;
|
|
1436
1470
|
const segments = [];
|
package/dist/index.mjs
CHANGED
|
@@ -858,38 +858,40 @@ function topologicalSortForAxis(elements, axis) {
|
|
|
858
858
|
}
|
|
859
859
|
return { sorted, errors };
|
|
860
860
|
}
|
|
861
|
-
function getSelfAnchorOffsetX(element, selfAnchor) {
|
|
861
|
+
function getSelfAnchorOffsetX(element, selfAnchor, actualWidth) {
|
|
862
|
+
const width = actualWidth ?? element.width;
|
|
862
863
|
switch (selfAnchor) {
|
|
863
864
|
case "left":
|
|
864
865
|
return 0;
|
|
865
866
|
case "center":
|
|
866
|
-
return
|
|
867
|
+
return width / 2;
|
|
867
868
|
case "right":
|
|
868
|
-
return
|
|
869
|
+
return width;
|
|
869
870
|
default:
|
|
870
871
|
return 0;
|
|
871
872
|
}
|
|
872
873
|
}
|
|
873
|
-
function getSelfAnchorOffsetY(element, selfAnchor) {
|
|
874
|
+
function getSelfAnchorOffsetY(element, selfAnchor, actualHeight) {
|
|
875
|
+
const height = actualHeight ?? element.height;
|
|
874
876
|
switch (selfAnchor) {
|
|
875
877
|
case "top":
|
|
876
878
|
return 0;
|
|
877
879
|
case "middle":
|
|
878
|
-
return
|
|
880
|
+
return height / 2;
|
|
879
881
|
case "bottom":
|
|
880
|
-
return
|
|
882
|
+
return height;
|
|
881
883
|
default:
|
|
882
884
|
return 0;
|
|
883
885
|
}
|
|
884
886
|
}
|
|
885
|
-
function calculateAbsoluteX(element, referenceElement, anchor, selfAnchor, offset) {
|
|
887
|
+
function calculateAbsoluteX(element, referenceElement, anchor, selfAnchor, offset, actualWidth) {
|
|
886
888
|
const refX = anchor === "left" ? referenceElement.x : referenceElement.x + referenceElement.width;
|
|
887
|
-
const selfOffset = getSelfAnchorOffsetX(element, selfAnchor);
|
|
889
|
+
const selfOffset = getSelfAnchorOffsetX(element, selfAnchor, actualWidth);
|
|
888
890
|
return refX + offset - selfOffset;
|
|
889
891
|
}
|
|
890
|
-
function calculateAbsoluteY(element, referenceElement, anchor, selfAnchor, offset) {
|
|
892
|
+
function calculateAbsoluteY(element, referenceElement, anchor, selfAnchor, offset, actualHeight) {
|
|
891
893
|
const refY = anchor === "top" ? referenceElement.y : referenceElement.y + referenceElement.height;
|
|
892
|
-
const selfOffset = getSelfAnchorOffsetY(element, selfAnchor);
|
|
894
|
+
const selfOffset = getSelfAnchorOffsetY(element, selfAnchor, actualHeight);
|
|
893
895
|
return refY + offset - selfOffset;
|
|
894
896
|
}
|
|
895
897
|
function resolveElementPositions(elements, textValues) {
|
|
@@ -947,26 +949,37 @@ function resolveElementPositions(elements, textValues) {
|
|
|
947
949
|
if (refPosition) {
|
|
948
950
|
const defaultSelfAnchor = elem.relativePositionX.anchor === "right" ? "left" : "right";
|
|
949
951
|
const selfAnchor = elem.relativePositionX.selfAnchor ?? defaultSelfAnchor;
|
|
952
|
+
let actualWidth;
|
|
953
|
+
let autoResult = null;
|
|
954
|
+
if (elem.type === "text") {
|
|
955
|
+
const textContent = getTextContent(elem);
|
|
956
|
+
autoResult = calculateAutoWidthDimensions(elem, textContent, measureCtx);
|
|
957
|
+
if (autoResult && elem.autoWidth) {
|
|
958
|
+
actualWidth = autoResult.actualWidth;
|
|
959
|
+
}
|
|
960
|
+
}
|
|
950
961
|
const newX = calculateAbsoluteX(
|
|
951
962
|
elem,
|
|
952
963
|
refPosition,
|
|
953
964
|
elem.relativePositionX.anchor,
|
|
954
965
|
selfAnchor,
|
|
955
|
-
elem.relativePositionX.offset
|
|
966
|
+
elem.relativePositionX.offset,
|
|
967
|
+
actualWidth
|
|
968
|
+
// Use actual width for self anchor calculation
|
|
956
969
|
);
|
|
957
970
|
resolvedX.set(elem.id, { x: newX, width: elem.width });
|
|
958
|
-
if (
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
971
|
+
if (autoResult) {
|
|
972
|
+
if (elem.autoWidth) {
|
|
973
|
+
const updatedResult = calculateAutoWidthDimensions({ ...elem, x: newX }, getTextContent(elem), measureCtx);
|
|
974
|
+
if (updatedResult) {
|
|
975
|
+
referenceX.set(elem.id, { x: updatedResult.actualX, width: updatedResult.actualWidth });
|
|
976
|
+
referenceY.set(elem.id, { y: referenceY.get(elem.id)?.y ?? elem.y, height: updatedResult.actualHeight });
|
|
964
977
|
} else {
|
|
965
978
|
referenceX.set(elem.id, { x: newX, width: elem.width });
|
|
966
979
|
}
|
|
967
|
-
referenceY.set(elem.id, { y: referenceY.get(elem.id)?.y ?? elem.y, height: autoResult.actualHeight });
|
|
968
980
|
} else {
|
|
969
981
|
referenceX.set(elem.id, { x: newX, width: elem.width });
|
|
982
|
+
referenceY.set(elem.id, { y: referenceY.get(elem.id)?.y ?? elem.y, height: autoResult.actualHeight });
|
|
970
983
|
}
|
|
971
984
|
} else {
|
|
972
985
|
referenceX.set(elem.id, { x: newX, width: elem.width });
|
|
@@ -981,22 +994,26 @@ function resolveElementPositions(elements, textValues) {
|
|
|
981
994
|
if (refPosition) {
|
|
982
995
|
const defaultSelfAnchor = elem.relativePositionY.anchor === "bottom" ? "top" : "bottom";
|
|
983
996
|
const selfAnchor = elem.relativePositionY.selfAnchor ?? defaultSelfAnchor;
|
|
997
|
+
let actualHeight;
|
|
998
|
+
if (elem.type === "text") {
|
|
999
|
+
const textContent = getTextContent(elem);
|
|
1000
|
+
const autoResult = calculateAutoWidthDimensions(elem, textContent, measureCtx);
|
|
1001
|
+
if (autoResult) {
|
|
1002
|
+
actualHeight = autoResult.actualHeight;
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
984
1005
|
const newY = calculateAbsoluteY(
|
|
985
1006
|
elem,
|
|
986
1007
|
refPosition,
|
|
987
1008
|
elem.relativePositionY.anchor,
|
|
988
1009
|
selfAnchor,
|
|
989
|
-
elem.relativePositionY.offset
|
|
1010
|
+
elem.relativePositionY.offset,
|
|
1011
|
+
actualHeight
|
|
1012
|
+
// Use actual height for self anchor calculation
|
|
990
1013
|
);
|
|
991
1014
|
resolvedY.set(elem.id, { y: newY, height: elem.height });
|
|
992
|
-
if (
|
|
993
|
-
|
|
994
|
-
const autoResult = calculateAutoWidthDimensions({ ...elem, y: newY }, textContent, measureCtx);
|
|
995
|
-
if (autoResult) {
|
|
996
|
-
referenceY.set(elem.id, { y: newY, height: autoResult.actualHeight });
|
|
997
|
-
} else {
|
|
998
|
-
referenceY.set(elem.id, { y: newY, height: elem.height });
|
|
999
|
-
}
|
|
1015
|
+
if (actualHeight !== void 0) {
|
|
1016
|
+
referenceY.set(elem.id, { y: newY, height: actualHeight });
|
|
1000
1017
|
} else {
|
|
1001
1018
|
referenceY.set(elem.id, { y: newY, height: elem.height });
|
|
1002
1019
|
}
|
|
@@ -1064,7 +1081,16 @@ function getReferenceElementY(elements, elementId) {
|
|
|
1064
1081
|
}
|
|
1065
1082
|
|
|
1066
1083
|
// src/utils/cropBounds.ts
|
|
1067
|
-
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) {
|
|
1068
1094
|
if (!dynamicCrop) {
|
|
1069
1095
|
return { x: 0, y: 0, width: canvasWidth, height: canvasHeight };
|
|
1070
1096
|
}
|
|
@@ -1077,6 +1103,12 @@ function calculateCropBounds(elements, dynamicCrop, canvasWidth, canvasHeight) {
|
|
|
1077
1103
|
if (boundary.elementId) return boundary.elementId;
|
|
1078
1104
|
return void 0;
|
|
1079
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
|
+
}
|
|
1080
1112
|
let cropY = 0;
|
|
1081
1113
|
let cropHeight = canvasHeight;
|
|
1082
1114
|
if (dynamicCrop.vertical?.enabled) {
|
|
@@ -1087,8 +1119,9 @@ function calculateCropBounds(elements, dynamicCrop, canvasWidth, canvasHeight) {
|
|
|
1087
1119
|
let minY = canvasHeight;
|
|
1088
1120
|
let maxY = 0;
|
|
1089
1121
|
for (const elem of elements) {
|
|
1122
|
+
const actualHeight = getActualElementHeight(elem, textValues, measureCtx);
|
|
1090
1123
|
minY = Math.min(minY, elem.y);
|
|
1091
|
-
maxY = Math.max(maxY, elem.y +
|
|
1124
|
+
maxY = Math.max(maxY, elem.y + actualHeight);
|
|
1092
1125
|
}
|
|
1093
1126
|
if (elements.length > 0) {
|
|
1094
1127
|
cropY = Math.max(0, minY - paddingStart);
|
|
@@ -1109,7 +1142,8 @@ function calculateCropBounds(elements, dynamicCrop, canvasWidth, canvasHeight) {
|
|
|
1109
1142
|
if (endElementId) {
|
|
1110
1143
|
const endElem = elementMap.get(endElementId);
|
|
1111
1144
|
if (endElem) {
|
|
1112
|
-
|
|
1145
|
+
const actualHeight = getActualElementHeight(endElem, textValues, measureCtx);
|
|
1146
|
+
bottomY = endElem.y + actualHeight;
|
|
1113
1147
|
}
|
|
1114
1148
|
}
|
|
1115
1149
|
cropY = Math.max(0, topY - paddingStart);
|
|
@@ -1343,8 +1377,8 @@ function ImageEditorComposition({
|
|
|
1343
1377
|
}, [elements, textValues]);
|
|
1344
1378
|
const cropBounds = useMemo3(() => {
|
|
1345
1379
|
if (!isDynamicCropEnabled(dynamicCrop) || !resolvedElements) return null;
|
|
1346
|
-
return calculateCropBounds(resolvedElements, dynamicCrop, canvasWidth, canvasHeight);
|
|
1347
|
-
}, [resolvedElements, dynamicCrop, canvasWidth, canvasHeight]);
|
|
1380
|
+
return calculateCropBounds(resolvedElements, dynamicCrop, canvasWidth, canvasHeight, textValues);
|
|
1381
|
+
}, [resolvedElements, dynamicCrop, canvasWidth, canvasHeight, textValues]);
|
|
1348
1382
|
const segmentsFromElements = useMemo3(() => {
|
|
1349
1383
|
if (!resolvedElements) return null;
|
|
1350
1384
|
const segments = [];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ugcinc-render",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.25",
|
|
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",
|