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
12 changes: 9 additions & 3 deletions src/components/Canvas/hooks/useKonvaTransformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,12 +190,18 @@ export function useKonvaTransformer({
}, [selectedIds, selectedTypesKey, selectedSignature, stageRef, transformerRef]);

const resizeEnabled = selectedIds.length <= 1;
const singleType =
selectedIds.length === 1
? objects.find((o) => o.id === selectedIds[0])?.type ?? ""
: "";
const enabledAnchors: string[] | undefined =
selectedIds.length > 1
? []
: BARCODE_1D_TYPES.has(objects.find((o) => o.id === selectedIds[0])?.type ?? "")
? ["top-center", "bottom-center"]
: undefined;
: ObjectRegistry[singleType]?.heightLocked
? []
: BARCODE_1D_TYPES.has(singleType)
? ["top-center", "bottom-center"]
: undefined;
const isFreeResize = enabledAnchors === undefined;

/** Reset all transform-time state. Idempotent; safe to call from any exit path. */
Expand Down
10 changes: 7 additions & 3 deletions src/registry/barcode1d.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { ObjectTypeDefinition, ObjectGroup, LabelObjectBase } from '../type
import { useT } from '../lib/useT';
import { inputCls, labelCls } from '../components/Properties/styles';
import { fieldPos } from './zplHelpers';
import { commitHeightTransform } from './transformHelpers';

export interface Barcode1DProps {
content: string;
Expand Down Expand Up @@ -29,6 +30,8 @@ interface Barcode1DConfig {
* here ensures Labelary uses the same ratio as the canvas rendering.
*/
byRatio?: number;
/** See {@link ObjectTypeDefinition.heightLocked}. */
heightLocked?: boolean;
}

interface BarcodeLocale {
Expand All @@ -53,10 +56,9 @@ export function createBarcode1D(config: Barcode1DConfig): ObjectTypeDefinition<B
checkDigit: false,
},
defaultSize: { width: 300, height: 120 },
heightLocked: config.heightLocked,

commitTransform: (obj, { sy, snap }) => ({
height: Math.max(1, snap(Math.round(obj.props.height * sy))),
}),
commitTransform: config.heightLocked ? undefined : commitHeightTransform,

toZPL: (obj: LabelObjectBase & { props: Barcode1DProps }) => {
const p = obj.props;
Expand Down Expand Up @@ -95,6 +97,8 @@ export function createBarcode1D(config: Barcode1DConfig): ObjectTypeDefinition<B
className={inputCls}
value={p.height}
min={1}
disabled={config.heightLocked}
readOnly={config.heightLocked}
onChange={(e) => onChange({ height: Number(e.target.value) })}
/>
</div>
Expand Down
3 changes: 3 additions & 0 deletions src/registry/code128.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { ObjectTypeDefinition } from '../types/ObjectType';
import { useT } from '../lib/useT';
import { inputCls, labelCls } from '../components/Properties/styles';
import { fieldPos } from './zplHelpers';
import { commitHeightTransform } from './transformHelpers';

export interface Code128Props {
content: string;
Expand All @@ -24,6 +25,8 @@ export const code128: ObjectTypeDefinition<Code128Props> = {
},
defaultSize: { width: 300, height: 120 },

commitTransform: commitHeightTransform,

toZPL: (obj) => {
const p = obj.props;
const interp = p.printInterpretation ? 'Y' : 'N';
Expand Down
3 changes: 3 additions & 0 deletions src/registry/code39.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { ObjectTypeDefinition } from '../types/ObjectType';
import { useT } from '../lib/useT';
import { inputCls, labelCls } from '../components/Properties/styles';
import { fieldPos } from './zplHelpers';
import { commitHeightTransform } from './transformHelpers';

export interface Code39Props {
content: string;
Expand All @@ -24,6 +25,8 @@ export const code39: ObjectTypeDefinition<Code39Props> = {
},
defaultSize: { width: 300, height: 120 },

commitTransform: commitHeightTransform,

toZPL: (obj) => {
const p = obj.props;
const interp = p.printInterpretation ? 'Y' : 'N';
Expand Down
3 changes: 3 additions & 0 deletions src/registry/ean13.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { ObjectTypeDefinition } from '../types/ObjectType';
import { useT } from '../lib/useT';
import { inputCls, labelCls } from '../components/Properties/styles';
import { fieldPos } from './zplHelpers';
import { commitHeightTransform } from './transformHelpers';

export interface Ean13Props {
content: string; // 12 digits — ZPL appends the check digit automatically
Expand All @@ -22,6 +23,8 @@ export const ean13: ObjectTypeDefinition<Ean13Props> = {
},
defaultSize: { width: 300, height: 120 },

commitTransform: commitHeightTransform,

toZPL: (obj) => {
const p = obj.props;
const interp = p.printInterpretation ? 'Y' : 'N';
Expand Down
4 changes: 4 additions & 0 deletions src/registry/gs1databar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ export const gs1databar = createBarcode1D({
hasCheckDigit: false,
localeKey: "gs1databar",
group: 'code-1d',
// GS1 Databar Omnidirectional has a symbology-fixed height; Zebra/Labelary
// ignore the ^BR height parameter for this variant. Disabling resize and the
// height input keeps the designer honest about what affects the print.
heightLocked: true,
zplCommand: (p) => {
// ^BR{orientation},{symbology},{magnification},{separator},{height},{segments}
// symbology 1 = omnidirectional
Expand Down
12 changes: 12 additions & 0 deletions src/registry/transformHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,18 @@ export function commitWidthHeightTransform<P extends WidthHeightProps>(
} as Partial<P>;
}

/** Shared commitTransform for 1D barcodes — only the bar height scales (width
* is determined by content + module width, not by the resize anchor). */
export function commitHeightTransform<P extends { height: number }>(
obj: LabelObjectBase & { props: P },
ctx: TransformContext,
): Partial<P> {
const { sy, snap } = ctx;
return {
height: Math.max(1, snap(Math.round(obj.props.height * sy))),
} as Partial<P>;
}

interface Stacked2DProps {
rowHeight: number;
moduleWidth: number;
Expand Down
7 changes: 7 additions & 0 deletions src/types/ObjectType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ export interface ObjectTypeDefinition<P extends object = object> {
* back to the model's top-left convention.
*/
nodeOrigin?: 'center' | 'top-left';
/**
* True if the rendered height is fixed by the symbology spec rather than the
* `height` prop (e.g. GS1 Databar Omnidirectional). The transformer disables
* its height anchors and the properties panel renders the height input as
* read-only — both reflect that the value cannot influence the print output.
*/
heightLocked?: boolean;
toZPL: (obj: LabelObjectBase & { props: P }) => string;
/**
* Optional hook to enforce type-specific invariants on incoming changes
Expand Down