@pixldocs/canvas-renderer 0.5.43 → 0.5.45

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.
package/dist/index.cjs CHANGED
@@ -4908,40 +4908,109 @@ function applyTextBackground(obj, cfg) {
4908
4908
  const originalToSVG = (_a = obj.toSVG) == null ? void 0 : _a.bind(obj);
4909
4909
  if (typeof originalToSVG === "function") {
4910
4910
  obj.toSVG = function(reviver) {
4911
- const svg = originalToSVG(reviver);
4911
+ let svg = originalToSVG(reviver);
4912
4912
  const bg = this[PD_BG_KEY];
4913
- if (!hasTextBackground(bg)) return svg;
4913
+ const shadow = this.shadow;
4914
+ const hasBg = hasTextBackground(bg);
4915
+ const hasShadow = !!shadow && !!shadow.color && shadow.color !== "transparent";
4916
+ if (!hasBg && !hasShadow) return svg;
4914
4917
  const w = this.width ?? 0;
4915
4918
  const h = this.height ?? 0;
4916
- const pT = Math.max(0, Number(bg.padTop ?? 0));
4917
- const pR = Math.max(0, Number(bg.padRight ?? 0));
4918
- const pB = Math.max(0, Number(bg.padBottom ?? 0));
4919
- const pL = Math.max(0, Number(bg.padLeft ?? 0));
4919
+ const pT = Math.max(0, Number((bg == null ? void 0 : bg.padTop) ?? 0));
4920
+ const pR = Math.max(0, Number((bg == null ? void 0 : bg.padRight) ?? 0));
4921
+ const pB = Math.max(0, Number((bg == null ? void 0 : bg.padBottom) ?? 0));
4922
+ const pL = Math.max(0, Number((bg == null ? void 0 : bg.padLeft) ?? 0));
4920
4923
  const x = -w / 2 - pL;
4921
4924
  const y = -h / 2 - pT;
4922
4925
  const bgW = w + pL + pR;
4923
4926
  const bgH = h + pT + pB;
4924
- const d = buildRoundedRectPathD(
4927
+ const bgD = buildRoundedRectPathD(
4925
4928
  x,
4926
4929
  y,
4927
4930
  bgW,
4928
4931
  bgH,
4929
- bg.rxTL ?? 0,
4930
- bg.rxTR ?? 0,
4931
- bg.rxBR ?? 0,
4932
- bg.rxBL ?? 0
4932
+ (bg == null ? void 0 : bg.rxTL) ?? 0,
4933
+ (bg == null ? void 0 : bg.rxTR) ?? 0,
4934
+ (bg == null ? void 0 : bg.rxBR) ?? 0,
4935
+ (bg == null ? void 0 : bg.rxBL) ?? 0
4933
4936
  );
4934
- const fill = bg.color;
4935
- const bgPath = `<path d="${d}" fill="${escapeXmlAttr(fill)}" />`;
4937
+ const bgFill = (bg == null ? void 0 : bg.color) || "";
4938
+ const bgPath = hasBg ? `<path d="${bgD}" fill="${escapeXmlAttr(bgFill)}" />` : "";
4939
+ svg = svg.replace(/style="[^"]*filter:\s*url\([^)]+\)[^"]*"/i, "");
4940
+ svg = svg.replace(/<filter[\s\S]*?<\/filter>/gi, "");
4941
+ let bgShadowLayer = "";
4942
+ let textShadowLayer = "";
4943
+ if (hasShadow) {
4944
+ const ox = Number(shadow.offsetX ?? 0) || 0;
4945
+ const oy = Number(shadow.offsetY ?? 0) || 0;
4946
+ const blur = Math.max(0, Number(shadow.blur ?? 0));
4947
+ const shadowColor = String(shadow.color);
4948
+ const shadowBgPath = hasBg ? `<path d="${bgD}" fill="${escapeXmlAttr(shadowColor)}" />` : "";
4949
+ const inner = extractGInnerMarkup(svg);
4950
+ const recoloredText = recolorSvgFills(inner, shadowColor);
4951
+ const bgLayers = [];
4952
+ const textLayers = [];
4953
+ const pushShadowPass = (tx, ty, opacity) => {
4954
+ const attrs = `transform="translate(${tx.toFixed(3)} ${ty.toFixed(3)})"${opacity ? ` opacity="${opacity}"` : ""}`;
4955
+ if (shadowBgPath) bgLayers.push(`<g ${attrs}>${shadowBgPath}</g>`);
4956
+ if (recoloredText) textLayers.push(`<g ${attrs}>${recoloredText}</g>`);
4957
+ };
4958
+ if (blur > 0) {
4959
+ const ringCount = Math.min(6, Math.max(2, Math.round(blur / 2)));
4960
+ for (let i = 1; i <= ringCount; i++) {
4961
+ const t = i / ringCount;
4962
+ const dist = blur * t * 0.6;
4963
+ const op = (0.18 * (1 - t * 0.7)).toFixed(3);
4964
+ const ringOffsets = [
4965
+ [dist, 0],
4966
+ [-dist, 0],
4967
+ [0, dist],
4968
+ [0, -dist],
4969
+ [dist * 0.7, dist * 0.7],
4970
+ [-dist * 0.7, dist * 0.7],
4971
+ [dist * 0.7, -dist * 0.7],
4972
+ [-dist * 0.7, -dist * 0.7]
4973
+ ];
4974
+ for (const [dx, dy] of ringOffsets) {
4975
+ pushShadowPass(ox + dx, oy + dy, op);
4976
+ }
4977
+ }
4978
+ pushShadowPass(ox, oy, "0.25");
4979
+ } else {
4980
+ pushShadowPass(ox, oy);
4981
+ }
4982
+ bgShadowLayer = bgLayers.join("");
4983
+ textShadowLayer = textLayers.join("");
4984
+ }
4936
4985
  const openTagMatch = svg.match(/^\s*<g\b[^>]*>/);
4986
+ const inserted = bgShadowLayer + bgPath + textShadowLayer;
4937
4987
  if (openTagMatch) {
4938
4988
  const openTag = openTagMatch[0];
4939
- return svg.replace(openTag, openTag + bgPath);
4989
+ return svg.replace(openTag, openTag + inserted);
4940
4990
  }
4941
- return `<g>${bgPath}${svg}</g>`;
4991
+ return `<g>${inserted}${svg}</g>`;
4942
4992
  };
4943
4993
  }
4944
4994
  }
