Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
184 changes: 0 additions & 184 deletions src/App.css

This file was deleted.

5 changes: 5 additions & 0 deletions src/components/Canvas/BarcodeObject.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ export function BarcodeObject({
if (opts) {
const canvas = document.createElement("canvas");
try {
// buildBwipOptions returns Record<string, unknown> on purpose: the
// option fields differ across barcode types (ean13 vs code128 vs …)
// and per-type narrowing would duplicate the switch already in
// buildBwipOptions. bwip-js' toCanvas signature uses a strict
// literal-string union, so the structural cast bridges the two.
bwipjs.toCanvas(canvas, opts as unknown as Parameters<typeof bwipjs.toCanvas>[1]);
barcodeCanvas = canvas;
} catch (e) {
Expand Down
27 changes: 17 additions & 10 deletions src/components/Canvas/KonvaObject.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState, useEffect } from "react";
import { useState, useEffect, useRef } from "react";
import { getFontFamily } from "../../lib/fontCache";
import { useFontCacheVersion } from "../../hooks/useFontCacheVersion";
import {
Expand Down Expand Up @@ -246,11 +246,18 @@ function ImageObject({
const y = offsetY + dotsToPx(obj.y, scale, dpmm);

const [htmlImg, setHtmlImg] = useState<HTMLImageElement | null>(null);
// Reset the cached HTMLImageElement during render when the source changes,
// instead of inside an effect. The "set state during render on prop change"
// pattern is the official React workaround for what would otherwise be a
// setState-in-effect anti-pattern. The next render observes prevDataUrl
// already updated, so this does not loop.
const prevDataUrlRef = useRef<string | undefined>(cached?.dataUrl);
if (prevDataUrlRef.current !== cached?.dataUrl) {
prevDataUrlRef.current = cached?.dataUrl;
setHtmlImg(null);
}
useEffect(() => {
if (!cached) {
setHtmlImg(null); // eslint-disable-line react-hooks/set-state-in-effect
return;
}
if (!cached) return;
let active = true;
const img = new window.Image();
img.src = cached.dataUrl;
Expand All @@ -260,7 +267,7 @@ function ImageObject({
return () => {
active = false;
};
}, [cached?.dataUrl, cached]);
}, [cached]);

const handleDragMove = (e: Konva.KonvaEventObject<DragEvent>) => {
onChange({
Expand Down Expand Up @@ -376,7 +383,7 @@ function KonvaObjectInner({
let displayY = obj.y;
if (obj.positionType === "FT") {
if (obj.type === "text" || obj.type === "serial") {
const p = obj.props as { fontHeight: number; rotation: string };
const p = obj.props;
// ^FT places the origin at the baseline of the first character.
// The Konva anchor point after rotation sits at a different corner
// of the visual bounding box than the ZPL FT baseline origin:
Expand All @@ -402,7 +409,7 @@ function KonvaObjectInner({
// Konva rotates text around its top-left corner, but ZPL's ^FO anchor
// shifts with rotation. 15 dots is an empirically determined fixed offset.
if (obj.type === "text" || obj.type === "serial") {
const p = obj.props as { fontHeight: number; rotation: string };
const p = obj.props;
const ROTATION_OFFSET = 15; // dots — empirical canvas/ZPL alignment correction
if (p.rotation === "I") {
displayY -= ROTATION_OFFSET;
Expand Down Expand Up @@ -435,7 +442,7 @@ function KonvaObjectInner({
let finalY = pxToDots(e.target.y() - offsetY, scale, dpmm);

if (obj.type === "text" || obj.type === "serial") {
const p = obj.props as { fontHeight: number; rotation: string };
const p = obj.props;
const ROTATION_OFFSET = 15;
if (p.rotation === "I") {
finalY += ROTATION_OFFSET;
Expand All @@ -451,7 +458,7 @@ function KonvaObjectInner({
// instead of the ZPL baseline coordinate, causing a vertical jump on re-render.
if (obj.positionType === "FT") {
if (obj.type === "text" || obj.type === "serial") {
const p = obj.props as { fontHeight: number; rotation: string };
const p = obj.props;
const renderedH = p.fontHeight / 1.3;
if (p.rotation === "N") {
finalY += p.fontHeight;
Expand Down