embroidery-qc-image 1.0.22 → 1.0.24

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;AAyJjC,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;AAoWD,QAAA,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC,sBAAsB,CAqHvD,CAAC;AAw7BF,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;AAoWD,QAAA,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC,sBAAsB,CAqHvD,CAAC;AAm7BF,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
@@ -31,78 +31,13 @@ function styleInject(css, ref) {
31
31
  var css_248z = ".render-embroidery {\r\n display: inline-block;\r\n position: relative;\r\n width: 100%;\r\n max-width: 100%;\r\n}\r\n\r\n.render-embroidery-canvas {\r\n display: block;\r\n width: 100%;\r\n height: auto;\r\n image-rendering: high-quality;\r\n background: transparent;\r\n}\r\n";
32
32
  styleInject(css_248z);
33
33
 
34
- // ============================================================================
35
- // CONSTANTS
36
- // ============================================================================
37
- const COLOR_MAP = {
38
- "Army (1394)": "#545541",
39
- Army: "#545541",
40
- "Black (8)": "#060608",
41
- Black: "#060608",
42
- "Bubblegum (1309)": "#E77B9F",
43
- Bubblegum: "#E77B9F",
44
- "Carolina Blue (1274)": "#608CC9",
45
- "Carolina Blue": "#608CC9",
46
- "Celadon (1098)": "#8EAD8D",
47
- Celadon: "#8EAD8D",
48
- "Coffee Bean (1145)": "#502B23",
49
- "Coffee Bean": "#502B23",
50
- "Daffodil (1180)": "#FBE30D",
51
- Daffodil: "#FBE30D",
52
- "Dark Gray (1131)": "#2E272E",
53
- "Dark Gray": "#2E272E",
54
- "Doe Skin Beige (1344)": "#AE9B8B",
55
- "Doe Skin Beige": "#AE9B8B",
56
- "Dusty Blue (1373)": "#7B90A9",
57
- "Dusty Blue": "#7B90A9",
58
- "Forest Green (1397)": "#073020",
59
- "Forest Green": "#073020",
60
- "Gold (1425)": "#D2920A",
61
- Gold: "#D2920A",
62
- "Gray (1118)": "#9999A3",
63
- Gray: "#9999A3",
64
- "Ivory (1072)": "#E3DAC9",
65
- Ivory: "#E3DAC9",
66
- "Lavender (1032)": "#9274B6",
67
- Lavender: "#9274B6",
68
- "Light Denim (1133)": "#366696",
69
- "Light Denim": "#366696",
70
- "Light Salmon (1018)": "#E0A793",
71
- "Light Salmon": "#E0A793",
72
- "Maroon (1374)": "#480C1C",
73
- Maroon: "#480C1C",
74
- "Navy Blue (1044)": "#04072A",
75
- "Navy Blue": "#04072A",
76
- "Olive Green (1157)": "#625E1F",
77
- "Olive Green": "#625E1F",
78
- "Orange (1278)": "#D45D03",
79
- Orange: "#D45D03",
80
- "Peach Blush (1053)": "#E2C0B6",
81
- "Peach Blush": "#E2C0B6",
82
- "Pink (1148)": "#EFAFBF",
83
- Pink: "#EFAFBF",
84
- "Purple (1412)": "#37196F",
85
- Purple: "#37196F",
86
- "Red (1037)": "#9D000B",
87
- Red: "#9D000B",
88
- "Silver Sage (1396)": "#424F45",
89
- "Silver Sage": "#424F45",
90
- "Summer Sky (1432)": "#65A8D2",
91
- "Summer Sky": "#65A8D2",
92
- "Terra Cotta (1477)": "#AE3111",
93
- "Terra Cotta": "#AE3111",
94
- "Sand (1055)": "#D2C2AB",
95
- Sand: "#D2C2AB",
96
- "White (9)": "#D8D7DC",
97
- White: "#D8D7DC",
98
- };
99
34
  const DEFAULT_ERROR_COLOR = "#CC1F1A";
100
35
  const DEFAULT_WARNING_COLOR = "#FF8C00";
101
36
  const BASE_URLS = {
102
37
  FONT: "https://s3.hn-1.cloud.cmctelecom.vn/god-system-images/embroidery/fonts",
103
- ICON: "https://s3.hn-1.cloud.cmctelecom.vn/god-system-images/embroidery/icons",
104
- FLORAL: "https://s3.hn-1.cloud.cmctelecom.vn/god-system-images/embroidery/florals",
105
- THREAD_COLOR: "https://s3.hn-1.cloud.cmctelecom.vn/god-system-images/embroidery/thread-colors",
38
+ ICON: "https://s3.hn-1.cloud.cmctelecom.vn/god-system-images/embroidery/icons-resized",
39
+ FLORAL: "https://s3.hn-1.cloud.cmctelecom.vn/god-system-images/embroidery/florals-resized",
40
+ THREAD_COLOR: "https://s3.hn-1.cloud.cmctelecom.vn/god-system-images/embroidery/thread-colors-resized",
106
41
  };
107
42
  const LAYOUT = {
108
43
  // Font families
@@ -138,6 +73,13 @@ const LAYOUT = {
138
73
  // HELPER FUNCTIONS
139
74
  // ============================================================================
140
75
  const loadFont = (fontName) => {
76
+ // Check if font is already loaded in document.fonts (browser cache)
77
+ const fontFaceSet = document.fonts;
78
+ for (const font of fontFaceSet) {
79
+ if (font.family === fontName && font.status === 'loaded') {
80
+ return Promise.resolve();
81
+ }
82
+ }
141
83
  return new Promise((resolve) => {
142
84
  const fontUrl = `${BASE_URLS.FONT}/${encodeURIComponent(fontName)}.woff2`;
143
85
  const fontFace = new FontFace(fontName, `url(${fontUrl})`);
@@ -155,10 +97,10 @@ const loadFont = (fontName) => {
155
97
  };
156
98
  const getImageUrl = (type, value) => {
157
99
  if (type === "icon")
158
- return `${BASE_URLS.ICON}/Icon ${value}.png`;
100
+ return `${BASE_URLS.ICON}/Icon ${value}.webp`;
159
101
  if (type === "floral")
160
- return `${BASE_URLS.FLORAL}/${value}.png`;
161
- return `${BASE_URLS.THREAD_COLOR}/${value}.png`;
102
+ return `${BASE_URLS.FLORAL}/${value}.webp`;
103
+ return `${BASE_URLS.THREAD_COLOR}/${value}.webp`;
162
104
  };
163
105
  const getProxyUrl = (url) => `https://proxy-img.c8p.workers.dev?url=${encodeURIComponent(url)}`;
164
106
  const ensureImage = (existing) => {
@@ -377,43 +319,6 @@ const buildWrappedLines = (ctx, text, maxWidth) => {
377
319
  lines.push(currentLine);
378
320
  return lines;
379
321
  };
380
- const wrapTextMultiColor = (ctx, text, colors, x, y, maxWidth, lineHeight) => {
381
- const words = text.split(" ");
382
- const lines = [];
383
- const lineStartIndices = [0];
384
- let currentLine = words[0];
385
- let currentCharIndex = words[0].length;
386
- for (let i = 1; i < words.length; i++) {
387
- const testLine = currentLine + " " + words[i];
388
- if (ctx.measureText(testLine).width > maxWidth && currentLine.length > 0) {
389
- lines.push(currentLine);
390
- lineStartIndices.push(currentCharIndex + 1);
391
- currentLine = words[i];
392
- currentCharIndex += words[i].length + 1;
393
- }
394
- else {
395
- currentLine = testLine;
396
- currentCharIndex += words[i].length + 1;
397
- }
398
- }
399
- lines.push(currentLine);
400
- let currentY = y;
401
- lines.forEach((line, lineIdx) => {
402
- let currentX = x;
403
- const startCharIdx = lineIdx > 0 ? lineStartIndices[lineIdx] : 0;
404
- for (let i = 0; i < line.length; i++) {
405
- const char = line[i];
406
- const globalCharIdx = startCharIdx + i;
407
- const colorIndex = globalCharIdx % colors.length;
408
- const color = colors[colorIndex];
409
- ctx.fillStyle = COLOR_MAP[color] || LAYOUT.LABEL_COLOR;
410
- ctx.fillText(char, currentX, currentY);
411
- currentX += ctx.measureText(char).width;
412
- }
413
- currentY += lineHeight;
414
- });
415
- return lines.length * lineHeight;
416
- };
417
322
  const drawSwatches = (ctx, colors, startX, startY, swatchHeight, scaleFactor, imageRefs) => {
418
323
  let swatchX = startX;
419
324
  colors.forEach((color) => {
@@ -885,9 +790,25 @@ const renderUniformLabels = (ctx, uniformProps, x, y, maxWidth, scaleFactor, ima
885
790
  let rendered = 0;
886
791
  if (values.font && shouldRenderField("font")) {
887
792
  const allDefault = textPositions.every((p) => p.is_font_default === true);
888
- const fontLabel = allDefault ? `Font: ${values.font} (Mặc định)` : `Font: ${values.font} (Custom)`;
889
- const result = wrapText(ctx, fontLabel, x, cursorY, maxWidth, fontSize + lineGap);
890
- cursorY += result.height;
793
+ // Render "Font: " với font mặc định
794
+ const prefix = "Font: ";
795
+ ctx.font = `${fontSize}px ${LAYOUT.FONT_FAMILY}`;
796
+ const prefixWidth = ctx.measureText(prefix).width;
797
+ let currentX = x + prefixWidth;
798
+ ctx.fillText(prefix, x, cursorY);
799
+ // Render tên font với font từ config
800
+ ctx.font = `${fontSize}px ${values.font}`;
801
+ const fontNameWidth = ctx.measureText(values.font).width;
802
+ ctx.fillText(values.font, currentX, cursorY);
803
+ currentX += fontNameWidth;
804
+ // Render "(Mặc định)" hoặc "(Custom)" với font mặc định
805
+ const suffix = allDefault ? " (Mặc định)" : " (Custom)";
806
+ ctx.font = `${fontSize}px ${LAYOUT.FONT_FAMILY}`;
807
+ ctx.measureText(suffix).width;
808
+ ctx.fillText(suffix, currentX, cursorY);
809
+ // Tính toán height và di chuyển cursorY
810
+ const lineHeight = fontSize + lineGap;
811
+ cursorY += lineHeight;
891
812
  rendered++;
892
813
  }
893
814
  if (values.shape && values.shape !== "None" && shouldRenderField("shape")) {
@@ -936,31 +857,15 @@ const renderTextPosition = (ctx, position, x, y, maxWidth, displayIndex, showLab
936
857
  const textMaxWidth = maxWidth - labelWidth;
937
858
  // Get display text (handle empty/null/undefined)
938
859
  const isEmptyText = !position.text || position.text.trim() === "";
939
- // Draw text content
860
+ // Draw text content - dùng font mặc định và màu đỏ
861
+ ctx.font = `${textFontSize}px ${LAYOUT.FONT_FAMILY}`;
862
+ ctx.fillStyle = DEFAULT_ERROR_COLOR;
940
863
  if (isEmptyText) {
941
- ctx.font = `${textFontSize}px ${LAYOUT.FONT_FAMILY}`;
942
- ctx.fillStyle = LAYOUT.LABEL_COLOR;
943
864
  const textResult = wrapText(ctx, "(không có text)", x + labelWidth, currentY, textMaxWidth, textFontSize);
944
865
  currentY += textResult.height;
945
866
  drawnHeight += textResult.height;
946
867
  }
947
- else if (position.floral_pattern) {
948
- // Khi có floral_pattern, dùng màu mặc định như label
949
- ctx.font = `${textFontSize}px ${position.font}`;
950
- ctx.fillStyle = LAYOUT.LABEL_COLOR;
951
- const textResult = wrapText(ctx, position.text, x + labelWidth, currentY, textMaxWidth, textFontSize);
952
- currentY += textResult.height;
953
- drawnHeight += textResult.height;
954
- }
955
- else if (position.character_colors?.length) {
956
- ctx.font = `${textFontSize}px ${position.font}`;
957
- const textHeight = wrapTextMultiColor(ctx, position.text, position.character_colors, x + labelWidth, currentY, textMaxWidth, textFontSize);
958
- currentY += textHeight;
959
- drawnHeight += textHeight;
960
- }
961
868
  else {
962
- ctx.font = `${textFontSize}px ${position.font}`;
963
- ctx.fillStyle = COLOR_MAP[position.color ?? "None"] || LAYOUT.LABEL_COLOR;
964
869
  const textResult = wrapText(ctx, position.text, x + labelWidth, currentY, textMaxWidth, textFontSize);
965
870
  currentY += textResult.height;
966
871
  drawnHeight += textResult.height;
@@ -976,12 +881,26 @@ const renderTextPosition = (ctx, position, x, y, maxWidth, displayIndex, showLab
976
881
  drawnHeight += result.height;
977
882
  }
978
883
  if (showLabels.font && position.font) {
979
- const fontLabel = position.is_font_default === true
980
- ? `Font: ${position.font} (Mặc định)`
981
- : `Font: ${position.font} (Custom)`;
982
- const result = wrapText(ctx, fontLabel, x, currentY, maxWidth, otherFontSize + lineGap);
983
- currentY += result.height;
984
- drawnHeight += result.height;
884
+ // Render "Font: " với font mặc định
885
+ const prefix = "Font: ";
886
+ ctx.font = `${otherFontSize}px ${LAYOUT.FONT_FAMILY}`;
887
+ const prefixWidth = ctx.measureText(prefix).width;
888
+ let currentX = x + prefixWidth;
889
+ ctx.fillText(prefix, x, currentY);
890
+ // Render tên font với font từ config
891
+ ctx.font = `${otherFontSize}px ${position.font}`;
892
+ const fontNameWidth = ctx.measureText(position.font).width;
893
+ ctx.fillText(position.font, currentX, currentY);
894
+ currentX += fontNameWidth;
895
+ // Render "(Mặc định)" hoặc "(Custom)" với font mặc định
896
+ const suffix = position.is_font_default === true ? " (Mặc định)" : " (Custom)";
897
+ ctx.font = `${otherFontSize}px ${LAYOUT.FONT_FAMILY}`;
898
+ ctx.measureText(suffix).width;
899
+ ctx.fillText(suffix, currentX, currentY);
900
+ // Tính toán height và di chuyển cursorY
901
+ const lineHeight = otherFontSize + lineGap;
902
+ currentY += lineHeight;
903
+ drawnHeight += lineHeight;
985
904
  }
986
905
  if (showLabels.color) {
987
906
  const colorValue = position.character_colors?.join(", ") || position.color;
@@ -1064,8 +983,11 @@ const prepareExportCanvas = async (config, options = {}) => {
1064
983
  const imageRefs = {
1065
984
  current: new Map(),
1066
985
  };
1067
- await preloadFonts(config);
1068
- await preloadImages(config, imageRefs);
986
+ // Load fonts and images in parallel
987
+ await Promise.all([
988
+ preloadFonts(config),
989
+ preloadImages(config, imageRefs)
990
+ ]);
1069
991
  renderEmbroideryCanvas(canvas, config, { width, height }, imageRefs);
1070
992
  if (!canvas.width || !canvas.height) {
1071
993
  return null;