()(
}),
{
name: 'zpl-designer-session',
- version: 2,
+ version: 3,
migrate: (persistedState, version) => migrateLegacy(persistedState, version) as LabelState,
storage: createJSONStorage(() => localStorage),
partialize: (state) => ({
diff --git a/src/test/shapeRegression.test.ts b/src/test/shapeRegression.test.ts
index 56d7473c..03a87be6 100644
--- a/src/test/shapeRegression.test.ts
+++ b/src/test/shapeRegression.test.ts
@@ -8,7 +8,7 @@ import { shapeTestCases } from "../../tests/fixtures/shapeTestCases";
import { renderShape } from "../lib/shapeRender";
/**
- * Pixel regression for shape primitives (box / ellipse / circle / line),
+ * Pixel regression for shape primitives (box / ellipse / line),
* the geometric counterpart of `visualRegression.test.ts` (which covers
* barcodes via bwip-js). Each test:
*
diff --git a/src/types/ObjectType.ts b/src/types/ObjectType.ts
index fc0748d2..3c0cc216 100644
--- a/src/types/ObjectType.ts
+++ b/src/types/ObjectType.ts
@@ -88,12 +88,14 @@ export interface ObjectTypeDefinition {
*/
interpretationLocked?: boolean;
/**
- * True if the shape requires a 1:1 aspect ratio (e.g. circle: a single
- * diameter). The transformer restricts to corner anchors and forces the
- * resize bbox to stay square so visual feedback during drag matches the
- * uniform `commitTransform` applied on release.
+ * Marks types whose resize must keep a 1:1 aspect ratio. The transformer
+ * restricts to corner anchors and forces the resize bbox to stay square,
+ * so visual feedback during drag matches the uniform `commitTransform`
+ * applied on release. A predicate form supports per-instance opt-in
+ * (e.g. ellipse with `lockAspect: true`); `true` applies to every
+ * instance of the type (e.g. QR / DataMatrix).
*/
- uniformScale?: boolean;
+ uniformScale?: boolean | ((props: P) => boolean);
toZPL: (obj: LabelObjectBase & { props: P }) => string;
/**
* Optional hook to enforce type-specific invariants on incoming changes
diff --git a/tests/fixtures/shapeTestCases.ts b/tests/fixtures/shapeTestCases.ts
index 0515f784..65d9b707 100644
--- a/tests/fixtures/shapeTestCases.ts
+++ b/tests/fixtures/shapeTestCases.ts
@@ -1,8 +1,8 @@
import type { LabelObject } from "../../src/types/Group";
/**
- * Pixel-regression cases for the geometric primitives (box, line, ellipse,
- * circle) — analogous to `testCases.ts` for barcodes. Each entry pairs a
+ * Pixel-regression cases for the geometric primitives (box, line, ellipse) —
+ * analogous to `testCases.ts` for barcodes. Each entry pairs a
* canonical `LabelObject` (used by `renderShape` to produce the local
* canvas) with the ZPL Labelary should render as the reference.
*
@@ -17,7 +17,7 @@ import type { LabelObject } from "../../src/types/Group";
* Initial set deliberately covers the geometry-asymmetry cases:
* - thick outline boxes (^GB thickness extrudes inward)
* - horizontal / vertical lines of varying thickness
- * - ellipse + circle outline (^GE thickness behaviour)
+ * - ellipse outline (^GE thickness behaviour) including square (^GC)
* Anti-aliasing-only cases (thickness 1, filled solid) are kept too as a
* baseline that should match trivially.
*
@@ -117,11 +117,11 @@ export const shapeTestCases: ShapeTestCase[] = [
id: "shape_circle_outline",
obj: {
id: "8",
- type: "circle",
+ type: "ellipse",
x: 100,
y: 100,
rotation: 0,
- props: { diameter: 200, thickness: 8, filled: false, color: "B" },
+ props: { width: 200, height: 200, thickness: 8, filled: false, color: "B", lockAspect: true },
},
zpl_input: "^XA^FO100,100^GE200,200,8,B^FS^XZ",
image_ref: "shape_circle_outline.png",