@pixldocs/canvas-renderer 0.5.43 → 0.5.44

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.44";
225
225
 
226
226
  export declare interface PageSettings {
227
227
  backgroundColor?: string;
package/dist/index.js CHANGED
@@ -4889,40 +4889,107 @@ 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 shadowLayer = "";
4923
+ if (hasShadow) {
4924
+ const ox = Number(shadow.offsetX ?? 0) || 0;
4925
+ const oy = Number(shadow.offsetY ?? 0) || 0;
4926
+ const blur = Math.max(0, Number(shadow.blur ?? 0));
4927
+ const shadowColor = String(shadow.color);
4928
+ const shadowBgPath = hasBg ? `<path d="${bgD}" fill="${escapeXmlAttr(shadowColor)}" />` : "";
4929
+ const inner = extractGInnerMarkup(svg);
4930
+ const recoloredText = recolorSvgFills(inner, shadowColor);
4931
+ const layers = [];
4932
+ if (blur > 0) {
4933
+ const ringCount = Math.min(6, Math.max(2, Math.round(blur / 2)));
4934
+ for (let i = 1; i <= ringCount; i++) {
4935
+ const t = i / ringCount;
4936
+ const dist = blur * t * 0.6;
4937
+ const op = (0.18 * (1 - t * 0.7)).toFixed(3);
4938
+ const ringOffsets = [
4939
+ [dist, 0],
4940
+ [-dist, 0],
4941
+ [0, dist],
4942
+ [0, -dist],
4943
+ [dist * 0.7, dist * 0.7],
4944
+ [-dist * 0.7, dist * 0.7],
4945
+ [dist * 0.7, -dist * 0.7],
4946
+ [-dist * 0.7, -dist * 0.7]
4947
+ ];
4948
+ for (const [dx, dy] of ringOffsets) {
4949
+ layers.push(
4950
+ `<g transform="translate(${(ox + dx).toFixed(3)} ${(oy + dy).toFixed(3)})" opacity="${op}">${shadowBgPath}${recoloredText}</g>`
4951
+ );
4952
+ }
4953
+ }
4954
+ layers.push(
4955
+ `<g transform="translate(${ox.toFixed(3)} ${oy.toFixed(3)})" opacity="0.25">${shadowBgPath}${recoloredText}</g>`
4956
+ );
4957
+ } else {
4958
+ layers.push(
4959
+ `<g transform="translate(${ox.toFixed(3)} ${oy.toFixed(3)})">${shadowBgPath}${recoloredText}</g>`
4960
+ );
4961
+ }
4962
+ shadowLayer = layers.join("");
4963
+ }
4917
4964
  const openTagMatch = svg.match(/^\s*<g\b[^>]*>/);
4965
+ const inserted = shadowLayer + bgPath;
4918
4966
  if (openTagMatch) {
4919
4967
  const openTag = openTagMatch[0];
4920
- return svg.replace(openTag, openTag + bgPath);
4968
+ return svg.replace(openTag, openTag + inserted);
4921
4969
  }
4922
- return `<g>${bgPath}${svg}</g>`;
4970
+ return `<g>${inserted}${svg}</g>`;
4923
4971
  };
4924
4972
  }
4925
4973
  }
4974
+ function recolorSvgFills(svg, color) {
4975
+ const safe = escapeXmlAttr(color);
4976
+ let out = svg.replace(
4977
+ /(<(?:text|tspan|path|rect)\b[^>]*?\sfill=")([^"]*)("[^>]*>)/gi,
4978
+ (_m, pre, val, post) => {
4979
+ const v = val.trim().toLowerCase();
4980
+ if (v === "none" || v === "transparent") return pre + val + post;
4981
+ return pre + safe + post;
4982
+ }
4983
+ );
4984
+ out = out.replace(
4985
+ /(<(?:text|tspan|path|rect)\b[^>]*?\sstyle=")([^"]*)("[^>]*>)/gi,
4986
+ (_m, pre, styleVal, post) => {
4987
+ const replaced = styleVal.replace(/fill\s*:\s*[^;"]+/gi, `fill: ${color}`);
4988
+ return pre + replaced + post;
4989
+ }
4990
+ );
4991
+ return out;
4992
+ }
4926
4993
  function buildRoundedRectPathD(x, y, w, h, rTL, rTR, rBR, rBL) {
4927
4994
  const maxR = Math.min(w, h) / 2;
4928
4995
  const tl = Math.min(Math.max(0, rTL), maxR);
@@ -4946,6 +5013,13 @@ function buildRoundedRectPathD(x, y, w, h, rTL, rTR, rBR, rBL) {
4946
5013
  function escapeXmlAttr(s) {
4947
5014
  return String(s).replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
4948
5015
  }
5016
+ function extractGInnerMarkup(markup) {
5017
+ const openMatch = markup.match(/^\s*<g\b[^>]*>/);
5018
+ if (!openMatch) return markup;
5019
+ const closeIdx = markup.lastIndexOf("</g>");
5020
+ if (closeIdx <= openMatch[0].length) return markup;
5021
+ return markup.slice(openMatch[0].length, closeIdx);
5022
+ }
4949
5023
  const TRIANGLE_STROKE_MITER_LIMIT = 1e6;
4950
5024
  const toSafeNumber = (value, fallback = 0) => Number.isFinite(value) ? Math.max(0, Number(value)) : fallback;
4951
5025
  function normalizeShapeType(shapeType) {
@@ -12267,7 +12341,7 @@ function PixldocsPreview(props) {
12267
12341
  !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
12342
  ] });
12269
12343
  }
12270
- const PACKAGE_VERSION = "0.5.43";
12344
+ const PACKAGE_VERSION = "0.5.44";
12271
12345
  let __underlineFixInstalled = false;
12272
12346
  function installUnderlineFix(fab) {
12273
12347
  var _a;