@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.d.ts CHANGED
@@ -221,7 +221,7 @@ export declare function normalizeFontFamily(fontStack: string): string;
221
221
  * Package version banner. Bump alongside package.json so we can confirm
222
222
  * (via browser:log) that the deployed bundle matches the expected build.
223
223
  */
224
- export declare const PACKAGE_VERSION = "0.5.43";
224
+ export declare const PACKAGE_VERSION = "0.5.45";
225
225
 
226
226
  export declare interface PageSettings {
227
227
  backgroundColor?: string;
package/dist/index.js CHANGED
@@ -4889,40 +4889,109 @@ function applyTextBackground(obj, cfg) {
4889
4889
  const originalToSVG = (_a = obj.toSVG) == null ? void 0 : _a.bind(obj);
4890
4890
  if (typeof originalToSVG === "function") {
4891
4891
  obj.toSVG = function(reviver) {
4892
- const svg = originalToSVG(reviver);
4892
+ let svg = originalToSVG(reviver);
4893
4893
  const bg = this[PD_BG_KEY];
4894
- if (!hasTextBackground(bg)) return svg;
4894
+ const shadow = this.shadow;
4895
+ const hasBg = hasTextBackground(bg);
4896
+ const hasShadow = !!shadow && !!shadow.color && shadow.color !== "transparent";
4897
+ if (!hasBg && !hasShadow) return svg;
4895
4898
  const w = this.width ?? 0;
4896
4899
  const h = this.height ?? 0;
4897
- const pT = Math.max(0, Number(bg.padTop ?? 0));
4898
- const pR = Math.max(0, Number(bg.padRight ?? 0));
4899
- const pB = Math.max(0, Number(bg.padBottom ?? 0));
4900
- const pL = Math.max(0, Number(bg.padLeft ?? 0));
4900
+ const pT = Math.max(0, Number((bg == null ? void 0 : bg.padTop) ?? 0));
4901
+ const pR = Math.max(0, Number((bg == null ? void 0 : bg.padRight) ?? 0));
4902
+ const pB = Math.max(0, Number((bg == null ? void 0 : bg.padBottom) ?? 0));
4903
+ const pL = Math.max(0, Number((bg == null ? void 0 : bg.padLeft) ?? 0));
4901
4904
  const x = -w / 2 - pL;
4902
4905
  const y = -h / 2 - pT;
4903
4906
  const bgW = w + pL + pR;
4904
4907
  const bgH = h + pT + pB;
4905
- const d = buildRoundedRectPathD(
4908
+ const bgD = buildRoundedRectPathD(
4906
4909
  x,
4907
4910
  y,
4908
4911
  bgW,
4909
4912
  bgH,
4910
- bg.rxTL ?? 0,
4911
- bg.rxTR ?? 0,
4912
- bg.rxBR ?? 0,
4913
- bg.rxBL ?? 0
4913
+ (bg == null ? void 0 : bg.rxTL) ?? 0,
4914
+ (bg == null ? void 0 : bg.rxTR) ?? 0,
4915
+ (bg == null ? void 0 : bg.rxBR) ?? 0,
4916
+ (bg == null ? void 0 : bg.rxBL) ?? 0
4914
4917
  );
4915
- const fill = bg.color;
4916
- const bgPath = `<path d="${d}" fill="${escapeXmlAttr(fill)}" />`;
4918
+ const bgFill = (bg == null ? void 0 : bg.color) || "";
4919
+ const bgPath = hasBg ? `<path d="${bgD}" fill="${escapeXmlAttr(bgFill)}" />` : "";
4920
+ svg = svg.replace(/style="[^"]*filter:\s*url\([^)]+\)[^"]*"/i, "");
4921
+ svg = svg.replace(/<filter[\s\S]*?<\/filter>/gi, "");
4922
+ let bgShadowLayer = "";
4923
+ let textShadowLayer = "";
4924
+ if (hasShadow) {
4925
+ const ox = Number(shadow.offsetX ?? 0) || 0;
4926
+ const oy = Number(shadow.offsetY ?? 0) || 0;
4927
+ const blur = Math.max(0, Number(shadow.blur ?? 0));
4928
+ const shadowColor = String(shadow.color);
4929
+ const shadowBgPath = hasBg ? `<path d="${bgD}" fill="${escapeXmlAttr(shadowColor)}" />` : "";
4930
+ const inner = extractGInnerMarkup(svg);
4931
+ const recoloredText = recolorSvgFills(inner, shadowColor);
4932
+ const bgLayers = [];
4933
+ const textLayers = [];
4934
+ const pushShadowPass = (tx, ty, opacity) => {
4935
+ const attrs = `transform="translate(${tx.toFixed(3)} ${ty.toFixed(3)})"${opacity ? ` opacity="${opacity}"` : ""}`;
4936
+ if (shadowBgPath) bgLayers.push(`<g ${attrs}>${shadowBgPath}</g>`);
4937
+ if (recoloredText) textLayers.push(`<g ${attrs}>${recoloredText}</g>`);
4938
+ };
4939
+ if (blur > 0) {
4940
+ const ringCount = Math.min(6, Math.max(2, Math.round(blur / 2)));
4941
+ for (let i = 1; i <= ringCount; i++) {
4942
+ const t = i / ringCount;
4943
+ const dist = blur * t * 0.6;
4944
+ const op = (0.18 * (1 - t * 0.7)).toFixed(3);
4945
+ const ringOffsets = [
4946
+ [dist, 0],
4947
+ [-dist, 0],
4948
+ [0, dist],
4949
+ [0, -dist],
4950
+ [dist * 0.7, dist * 0.7],
4951
+ [-dist * 0.7, dist * 0.7],
4952
+ [dist * 0.7, -dist * 0.7],
4953
+ [-dist * 0.7, -dist * 0.7]
4954
+ ];
4955
+ for (const [dx, dy] of ringOffsets) {
4956
+ pushShadowPass(ox + dx, oy + dy, op);
4957
+ }
4958
+ }
4959
+ pushShadowPass(ox, oy, "0.25");
4960
+ } else {
4961
+ pushShadowPass(ox, oy);
4962
+ }
4963
+ bgShadowLayer = bgLayers.join("");
4964
+ textShadowLayer = textLayers.join("");
4965
+ }
4917
4966
  const openTagMatch = svg.match(/^\s*<g\b[^>]*>/);
4967
+ const inserted = bgShadowLayer + bgPath + textShadowLayer;
4918
4968
  if (openTagMatch) {
4919
4969
  const openTag = openTagMatch[0];
4920
- return svg.replace(openTag, openTag + bgPath);
4970
+ return svg.replace(openTag, openTag + inserted);
4921
4971
  }
4922
- return `<g>${bgPath}${svg}</g>`;
4972
+ return `<g>${inserted}${svg}</g>`;
4923
4973
  };
4924
4974
  }
4925
4975
  }
4976
+ function recolorSvgFills(svg, color) {
4977
+ const safe = escapeXmlAttr(color);
4978
+ let out = svg.replace(
4979
+ /(<(?:text|tspan|path|rect)\b[^>]*?\sfill=")([^"]*)("[^>]*>)/gi,
4980
+ (_m, pre, val, post) => {
4981
+ const v = val.trim().toLowerCase();
4982
+ if (v === "none" || v === "transparent") return pre + val + post;
4983
+ return pre + safe + post;
4984
+ }
4985
+ );
4986
+ out = out.replace(
4987
+ /(<(?:text|tspan|path|rect)\b[^>]*?\sstyle=")([^"]*)("[^>]*>)/gi,
4988
+ (_m, pre, styleVal, post) => {
4989
+ const replaced = styleVal.replace(/fill\s*:\s*[^;"]+/gi, `fill: ${color}`);
4990
+ return pre + replaced + post;
4991
+ }
4992
+ );
4993
+ return out;
4994
+ }
4926
4995
  function buildRoundedRectPathD(x, y, w, h, rTL, rTR, rBR, rBL) {
4927
4996
  const maxR = Math.min(w, h) / 2;
4928
4997
  const tl = Math.min(Math.max(0, rTL), maxR);
@@ -4946,6 +5015,13 @@ function buildRoundedRectPathD(x, y, w, h, rTL, rTR, rBR, rBL) {
4946
5015
  function escapeXmlAttr(s) {
4947
5016
  return String(s).replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
4948
5017
  }
5018
+ function extractGInnerMarkup(markup) {
5019
+ const openMatch = markup.match(/^\s*<g\b[^>]*>/);
5020
+ if (!openMatch) return markup;
5021
+ const closeIdx = markup.lastIndexOf("</g>");
5022
+ if (closeIdx <= openMatch[0].length) return markup;
5023
+ return markup.slice(openMatch[0].length, closeIdx);
5024
+ }
4949
5025
  const TRIANGLE_STROKE_MITER_LIMIT = 1e6;
4950
5026
  const toSafeNumber = (value, fallback = 0) => Number.isFinite(value) ? Math.max(0, Number(value)) : fallback;
4951
5027
  function normalizeShapeType(shapeType) {
@@ -12267,7 +12343,7 @@ function PixldocsPreview(props) {
12267
12343
  !canvasSettled && /* @__PURE__ */ jsx("div", { style: { position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center", minHeight: 200 }, children: /* @__PURE__ */ jsx("div", { style: { color: "#888", fontSize: 14 }, children: "Loading preview..." }) })
12268
12344
  ] });
12269
12345
  }
12270
- const PACKAGE_VERSION = "0.5.43";
12346
+ const PACKAGE_VERSION = "0.5.45";
12271
12347
  let __underlineFixInstalled = false;
12272
12348
  function installUnderlineFix(fab) {
12273
12349
  var _a;