ugcinc 4.5.70 → 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,17 +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 spaces for the stroke layer.
167
- * Spaces have zero alpha for the emoji glyphs, so feMorphology won't dilate them.
168
- * Returns a plain string no DOM changes, preserving identical vertical metrics.
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.
169
179
  */
170
- function getStrokeText(text) {
180
+ function renderTextWithEmojiSpans(text, forStroke) {
171
181
  if (!(0, emoji_1.hasEmoji)(text))
172
182
  return text;
173
- return (0, emoji_1.splitTextAndEmojis)(text)
174
- .map(part => part.type === 'emoji' ? ' ' : part.content)
175
- .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);
176
188
  }
177
189
  /**
178
190
  * TextElement renders text with full styling support including:
@@ -378,8 +390,8 @@ function TextElement({ segment, scale = 1 }) {
378
390
  const strokePadPct = Math.max(50, Math.ceil((strokeWidth / fontSize) * 200));
379
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;
380
392
  if (autoWidth) {
381
- 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)));
382
- 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)));
383
395
  if (backgroundColor) {
384
396
  return ((0, jsx_runtime_1.jsx)("div", { style: positioningContainerStyle, children: (0, jsx_runtime_1.jsxs)("div", { style: {
385
397
  width: calculatedWidth,
@@ -391,6 +403,6 @@ function TextElement({ segment, scale = 1 }) {
391
403
  }
392
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 })] }) }));
393
405
  }
394
- 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) })] }) }));
395
407
  }
396
408
  exports.default = TextElement;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ugcinc",
3
- "version": "4.5.70",
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",