sadpandajoe commented on code in PR #44147:
URL: https://github.com/apache/superset/pull/44147#discussion_r4174150683


##########
superset-frontend/plugins/plugin-chart-echarts/src/Pie/transformProps.ts:
##########
@@ -425,6 +428,87 @@ export default function transformProps(
     {},
   );
 
+  // Wraps a single line of text by pixel width, breaking at spaces. Oversized
+  // tokens (e.g. long identifiers or CJK strings without spaces) are split
+  // character-by-character so they never overflow the configured limit.
+  const wrapLine = (line: string, maxWidth: number): string => {
+    const words = line.split(' ');
+    const resultLines: string[] = [];
+    let currentLine = '';
+
+    const pushWord = (token: string) => {
+      // If the token itself is wider than maxWidth, split char by char.
+      if (measureTextWidth(token, theme) > maxWidth) {
+        if (currentLine) {
+          resultLines.push(currentLine);
+          currentLine = '';
+        }
+        let charBuf = '';
+        for (const ch of token) {
+          const testBuf = `${charBuf}${ch}`;
+          if (measureTextWidth(testBuf, theme) <= maxWidth) {
+            charBuf = testBuf;
+          } else {
+            if (charBuf) resultLines.push(charBuf);
+            charBuf = ch;
+          }
+        }
+        if (charBuf) currentLine = charBuf;
+        return;
+      }
+      const testLine = currentLine ? `${currentLine} ${token}` : token;
+      if (measureTextWidth(testLine, theme) <= maxWidth) {
+        currentLine = testLine;
+      } else {
+        if (currentLine) resultLines.push(currentLine);
+        currentLine = token;
+      }
+    };
+
+    for (const word of words) {
+      pushWord(word);
+    }
+    if (currentLine) resultLines.push(currentLine);
+    return resultLines.join('\n');
+  };
+
+  // Wraps every newline-delimited segment independently so multiline templates
+  // (e.g. {name}\n{percent}) keep their structural line breaks.
+  const wrapTextByPixels = (text: string, maxWidth: number): string =>
+    text
+      .split('\n')
+      .map(line => wrapLine(line, maxWidth))
+      .join('\n');
+
+  // Truncates a single line to fit inside maxWidth, appending '...'.
+  // When maxWidth is too narrow to fit even '...', returns '...' rather than
+  // producing garbage via a negative slice index.
+  const truncateLine = (line: string, maxWidth: number): string => {
+    if (measureTextWidth(line, theme) <= maxWidth) {
+      return line;
+    }
+    let left = 0;
+    let right = line.length;
+    while (left < right) {
+      const mid = Math.floor((left + right) / 2);
+      if (measureTextWidth(`${line.slice(0, mid)}...`, theme) <= maxWidth) {
+        left = mid + 1;
+      } else {
+        right = mid;
+      }
+    }
+    // left===0 means even '...' alone exceeds maxWidth; still return '...'.
+    return left === 0 ? '...' : `${line.slice(0, left - 1)}...`;

Review Comment:
   With Truncate and a 31px limit, `A😀😀😀😀 category` becomes `A�...` because 
this cutoff can split an emoji’s UTF-16 surrogate pair. Could truncation keep 
the cutoff on Unicode character boundaries?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to