ugcinc 4.5.65 → 4.5.67

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.
@@ -46,6 +46,20 @@ const defaults_1 = require("../utils/defaults");
46
46
  const fonts_1 = require("../utils/fonts");
47
47
  const text_1 = require("../utils/text");
48
48
  const emoji_1 = require("../utils/emoji");
49
+ /**
50
+ * Render text with emojis wrapped in spans — used by BOTH fill and stroke
51
+ * divs so they share identical DOM structure and vertical metrics.
52
+ * In the stroke layer, emoji spans get visibility:hidden so the SVG filter
53
+ * doesn't dilate them.
54
+ */
55
+ function renderTextWithEmojiSpans(text, hideEmojis) {
56
+ const parts = (0, emoji_1.splitTextAndEmojis)(text);
57
+ if (parts.every(p => p.type === 'text'))
58
+ return text;
59
+ return parts.map((part, i) => part.type === 'emoji'
60
+ ? (0, jsx_runtime_1.jsx)("span", { style: hideEmojis ? { visibility: 'hidden' } : undefined, children: part.content }, i)
61
+ : (0, jsx_runtime_1.jsx)(react_1.default.Fragment, { children: part.content }, i));
62
+ }
49
63
  /**
50
64
  * Calculate the actual width for auto-width text AND the line breaks.
51
65
  * Uses DOM-based measurement to ensure the same fonts are used as CSS rendering.
@@ -350,49 +364,24 @@ function TextElement({ segment, scale = 1 }) {
350
364
  const strokeTextStyle = (0, react_1.useMemo)(() => {
351
365
  if (!hasStroke)
352
366
  return undefined;
353
- const style = {
367
+ return {
354
368
  ...textStyle,
355
369
  color: strokeColor,
356
370
  filter: `url(#${filterId})`,
357
371
  position: 'absolute',
372
+ zIndex: 0,
358
373
  top: 0,
359
374
  left: 0,
360
375
  right: 0,
361
376
  bottom: 0,
362
377
  };
363
- return style;
364
- }, [hasStroke, textStyle, strokeColor, filterId, strokeWidth, paddingTop, paddingRight, paddingBottom, paddingLeft]);
365
- if (hasStroke) {
366
- console.log('[TextElement] STROKE_DIAG:', JSON.stringify({
367
- text: segment.text.substring(0, 30),
368
- strokeWidth,
369
- fontSize,
370
- fillZ: textStyle.zIndex,
371
- fillPos: textStyle.position,
372
- strokeZ: strokeTextStyle?.zIndex,
373
- strokePos: strokeTextStyle?.position,
374
- strokeFilter: strokeTextStyle?.filter,
375
- autoWidth,
376
- hasBg: !!backgroundColor,
377
- }));
378
- }
378
+ }, [hasStroke, textStyle, strokeColor, filterId]);
379
379
  // SVG filter for smooth text outline (avoids miter spikes from -webkit-text-stroke)
380
380
  const strokePadPct = Math.max(50, Math.ceil((strokeWidth / fontSize) * 200));
381
381
  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;
382
- // Render text with emojis made invisible (opacity 0) so the stroke
383
- // filter doesn't dilate around them. Emojis still occupy space to
384
- // keep layout identical to the fill layer.
385
- const renderStrokeText = (text) => {
386
- const parts = (0, emoji_1.splitTextAndEmojis)(text);
387
- if (parts.every(p => p.type === 'text'))
388
- return text;
389
- return parts.map((part, i) => part.type === 'emoji'
390
- ? (0, jsx_runtime_1.jsx)("span", { style: { visibility: 'hidden' }, children: part.content }, i)
391
- : (0, jsx_runtime_1.jsx)(react_1.default.Fragment, { children: part.content }, i));
392
- };
393
382
  if (autoWidth) {
394
- 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)));
395
- const strokeContent = calculatedLines.map((line, index) => ((0, jsx_runtime_1.jsxs)(react_1.default.Fragment, { children: [renderStrokeText(line), index < calculatedLines.length - 1 && (0, jsx_runtime_1.jsx)("br", {})] }, index)));
383
+ const fillContent = calculatedLines.map((line, index) => ((0, jsx_runtime_1.jsxs)(react_1.default.Fragment, { children: [hasStroke ? renderTextWithEmojiSpans(line, false) : line, index < calculatedLines.length - 1 && (0, jsx_runtime_1.jsx)("br", {})] }, index)));
384
+ const strokeContent = hasStroke ? 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))) : null;
396
385
  if (backgroundColor) {
397
386
  return ((0, jsx_runtime_1.jsx)("div", { style: positioningContainerStyle, children: (0, jsx_runtime_1.jsxs)("div", { style: {
398
387
  width: calculatedWidth,
@@ -400,10 +389,10 @@ function TextElement({ segment, scale = 1 }) {
400
389
  backgroundColor: (0, text_1.hexToRgba)(backgroundColor, backgroundOpacity),
401
390
  borderRadius: borderRadiusStyle,
402
391
  ...(hasStroke && { position: 'relative' }),
403
- }, 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 })] }) }));
392
+ }, 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: fillContent })] }) }));
404
393
  }
405
- 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
+ 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: fillContent })] }) }));
406
395
  }
407
- 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: renderStrokeText(segment.text) }), (0, jsx_runtime_1.jsx)("div", { style: textStyle, children: segment.text })] }) }));
396
+ 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: hasStroke ? renderTextWithEmojiSpans(segment.text, true) : segment.text }), (0, jsx_runtime_1.jsx)("div", { style: textStyle, children: hasStroke ? renderTextWithEmojiSpans(segment.text, false) : segment.text })] }) }));
408
397
  }
409
398
  exports.default = TextElement;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ugcinc",
3
- "version": "4.5.65",
3
+ "version": "4.5.67",
4
4
  "description": "TypeScript/JavaScript client for the UGC Inc API",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",