ugcinc 4.5.71 → 4.5.72

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.
@@ -162,18 +162,29 @@ function calculateAutoWidthAndLines({ text, maxWidth, paddingLeft, paddingRight,
162
162
  const calculatedWidth = Math.min(widestLineWidth + paddingLeft + paddingRight, maxWidth);
163
163
  return { width: calculatedWidth, lines };
164
164
  }
165
+ /** Shared inline style for emoji spans — prevents line breaks */
166
+ const emojiSpanStyle = {
167
+ display: 'inline',
168
+ whiteSpace: 'pre-wrap',
169
+ };
170
+ /** Stroke layer emoji span — same structure as fill but invisible to the SVG filter */
171
+ const emojiSpanStrokeStyle = {
172
+ ...emojiSpanStyle,
173
+ opacity: 0,
174
+ };
165
175
  /**
166
- * Replace emoji characters with em-spaces for the stroke layer.
167
- * Em-space (U+2003) is 1em wide, close to emoji width (~1-1.2em),
168
- * preserving line width for correct text-align centering.
169
- * The em-space renders as whitespace (no alpha for feMorphology to dilate).
176
+ * Render text with emojis wrapped in spans.
177
+ * Both fill and stroke divs use this so they have identical DOM structure
178
+ * (matching vertical metrics). The only difference is the emoji span style.
170
179
  */
171
- function getStrokeText(text) {
180
+ function renderTextWithEmojiSpans(text, forStroke) {
172
181
  if (!(0, emoji_1.hasEmoji)(text))
173
182
  return text;
174
- return (0, emoji_1.splitTextAndEmojis)(text)
175
- .map(part => part.type === 'emoji' ? '\u2003' : part.content)
176
- .join('');
183
+ const parts = (0, emoji_1.splitTextAndEmojis)(text);
184
+ const style = forStroke ? emojiSpanStrokeStyle : emojiSpanStyle;
185
+ return parts.map((part, i) => part.type === 'emoji'
186
+ ? (0, jsx_runtime_1.jsx)("span", { style: style, children: part.content }, i)
187
+ : part.content);
177
188
  }
178
189
  /**
179
190
  * TextElement renders text with full styling support including:
@@ -379,8 +390,8 @@ function TextElement({ segment, scale = 1 }) {
379
390
  const strokePadPct = Math.max(50, Math.ceil((strokeWidth / fontSize) * 200));
380
391
  const strokeFilterSvg = hasStroke ? ((0, jsx_runtime_1.jsx)("svg", { style: { position: 'absolute', width: 0, height: 0, overflow: 'hidden' }, "aria-hidden": "true", children: (0, jsx_runtime_1.jsx)("defs", { children: (0, jsx_runtime_1.jsxs)("filter", { id: filterId, x: `-${strokePadPct}%`, y: `-${strokePadPct}%`, width: `${100 + 2 * strokePadPct}%`, height: `${100 + 2 * strokePadPct}%`, children: [(0, jsx_runtime_1.jsx)("feMorphology", { in: "SourceAlpha", operator: "dilate", radius: strokeWidth, result: "dilated" }), (0, jsx_runtime_1.jsx)("feFlood", { floodColor: strokeColor, result: "color" }), (0, jsx_runtime_1.jsx)("feComposite", { in: "color", in2: "dilated", operator: "in" })] }) }) })) : null;
381
392
  if (autoWidth) {
382
- const textContent = calculatedLines.map((line, index) => ((0, jsx_runtime_1.jsxs)(react_1.default.Fragment, { children: [line, index < calculatedLines.length - 1 && (0, jsx_runtime_1.jsx)("br", {})] }, index)));
383
- const strokeContent = calculatedLines.map((line, index) => ((0, jsx_runtime_1.jsxs)(react_1.default.Fragment, { children: [getStrokeText(line), index < calculatedLines.length - 1 && (0, jsx_runtime_1.jsx)("br", {})] }, index)));
393
+ const textContent = calculatedLines.map((line, index) => ((0, jsx_runtime_1.jsxs)(react_1.default.Fragment, { children: [renderTextWithEmojiSpans(line, false), index < calculatedLines.length - 1 && (0, jsx_runtime_1.jsx)("br", {})] }, index)));
394
+ const strokeContent = calculatedLines.map((line, index) => ((0, jsx_runtime_1.jsxs)(react_1.default.Fragment, { children: [renderTextWithEmojiSpans(line, true), index < calculatedLines.length - 1 && (0, jsx_runtime_1.jsx)("br", {})] }, index)));
384
395
  if (backgroundColor) {
385
396
  return ((0, jsx_runtime_1.jsx)("div", { style: positioningContainerStyle, children: (0, jsx_runtime_1.jsxs)("div", { style: {
386
397
  width: calculatedWidth,
@@ -392,6 +403,6 @@ function TextElement({ segment, scale = 1 }) {
392
403
  }
393
404
  return ((0, jsx_runtime_1.jsx)("div", { style: positioningContainerStyle, children: (0, jsx_runtime_1.jsxs)("div", { style: { width: calculatedWidth, maxWidth: width, ...(hasStroke && { position: 'relative' }) }, children: [strokeFilterSvg, strokeTextStyle && (0, jsx_runtime_1.jsx)("div", { style: strokeTextStyle, "aria-hidden": "true", children: strokeContent }), (0, jsx_runtime_1.jsx)("div", { style: textStyle, children: textContent })] }) }));
394
405
  }
395
- return ((0, jsx_runtime_1.jsx)("div", { style: positioningContainerStyle, children: (0, jsx_runtime_1.jsxs)("div", { style: { ...backgroundBoxStyle, ...(hasStroke && { position: 'relative' }) }, children: [strokeFilterSvg, strokeTextStyle && (0, jsx_runtime_1.jsx)("div", { style: strokeTextStyle, "aria-hidden": "true", children: getStrokeText(segment.text) }), (0, jsx_runtime_1.jsx)("div", { style: textStyle, children: segment.text })] }) }));
406
+ return ((0, jsx_runtime_1.jsx)("div", { style: positioningContainerStyle, children: (0, jsx_runtime_1.jsxs)("div", { style: { ...backgroundBoxStyle, ...(hasStroke && { position: 'relative' }) }, children: [strokeFilterSvg, strokeTextStyle && (0, jsx_runtime_1.jsx)("div", { style: strokeTextStyle, "aria-hidden": "true", children: renderTextWithEmojiSpans(segment.text, true) }), (0, jsx_runtime_1.jsx)("div", { style: textStyle, children: renderTextWithEmojiSpans(segment.text, false) })] }) }));
396
407
  }
397
408
  exports.default = TextElement;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ugcinc",
3
- "version": "4.5.71",
3
+ "version": "4.5.72",
4
4
  "description": "TypeScript/JavaScript client for the UGC Inc API",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",