4995
+ function recolorSvgFills(svg, color) {
4996
+ const safe = escapeXmlAttr(color);
4997
+ let out = svg.replace(
4998
+ /(<(?:text|tspan|path|rect)\b[^>]*?\sfill=")([^"]*)("[^>]*>)/gi,
4999
+ (_m, pre, val, post) => {
5000
+ const v = val.trim().toLowerCase();
5001
+ if (v === "none" || v === "transparent") return pre + val + post;
5002
+ return pre + safe + post;
5003
+ }
5004
+ );
5005
+ out = out.replace(
5006
+ /(<(?:text|tspan|path|rect)\b[^>]*?\sstyle=")([^"]*)("[^>]*>)/gi,
5007
+ (_m, pre, styleVal, post) => {
5008
+ const replaced = styleVal.replace(/fill\s*:\s*[^;"]+/gi, `fill: ${color}`);
5009
+ return pre + replaced + post;
5010
+ }
5011
+ );
5012
+ return out;
5013
+ }
4945
5014
  function buildRoundedRectPathD(x, y, w, h, rTL, rTR, rBR, rBL) {
4946
5015
  const maxR = Math.min(w, h) / 2;
4947
5016
  const tl = Math.min(Math.max(0, rTL), maxR);
@@ -4965,6 +5034,13 @@ function buildRoundedRectPathD(x, y, w, h, rTL, rTR, rBR, rBL) {
4965
5034
  function escapeXmlAttr(s) {
4966
5035
  return String(s).replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
4967
5036
  }
5037
+ function extractGInnerMarkup(markup) {
5038
+ const openMatch = markup.match(/^\s*<g\b[^>]*>/);
5039
+ if (!openMatch) return markup;
5040
+ const closeIdx = markup.lastIndexOf("</g>");
5041
+ if (closeIdx <= openMatch[0].length) return markup;
5042
+ return markup.slice(openMatch[0].length, closeIdx);
5043
+ }
4968
5044
  const TRIANGLE_STROKE_MITER_LIMIT = 1e6;
4969
5045
  const toSafeNumber = (value, fallback = 0) => Number.isFinite(value) ? Math.max(0, Number(value)) : fallback;
4970
5046
  function normalizeShapeType(shapeType) {
@@ -12286,7 +12362,7 @@ function PixldocsPreview(props) {
12286
12362
  !canvasSettled && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center", minHeight: 200 }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "#888", fontSize: 14 }, children: "Loading preview..." }) })
12287
12363
  ] });
12288
12364
  }
12289
- const PACKAGE_VERSION = "0.5.43";
12365
+ const PACKAGE_VERSION = "0.5.45";
12290
12366
  let __underlineFixInstalled = false;
12291
12367
  function installUnderlineFix(fab) {
12292
12368
  var _a;