embroidery-qc-image 1.0.26 → 1.0.27

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.
@@ -1 +1 @@
1
- {"version":3,"file":"EmbroideryQCImage.d.ts","sourceRoot":"","sources":["../../src/components/EmbroideryQCImage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAY,MAAM,UAAU,CAAC;AAChF,OAAO,yBAAyB,CAAC;AAiKjC,MAAM,WAAW,8BAA8B;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,WAAW,GAAG,YAAY,GAAG,YAAY,CAAC;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAucD,QAAA,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC,sBAAsB,CAmHvD,CAAC;AA2tCF,eAAO,MAAM,6BAA6B,GACxC,QAAQ,kBAAkB,EAC1B,UAAS,8BAAmC,KAC3C,OAAO,CAAC,IAAI,GAAG,IAAI,CAuBrB,CAAC;AAEF,eAAO,MAAM,6BAA6B,GACxC,QAAQ,kBAAkB,EAC1B,UAAS,8BAAmC,KAC3C,OAAO,CAAC,MAAM,GAAG,IAAI,CAuBvB,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
1
+ {"version":3,"file":"EmbroideryQCImage.d.ts","sourceRoot":"","sources":["../../src/components/EmbroideryQCImage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAY,MAAM,UAAU,CAAC;AAChF,OAAO,yBAAyB,CAAC;AAiKjC,MAAM,WAAW,8BAA8B;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,WAAW,GAAG,YAAY,GAAG,YAAY,CAAC;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAucD,QAAA,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC,sBAAsB,CAmHvD,CAAC;AA4zCF,eAAO,MAAM,6BAA6B,GACxC,QAAQ,kBAAkB,EAC1B,UAAS,8BAAmC,KAC3C,OAAO,CAAC,IAAI,GAAG,IAAI,CAuBrB,CAAC;AAEF,eAAO,MAAM,6BAA6B,GACxC,QAAQ,kBAAkB,EAC1B,UAAS,8BAAmC,KAC3C,OAAO,CAAC,MAAM,GAAG,IAAI,CAuBvB,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
package/dist/index.esm.js CHANGED
@@ -1069,16 +1069,22 @@ displayIndex, showLabels, scaleFactor, imageRefs) => {
1069
1069
  effectiveTextFontSize = textFontSize * shrinkRatio;
1070
1070
  }
1071
1071
  }
1072
- // Vẽ phần value với font hiệu dụng, màu đỏ
1072
+ // Line height luôn theo Text label (textFontSize), không theo effectiveTextFontSize
1073
+ const valueLineHeight = textFontSize;
1074
+ const textBlockHeight = lines.length * valueLineHeight;
1075
+ // Text align center: căn giữa theo chiều dọc trong block
1076
+ const textCenterY = currentY + textBlockHeight / 2;
1077
+ // Vẽ phần value với font hiệu dụng, màu đỏ, align center
1078
+ ctx.textBaseline = "middle";
1073
1079
  ctx.font = `${effectiveTextFontSize}px ${LAYOUT.FONT_FAMILY}`;
1074
1080
  ctx.fillStyle = DEFAULT_ERROR_COLOR;
1075
- const valueLineHeight = effectiveTextFontSize; // giữ giống wrapText cũ (lineHeight = fontSize)
1076
- let localY = currentY;
1081
+ // Vẽ từ trên xuống: căn giữa mỗi dòng
1077
1082
  lines.forEach((line, idx) => {
1078
- ctx.fillText(line, valueStartX, localY);
1079
- localY += valueLineHeight;
1083
+ const lineY = textCenterY - (lines.length - 1) / 2 * valueLineHeight + idx * valueLineHeight;
1084
+ ctx.fillText(line, valueStartX, lineY);
1080
1085
  });
1081
- const textBlockHeight = lines.length * valueLineHeight;
1086
+ // Reset textBaseline về top cho các phần tiếp theo
1087
+ ctx.textBaseline = LAYOUT.TEXT_BASELINE;
1082
1088
  currentY += textBlockHeight;
1083
1089
  drawnHeight += textBlockHeight;
1084
1090
  // Draw additional labels (skip when text is empty)
@@ -1239,29 +1245,102 @@ const renderIconPosition = (ctx, position, x, y, maxWidth, scaleFactor, imageRef
1239
1245
  // Kiểm tra xem có icon_image không để tính height phù hợp
1240
1246
  const hasIconImage = position.icon_image && position.icon_image.trim().length > 0;
1241
1247
  const iconImageHeight = hasIconImage ? iconFontSize * 2 : iconFontSize;
1242
- // Text align bottom: đặt text ở dưới cùng của dòng
1243
- const textBottomY = cursorY + iconImageHeight;
1244
- // Đo width trước khi vẽ
1248
+ // Đo width của label
1245
1249
  ctx.font = `bold ${iconFontSize}px ${LAYOUT.FONT_FAMILY}`;
1246
1250
  const labelWidth = ctx.measureText(iconLabel).width;
1247
- ctx.font = `${iconFontSize}px ${LAYOUT.FONT_FAMILY}`;
1248
- const valueText = ` ${iconValue}`;
1249
- const valueWidth = ctx.measureText(valueText).width;
1250
- // Vẽ text với textBaseline = bottom
1251
- ctx.textBaseline = "bottom";
1251
+ // Chuẩn hóa xuống dòng cho icon_value (giống text value)
1252
+ const normalizeNewlines = (text) => text
1253
+ .replace(/\r\n/g, "\n")
1254
+ .replace(/\r/g, "\n")
1255
+ .replace(/\\n/g, "\n");
1256
+ const normalizedIconValue = normalizeNewlines(iconValue);
1257
+ const iconValueLines = normalizedIconValue.split("\n");
1258
+ // Tính kích thước icon_image nếu có để chừa khoảng trống
1259
+ let iconImageReservedWidth = 0;
1260
+ if (hasIconImage) {
1261
+ const iconUrl = getIconImageUrl(position);
1262
+ if (iconUrl) {
1263
+ const img = imageRefs.current.get(iconUrl);
1264
+ if (img?.complete && img.naturalHeight > 0) {
1265
+ const ratio = img.naturalWidth / img.naturalHeight;
1266
+ const iconHeight = iconFontSize * 2;
1267
+ const iconWidth = Math.max(1, Math.floor(iconHeight * ratio));
1268
+ iconImageReservedWidth = iconWidth + LAYOUT.ELEMENT_SPACING * scaleFactor;
1269
+ }
1270
+ }
1271
+ }
1272
+ // Tính available width cho icon value (trừ đi khoảng trống cho icon_image)
1273
+ const availableWidth = Math.max(1, maxWidth - labelWidth - iconImageReservedWidth);
1274
+ // Tính font-size hiệu dụng cho icon value
1275
+ // Giới hạn thu nhỏ tối đa 50% (tối thiểu = iconFontSize * 0.5)
1276
+ const MIN_ICON_VALUE_FONT_SIZE = iconFontSize * 0.5;
1277
+ const measureMaxLineWidth = (fontSize) => {
1278
+ ctx.font = `${fontSize}px ${LAYOUT.FONT_FAMILY}`;
1279
+ let maxLineWidth = 0;
1280
+ iconValueLines.forEach((line) => {
1281
+ const w = ctx.measureText(` ${line}`).width;
1282
+ if (w > maxLineWidth)
1283
+ maxLineWidth = w;
1284
+ });
1285
+ return maxLineWidth;
1286
+ };
1287
+ let effectiveIconValueFontSize = iconFontSize;
1288
+ const baseMaxWidth = measureMaxLineWidth(iconFontSize);
1289
+ let needsWrap = false;
1290
+ if (baseMaxWidth > availableWidth) {
1291
+ const shrinkRatio = availableWidth / baseMaxWidth;
1292
+ effectiveIconValueFontSize = Math.max(MIN_ICON_VALUE_FONT_SIZE, iconFontSize * shrinkRatio);
1293
+ // Kiểm tra xem sau khi thu nhỏ đến 50% có vẫn overflow không
1294
+ const minMaxWidth = measureMaxLineWidth(MIN_ICON_VALUE_FONT_SIZE);
1295
+ if (minMaxWidth > availableWidth) {
1296
+ // Vẫn overflow, cần dùng wrap text
1297
+ needsWrap = true;
1298
+ effectiveIconValueFontSize = MIN_ICON_VALUE_FONT_SIZE;
1299
+ }
1300
+ }
1301
+ // Tính line height và block height cho icon value
1302
+ const valueLineHeight = effectiveIconValueFontSize;
1303
+ let allWrappedLines = [];
1304
+ if (needsWrap) {
1305
+ // Dùng wrap text logic: wrap tất cả các dòng trước
1306
+ iconValueLines.forEach((line) => {
1307
+ const wrappedLines = buildWrappedLines(ctx, line, availableWidth);
1308
+ allWrappedLines.push(...wrappedLines);
1309
+ });
1310
+ allWrappedLines.length * valueLineHeight;
1311
+ }
1312
+ else {
1313
+ allWrappedLines = iconValueLines;
1314
+ iconValueLines.length * valueLineHeight;
1315
+ }
1316
+ // Text align center: căn giữa theo chiều dọc trong block
1317
+ const textCenterY = cursorY + iconImageHeight / 2;
1318
+ // Vẽ label với textBaseline = middle để align center với value
1319
+ ctx.textBaseline = "middle";
1252
1320
  ctx.font = `bold ${iconFontSize}px ${LAYOUT.FONT_FAMILY}`;
1253
1321
  ctx.fillStyle = LAYOUT.LABEL_COLOR;
1254
- ctx.fillText(iconLabel, x, textBottomY);
1255
- ctx.font = `${iconFontSize}px ${LAYOUT.FONT_FAMILY}`;
1322
+ ctx.fillText(iconLabel, x, textCenterY);
1323
+ const valueStartX = x + labelWidth;
1324
+ // Vẽ icon value với align center
1325
+ ctx.font = `${effectiveIconValueFontSize}px ${LAYOUT.FONT_FAMILY}`;
1256
1326
  ctx.fillStyle = DEFAULT_ERROR_COLOR;
1257
- ctx.fillText(valueText, x + labelWidth, textBottomY);
1327
+ let maxValueLineWidth = 0;
1328
+ // Vẽ từng dòng, căn giữa theo chiều dọc
1329
+ allWrappedLines.forEach((line, index) => {
1330
+ const lineY = textCenterY - (allWrappedLines.length - 1) / 2 * valueLineHeight + index * valueLineHeight;
1331
+ const lineText = needsWrap ? line : ` ${line}`;
1332
+ ctx.fillText(lineText, valueStartX, lineY);
1333
+ const w = ctx.measureText(lineText).width;
1334
+ if (w > maxValueLineWidth)
1335
+ maxValueLineWidth = w;
1336
+ });
1258
1337
  ctx.fillStyle = LAYOUT.LABEL_COLOR;
1259
1338
  // Reset textBaseline về top cho các phần tiếp theo
1260
1339
  ctx.textBaseline = LAYOUT.TEXT_BASELINE;
1261
1340
  const iconResult = {
1262
1341
  height: iconImageHeight + lineGap,
1263
1342
  // tổng width của cả label + value, dùng để canh icon image lệch sang phải
1264
- lastLineWidth: labelWidth + valueWidth};
1343
+ lastLineWidth: labelWidth + maxValueLineWidth};
1265
1344
  // Draw icon image
1266
1345
  const iconUrl = getIconImageUrl(position);
1267
1346
  if (iconUrl) {
@@ -1274,7 +1353,7 @@ const renderIconPosition = (ctx, position, x, y, maxWidth, scaleFactor, imageRef
1274
1353
  const iconX = x +
1275
1354
  Math.ceil(iconResult.lastLineWidth) +
1276
1355
  LAYOUT.ELEMENT_SPACING * scaleFactor;
1277
- const iconY = textBottomY - iconHeight; // Align bottom với text
1356
+ const iconY = textCenterY - iconHeight / 2; // Align center với text
1278
1357
  ctx.drawImage(img, iconX, iconY, swatchW, iconHeight);
1279
1358
  }
1280
1359
  }