@pixldocs/canvas-renderer 0.5.94 → 0.5.96

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
@@ -415,33 +415,6 @@ function measureTextHeight(element) {
415
415
  return fallbackEstimateHeight(element);
416
416
  }
417
417
  }
418
- function getMinTextWidth(element) {
419
- if (element.type !== "text" || !element.text) {
420
- return typeof element.width === "number" ? element.width : 200;
421
- }
422
- try {
423
- const textbox = new fabric__namespace.Textbox(element.text, {
424
- width: 1e4,
425
- fontSize: element.fontSize || 16,
426
- fontFamily: element.fontFamily || "Open Sans",
427
- fontWeight: element.fontWeight || 400,
428
- fontStyle: element.fontStyle || "normal",
429
- lineHeight: element.lineHeight || 1.2,
430
- charSpacing: element.charSpacing || 0,
431
- splitByGrapheme: element.splitByGrapheme ?? element.wordWrap === "break-word",
432
- left: 0,
433
- top: 0
434
- });
435
- textbox.initDimensions();
436
- const lineWidths = textbox.__lineWidths;
437
- if (lineWidths && lineWidths.length > 0) {
438
- const maxLine = Math.max(...lineWidths);
439
- return Math.ceil(maxLine) + 2;
440
- }
441
- } catch (_) {
442
- }
443
- return typeof element.width === "number" ? element.width : 200;
444
- }
445
418
  function fallbackEstimateHeight(element) {
446
419
  if (element.type !== "text" || !element.text) {
447
420
  return element.height || 20;
@@ -2797,11 +2770,22 @@ const waitUntilFontsAvailable = async (fontFamilies, options) => {
2797
2770
  }
2798
2771
  };
2799
2772
  const clearFabricCharCache = () => {
2773
+ var _a;
2800
2774
  const fabricAny = fabric__namespace;
2775
+ if (fabricAny.cache && typeof fabricAny.cache.clearFontCache === "function") {
2776
+ fabricAny.cache.clearFontCache();
2777
+ }
2778
+ if (((_a = fabricAny.cache) == null ? void 0 : _a.charWidthsCache) instanceof Map) {
2779
+ fabricAny.cache.charWidthsCache.clear();
2780
+ }
2801
2781
  if (typeof fabricAny.charWidthsCache === "object" && fabricAny.charWidthsCache !== null) {
2802
- Object.keys(fabricAny.charWidthsCache).forEach((key) => {
2803
- delete fabricAny.charWidthsCache[key];
2804
- });
2782
+ if (fabricAny.charWidthsCache instanceof Map) {
2783
+ fabricAny.charWidthsCache.clear();
2784
+ } else {
2785
+ Object.keys(fabricAny.charWidthsCache).forEach((key) => {
2786
+ delete fabricAny.charWidthsCache[key];
2787
+ });
2788
+ }
2805
2789
  }
2806
2790
  if (typeof fabric__namespace.util !== "undefined" && typeof fabric__namespace.util.clearFabricFontCache === "function") {
2807
2791
  fabric__namespace.util.clearFabricFontCache();
@@ -5576,6 +5560,8 @@ function createText(element) {
5576
5560
  const targetScaleY = element.scaleY ?? 1;
5577
5561
  const textbox = new fabric__namespace.Textbox(text, {
5578
5562
  width: targetWidth,
5563
+ minWidth: 1,
5564
+ dynamicMinWidth: 0,
5579
5565
  scaleX: targetScaleX,
5580
5566
  scaleY: targetScaleY,
5581
5567
  fontSize,
@@ -5596,6 +5582,8 @@ function createText(element) {
5596
5582
  textbox.initDimensions();
5597
5583
  textbox.set({
5598
5584
  width: targetWidth,
5585
+ minWidth: 1,
5586
+ dynamicMinWidth: 0,
5599
5587
  scaleX: targetScaleX,
5600
5588
  scaleY: targetScaleY
5601
5589
  });
@@ -5605,6 +5593,7 @@ function createText(element) {
5605
5593
  const scaleYAfterSet = textbox.scaleY ?? 1;
5606
5594
  if (Math.abs(widthAfterSet - targetWidth) > 0.01 || Math.abs(scaleXAfterSet - targetScaleX) > 0.01 || Math.abs(scaleYAfterSet - targetScaleY) > 0.01) {
5607
5595
  textbox.width = targetWidth;
5596
+ textbox.dynamicMinWidth = 0;
5608
5597
  textbox.scaleX = targetScaleX;
5609
5598
  textbox.scaleY = targetScaleY;
5610
5599
  textbox.setCoords();
@@ -6451,6 +6440,48 @@ const PageCanvas = react.forwardRef(
6451
6440
  if (!canvas2) return false;
6452
6441
  return !!canvas2._currentTransform || !!canvas2.__isUserTransforming;
6453
6442
  }, []);
6443
+ const reflowTextboxesFromCurrentElements = react.useCallback((canvas2) => {
6444
+ const elementById = new Map(elementsRef.current.map((el) => [el.id, el]));
6445
+ let didReflow = false;
6446
+ const reflowObject = (obj) => {
6447
+ var _a;
6448
+ if (obj instanceof fabric__namespace.Group) {
6449
+ (_a = obj._objects) == null ? void 0 : _a.forEach(reflowObject);
6450
+ obj.dirty = true;
6451
+ return;
6452
+ }
6453
+ if (!(obj instanceof fabric__namespace.Textbox)) return;
6454
+ const id = getObjectId(obj);
6455
+ const element = id ? elementById.get(id) : void 0;
6456
+ if (!element) return;
6457
+ const targetWidth = Math.max(1, Number(element.width) > 0 ? Number(element.width) : Number(obj.width ?? 200));
6458
+ const overflowPolicy = element.overflowPolicy || "grow-and-push";
6459
+ const splitByGrapheme = overflowPolicy === "auto-shrink" ? false : element.splitByGrapheme ?? element.wordWrap === "break-word";
6460
+ obj.set({
6461
+ width: targetWidth,
6462
+ minWidth: 1,
6463
+ dynamicMinWidth: 0,
6464
+ text: element.text || "Text",
6465
+ fontSize: element.fontSize || 16,
6466
+ fontFamily: element.fontFamily || "Open Sans",
6467
+ fontWeight: element.fontWeight || 400,
6468
+ fontStyle: element.fontStyle || "normal",
6469
+ lineHeight: element.lineHeight || 1.2,
6470
+ charSpacing: element.charSpacing || 0,
6471
+ splitByGrapheme
6472
+ });
6473
+ obj.initDimensions();
6474
+ if (Math.abs((obj.width ?? 0) - targetWidth) > 0.01) {
6475
+ obj.width = targetWidth;
6476
+ }
6477
+ obj.dynamicMinWidth = 0;
6478
+ obj.setCoords();
6479
+ obj.dirty = true;
6480
+ didReflow = true;
6481
+ };
6482
+ canvas2.getObjects().forEach(reflowObject);
6483
+ if (didReflow) canvas2.requestRenderAll();
6484
+ }, []);
6454
6485
  react.useEffect(() => {
6455
6486
  if (!canvasElRef.current) return;
6456
6487
  const zoom2 = workspaceZoom || 1;
@@ -6531,6 +6562,8 @@ const PageCanvas = react.forwardRef(
6531
6562
  };
6532
6563
  initFonts();
6533
6564
  const persistTextDimensionsAfterFontLoad = (canvas2) => {
6565
+ reflowTextboxesFromCurrentElements(canvas2);
6566
+ if (isPreviewMode) return;
6534
6567
  const state = useEditorStore.getState();
6535
6568
  const page = state.canvas.pages.find((p) => p.id === pageId);
6536
6569
  if (!page) return;
@@ -7735,7 +7768,7 @@ const PageCanvas = react.forwardRef(
7735
7768
  react.useEffect(() => {
7736
7769
  const fc = fabricRef.current;
7737
7770
  if (!fc) return;
7738
- if (!ready && !isPreviewMode) {
7771
+ if (!ready) {
7739
7772
  hasClearedCachesBeforeFirstSyncRef.current = false;
7740
7773
  return;
7741
7774
  }
@@ -9127,10 +9160,11 @@ const PageCanvas = react.forwardRef(
9127
9160
  text = result;
9128
9161
  }
9129
9162
  }
9130
- const minWidth = getMinTextWidth(element);
9131
- const textboxWidth = overflowPolicy === "auto-shrink" ? fixedWidth : Math.max(storedWidth, minWidth);
9163
+ const textboxWidth = fixedWidth;
9132
9164
  obj.set({
9133
9165
  width: textboxWidth,
9166
+ minWidth: 1,
9167
+ dynamicMinWidth: 0,
9134
9168
  fontSize,
9135
9169
  fontFamily: element.fontFamily || "Open Sans",
9136
9170
  fill: element.fill || "#1a1a1a",
@@ -9150,6 +9184,7 @@ const PageCanvas = react.forwardRef(
9150
9184
  if (Math.abs((obj.width ?? 0) - textboxWidth) > 0.01) {
9151
9185
  obj.width = textboxWidth;
9152
9186
  }
9187
+ obj.dynamicMinWidth = 0;
9153
9188
  obj.setCoords();
9154
9189
  obj.dirty = true;
9155
9190
  try {
@@ -12938,7 +12973,6 @@ function PixldocsPreview(props) {
12938
12973
  const [isLoading, setIsLoading] = react.useState(false);
12939
12974
  const [fontsReady, setFontsReady] = react.useState(false);
12940
12975
  const [canvasSettled, setCanvasSettled] = react.useState(false);
12941
- const [stabilizationPass, setStabilizationPass] = react.useState(0);
12942
12976
  const isResolveMode = !("config" in props && props.config);
12943
12977
  react.useEffect(() => {
12944
12978
  if (!isResolveMode) {
@@ -13009,21 +13043,16 @@ function PixldocsPreview(props) {
13009
13043
  isResolveMode ? props.themeId : void 0
13010
13044
  ]);
13011
13045
  const config = isResolveMode ? resolvedConfig : props.config;
13012
- const previewKey = react.useMemo(
13013
- () => `${pageIndex}-${stabilizationPass}`,
13014
- [pageIndex, stabilizationPass]
13015
- );
13046
+ const previewKey = react.useMemo(() => `${pageIndex}`, [pageIndex]);
13016
13047
  react.useEffect(() => {
13017
13048
  if (isResolveMode) return;
13018
13049
  if (!config) {
13019
13050
  setFontsReady(false);
13020
13051
  setCanvasSettled(false);
13021
- setStabilizationPass(0);
13022
13052
  return;
13023
13053
  }
13024
13054
  setFontsReady(false);
13025
13055
  setCanvasSettled(false);
13026
- setStabilizationPass(0);
13027
13056
  let cancelled = false;
13028
13057
  const hasAutoShrink = configHasAutoShrinkText$1(config);
13029
13058
  const waitMs = hasAutoShrink ? 4e3 : 1800;
@@ -13046,16 +13075,10 @@ function PixldocsPreview(props) {
13046
13075
  };
13047
13076
  }, [isResolveMode, config]);
13048
13077
  const handleCanvasReady = react.useCallback(() => {
13049
- if (stabilizationPass === 0) {
13050
- console.log(PREVIEW_DEBUG_PREFIX, "canvas-ready-pass", { pageIndex, stabilizationPass, action: "stabilize-again" });
13051
- setCanvasSettled(false);
13052
- setStabilizationPass(1);
13053
- return;
13054
- }
13055
- console.log(PREVIEW_DEBUG_PREFIX, "canvas-ready-pass", { pageIndex, stabilizationPass, action: "settled" });
13078
+ console.log(PREVIEW_DEBUG_PREFIX, "canvas-ready", { pageIndex, action: "settled" });
13056
13079
  setCanvasSettled(true);
13057
13080
  onReady == null ? void 0 : onReady();
13058
- }, [onReady, pageIndex, stabilizationPass]);
13081
+ }, [onReady, pageIndex]);
13059
13082
  if (isLoading) {
13060
13083
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className, style: { ...style, display: "flex", alignItems: "center", justifyContent: "center", minHeight: 200 }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "#888", fontSize: 14 }, children: "Loading preview..." }) });
13061
13084
  }