portakal-lite 0.0.1

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/raster.js ADDED
@@ -0,0 +1,204 @@
1
+ /**
2
+ * Rasterization helpers — turn etiket's raw encodings into a 1-bit
3
+ * MonochromeBitmap that compilers emit as TSC BITMAP / ZPL ^GFA graphics.
4
+ *
5
+ * etiket raw encoders return:
6
+ * - 1D: `bars: number[]` — alternating bar/space widths in modules
7
+ * - 2D: `matrix: boolean[][]` — module grid
8
+ * - postal: height-modulated bars (POSTNET/PLANET/RM4SCC/...)
9
+ *
10
+ * All content is rendered as pixels, so it is inherently injection-safe.
11
+ */
12
+ import { InvalidConfigError } from "./errors.js";
13
+ import { encodeBars } from "etiket/barcode";
14
+ import { encodeQR } from "etiket/qr";
15
+ import { encodeDataMatrix } from "etiket/datamatrix";
16
+ import { encodePDF417 } from "etiket/pdf417";
17
+ import { encodeAztec } from "etiket/aztec";
18
+ /** Hard cap on rasterized dimensions (protects ZPL ^GFA 16-bit fields). */
19
+ const MAX_RASTER_DOTS = 65535;
20
+ /** Total raster bytes cap (DoS guard against huge matrices). */
21
+ const MAX_RASTER_BYTES = 2000000;
22
+ /**
23
+ * Rasterize a 1D bar pattern (`bars` = alternating bar/space module widths,
24
+ * starting with a bar) into a monochrome bitmap.
25
+ */
26
+ export function rasterizeBars(bars, opts = {}) {
27
+ const moduleWidth = opts.moduleWidth ?? 2;
28
+ const height = opts.height ?? 80;
29
+ const rotation = opts.rotation ?? 0;
30
+ if (!Number.isInteger(moduleWidth) || moduleWidth < 1 || moduleWidth > 10) {
31
+ throw new InvalidConfigError("moduleWidth must be an integer between 1 and 10");
32
+ }
33
+ if (!Number.isInteger(height) || height < 1 || height > MAX_RASTER_DOTS) {
34
+ throw new InvalidConfigError(`height must be an integer between 1 and ${MAX_RASTER_DOTS}`);
35
+ }
36
+ if (![0, 90, 180, 270].includes(rotation)) {
37
+ throw new InvalidConfigError("rotation must be one of 0, 90, 180, 270");
38
+ }
39
+ let totalModules = 0;
40
+ for (const w of bars) {
41
+ if (!Number.isInteger(w) || w < 1) {
42
+ throw new InvalidConfigError(`invalid bar width ${String(w)}`);
43
+ }
44
+ totalModules += w;
45
+ }
46
+ const width = totalModules * moduleWidth;
47
+ // Fill the bitmap: bars (even indices) are black, spaces (odd) are white.
48
+ const raw = packRaster(width, height, (x) => {
49
+ let acc = 0;
50
+ let i = 0;
51
+ while (i < bars.length && acc <= x / moduleWidth) {
52
+ const span = bars[i];
53
+ if (acc <= x / moduleWidth && x / moduleWidth < acc + span) {
54
+ return i % 2 === 0;
55
+ }
56
+ acc += span;
57
+ i++;
58
+ }
59
+ return false;
60
+ });
61
+ return applyRotation(raw, rotation);
62
+ }
63
+ /**
64
+ * Rasterize a 2D module matrix into a monochrome bitmap.
65
+ * Each cell becomes `cellSize`×`cellSize` dots.
66
+ */
67
+ export function rasterizeMatrix(matrix, opts = {}) {
68
+ const cellSize = opts.moduleWidth ?? 6;
69
+ const rotation = opts.rotation ?? 0;
70
+ if (!Number.isInteger(cellSize) || cellSize < 1 || cellSize > 32) {
71
+ throw new InvalidConfigError("cellSize must be an integer between 1 and 32");
72
+ }
73
+ if (![0, 90, 180, 270].includes(rotation)) {
74
+ throw new InvalidConfigError("rotation must be one of 0, 90, 180, 270");
75
+ }
76
+ const rows = matrix.length;
77
+ const cols = matrix[0]?.length ?? 0;
78
+ if (rows === 0 || cols === 0) {
79
+ throw new InvalidConfigError("empty matrix");
80
+ }
81
+ const width = cols * cellSize;
82
+ const height = rows * cellSize;
83
+ const raw = packRaster(width, height, (x, y) => {
84
+ const cx = Math.floor(x / cellSize);
85
+ const cy = Math.floor(y / cellSize);
86
+ return matrix[cy]?.[cx] === true;
87
+ });
88
+ return applyRotation(raw, rotation);
89
+ }
90
+ /** Pack a black/white raster (given by a predicate) into a MonochromeBitmap. */
91
+ function packRaster(width, height, isBlack) {
92
+ if (width < 1 || height < 1 || width > MAX_RASTER_DOTS || height > MAX_RASTER_DOTS) {
93
+ throw new InvalidConfigError("raster dimensions out of range");
94
+ }
95
+ const bytesPerRow = Math.ceil(width / 8);
96
+ const totalBytes = bytesPerRow * height;
97
+ if (totalBytes > MAX_RASTER_BYTES) {
98
+ throw new InvalidConfigError(`raster too large (${totalBytes} bytes > ${MAX_RASTER_BYTES})`);
99
+ }
100
+ const data = new Uint8Array(totalBytes);
101
+ for (let y = 0; y < height; y++) {
102
+ for (let x = 0; x < width; x++) {
103
+ if (isBlack(x, y)) {
104
+ const byteIdx = y * bytesPerRow + (x >> 3);
105
+ data[byteIdx] |= 0x80 >> (x & 7);
106
+ }
107
+ }
108
+ }
109
+ return { data, width, height, bytesPerRow };
110
+ }
111
+ /** Rotate a bitmap 90/180/270 degrees clockwise (0 = identity). */
112
+ function applyRotation(bmp, rotation) {
113
+ if (rotation === 0)
114
+ return bmp;
115
+ const { width, height, data } = bmp;
116
+ const isBlack = (x, y) => (data[y * bmp.bytesPerRow + (x >> 3)] & (0x80 >> (x & 7))) !== 0;
117
+ if (rotation === 90) {
118
+ // dest(x,y) = src(y, width-1-x)
119
+ return packRaster(height, width, (x, y) => isBlack(y, width - 1 - x));
120
+ }
121
+ if (rotation === 180) {
122
+ return packRaster(width, height, (x, y) => isBlack(width - 1 - x, height - 1 - y));
123
+ }
124
+ // 270 = 90 CCW: dest(x,y) = src(height-1-y, x)
125
+ return packRaster(height, width, (x, y) => isBlack(height - 1 - y, x));
126
+ }
127
+ /**
128
+ * Rasterize a barcode/QR/matrix element into a MonochromeBitmap using etiket's
129
+ * raw encoders. Throws InvalidConfigError on empty/invalid encodings.
130
+ */
131
+ export function rasterizeElement(el) {
132
+ if (el.type === "barcode") {
133
+ const { symbology, content, options } = el;
134
+ const { encodeOpts, moduleWidth, height, rotation } = extractBarcodeOpts(options);
135
+ const bars = encodeBars(content, { type: symbology, ...encodeOpts });
136
+ return rasterizeBars(bars, { moduleWidth, height, rotation });
137
+ }
138
+ if (el.type === "qrcode") {
139
+ const { content, options } = el;
140
+ const cellSize = options.cellSize ?? 6;
141
+ const rotation = options.rotation ?? 0;
142
+ const matrix = encodeQR(content, {
143
+ ecLevel: options.ecc ?? "M",
144
+ version: options.version,
145
+ mode: options.mode,
146
+ mask: options.mask,
147
+ eci: options.eci,
148
+ gs1: options.gs1,
149
+ });
150
+ return rasterizeMatrix(matrix, { moduleWidth: cellSize, rotation });
151
+ }
152
+ // matrix element (narrowed: barcode and qrcode handled above)
153
+ if (el.type !== "matrix") {
154
+ throw new InvalidConfigError(`cannot rasterize element type ${el.type}`);
155
+ }
156
+ const { symbology, content, options } = el;
157
+ const cellSize = (options.cellSize ?? 6);
158
+ const rotation = (options.rotation ?? 0);
159
+ const matOpts = { moduleWidth: cellSize, rotation };
160
+ switch (symbology) {
161
+ case "datamatrix": {
162
+ const matrix = encodeDataMatrix(content, options.datamatrix);
163
+ return rasterizeMatrix(matrix, matOpts);
164
+ }
165
+ case "pdf417": {
166
+ const { matrix } = encodePDF417(content, options.pdf417);
167
+ return rasterizeMatrix(matrix, matOpts);
168
+ }
169
+ case "aztec": {
170
+ const matrix = encodeAztec(content, options.aztec);
171
+ return rasterizeMatrix(matrix, matOpts);
172
+ }
173
+ default:
174
+ throw new InvalidConfigError(`unsupported matrix symbology: ${String(symbology)}`);
175
+ }
176
+ }
177
+ function extractBarcodeOpts(options) {
178
+ const { x: _x, y: _y, height, moduleWidth, ratio: _ratio, rotation, readable: _readable, fontSize: _fontSize, ...encodeOpts } = options;
179
+ void _x;
180
+ void _y;
181
+ void _ratio;
182
+ void _readable;
183
+ void _fontSize;
184
+ return { encodeOpts, moduleWidth: moduleWidth, height: height, rotation: rotation };
185
+ }
186
+ /** Convert a Uint8Array to a TSC BITMAP data payload (comma-separated bytes). */
187
+ export function bytesToTSC(data) {
188
+ let out = "";
189
+ for (let i = 0; i < data.length; i++) {
190
+ if (i > 0)
191
+ out += ",";
192
+ out += String(data[i]);
193
+ }
194
+ return out;
195
+ }
196
+ /** Convert a Uint8Array to uppercase hex (ZPL ^GFA payload). */
197
+ export function bytesToHex(data) {
198
+ let out = "";
199
+ for (let i = 0; i < data.length; i++) {
200
+ out += data[i].toString(16).padStart(2, "0").toUpperCase();
201
+ }
202
+ return out;
203
+ }
204
+ //# sourceMappingURL=raster.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"raster.js","sourceRoot":"","sources":["../src/raster.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Receipt layout helpers — build aligned text lines for receipts or labels.
3
+ * Copied verbatim from portakal (https://github.com/productdevbook/portakal) — MIT.
4
+ * Pure string padding/truncation; output feeds into .text() which sanitizes.
5
+ */
6
+ /** Column definition for table layout */
7
+ export interface Column {
8
+ /** Column width in characters */
9
+ width: number;
10
+ /** Text alignment within column */
11
+ align?: "left" | "center" | "right";
12
+ }
13
+ /** Row helper: format text for same-line left+right (or multi-column) alignment */
14
+ export declare function formatRow(columns: Column[], values: string[], totalWidth: number): string;
15
+ /** Format a simple left+right pair on one line (most common receipt pattern) */
16
+ export declare function formatPair(left: string, right: string, totalWidth: number): string;
17
+ /** Format a table with headers and rows */
18
+ export declare function formatTable(columns: Column[], rows: string[][], totalWidth: number): string[];
19
+ /** Create a separator/divider line */
20
+ export declare function separator(char: string, totalWidth: number): string;
21
+ /** Word-wrap text at word boundaries */
22
+ export declare function wordWrap(text: string, maxWidth: number): string[];
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Receipt layout helpers — build aligned text lines for receipts or labels.
3
+ * Copied verbatim from portakal (https://github.com/productdevbook/portakal) — MIT.
4
+ * Pure string padding/truncation; output feeds into .text() which sanitizes.
5
+ */
6
+ /** Row helper: format text for same-line left+right (or multi-column) alignment */
7
+ export function formatRow(columns, values, totalWidth) {
8
+ if (columns.length === 0 || values.length === 0)
9
+ return "";
10
+ // If no explicit widths, auto-distribute
11
+ let assignedWidth = 0;
12
+ let autoCount = 0;
13
+ for (const col of columns) {
14
+ if (col.width > 0) {
15
+ assignedWidth += col.width;
16
+ }
17
+ else {
18
+ autoCount++;
19
+ }
20
+ }
21
+ const autoWidth = autoCount > 0 ? Math.floor((totalWidth - assignedWidth) / autoCount) : 0;
22
+ const parts = [];
23
+ for (let i = 0; i < columns.length; i++) {
24
+ const col = columns[i];
25
+ const val = values[i] ?? "";
26
+ const w = col.width > 0 ? col.width : autoWidth;
27
+ parts.push(alignText(val, w, col.align ?? "left"));
28
+ }
29
+ return parts.join("");
30
+ }
31
+ /** Format a simple left+right pair on one line (most common receipt pattern) */
32
+ export function formatPair(left, right, totalWidth) {
33
+ const rightLen = right.length;
34
+ const leftLen = totalWidth - rightLen;
35
+ if (leftLen <= 0)
36
+ return right.slice(0, totalWidth);
37
+ return padRight(left, leftLen) + right;
38
+ }
39
+ /** Format a table with headers and rows */
40
+ export function formatTable(columns, rows, totalWidth) {
41
+ return rows.map((row) => formatRow(columns, row, totalWidth));
42
+ }
43
+ /** Create a separator/divider line */
44
+ export function separator(char, totalWidth) {
45
+ return char.repeat(totalWidth);
46
+ }
47
+ /** Word-wrap text at word boundaries */
48
+ export function wordWrap(text, maxWidth) {
49
+ if (text.length <= maxWidth)
50
+ return [text];
51
+ const words = text.split(" ");
52
+ const lines = [];
53
+ let current = "";
54
+ for (const word of words) {
55
+ if (current.length === 0) {
56
+ current = word;
57
+ }
58
+ else if (current.length + 1 + word.length <= maxWidth) {
59
+ current += " " + word;
60
+ }
61
+ else {
62
+ lines.push(current);
63
+ current = word;
64
+ }
65
+ }
66
+ if (current.length > 0) {
67
+ lines.push(current);
68
+ }
69
+ return lines;
70
+ }
71
+ function alignText(text, width, align) {
72
+ const truncated = text.length > width ? text.slice(0, width) : text;
73
+ const padding = width - truncated.length;
74
+ switch (align) {
75
+ case "right":
76
+ return " ".repeat(padding) + truncated;
77
+ case "center": {
78
+ const leftPad = Math.floor(padding / 2);
79
+ const rightPad = padding - leftPad;
80
+ return " ".repeat(leftPad) + truncated + " ".repeat(rightPad);
81
+ }
82
+ default:
83
+ return truncated + " ".repeat(padding);
84
+ }
85
+ }
86
+ function padRight(text, width) {
87
+ if (text.length >= width)
88
+ return text.slice(0, width);
89
+ return text + " ".repeat(width - text.length);
90
+ }
91
+ //# sourceMappingURL=receipt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"receipt.js","sourceRoot":"","sources":["../src/receipt.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,336 @@
1
+ /**
2
+ * Shared types for the label builder and compilers.
3
+ * Copied from portakal (https://github.com/productdevbook/portakal) — MIT.
4
+ */
5
+ /** Unit of measurement for label dimensions */
6
+ export type Unit = "mm" | "inch" | "dot";
7
+ /** Print orientation / rotation */
8
+ export type Rotation = 0 | 90 | 180 | 270;
9
+ /** Text alignment */
10
+ export type Alignment = "left" | "center" | "right";
11
+ /** Dithering algorithm for image processing */
12
+ export type DitherAlgorithm = "threshold" | "floyd-steinberg" | "atkinson" | "ordered";
13
+ /** Label configuration */
14
+ export interface LabelConfig {
15
+ /** Printer profile ID (e.g., "tsc-te200", "zebra-zd420"). Overrides width, dpi, etc. */
16
+ printer?: string;
17
+ /** Label width */
18
+ width: number;
19
+ /** Label height (optional for receipt/continuous mode) */
20
+ height?: number;
21
+ /** Unit of measurement (default: "mm") */
22
+ unit?: Unit;
23
+ /** Printer DPI (default: 203) */
24
+ dpi?: number;
25
+ /**
26
+ * TSPL font "0" base character size in dots (width × height).
27
+ * DPI-dependent: 12×24 @ 203 DPI, 18×36 @ 300 DPI. Inherited from the
28
+ * printer profile when `printer` is set; overridable here.
29
+ */
30
+ fontBase?: {
31
+ width: number;
32
+ height: number;
33
+ };
34
+ /**
35
+ * How TSPL font "0" sizes are interpreted: "multiplier" (of `fontBase`)
36
+ * or "points" (1pt = 1/72in). Firmware varies; default "multiplier".
37
+ */
38
+ font0Mode?: "multiplier" | "points";
39
+ /**
40
+ * Average glyph width relative to the font height for text width estimates
41
+ * (default 0.6). Font "0" TrueType runs ~0.5–0.6× the point height; tune
42
+ * per printer/font if centered text drifts. Overridden per element via
43
+ * TextOptions.charWidthFactor.
44
+ */
45
+ charWidthFactor?: number;
46
+ /** Gap between labels in mm (label printers only) */
47
+ gap?: number;
48
+ /**
49
+ * Print margin in `unit` (default 0) — a minimum offset the printer keeps
50
+ * from the media edge. Emitted as `^ML` on ZPL; TSC has no equivalent
51
+ * command, so the caller insets the layout instead.
52
+ */
53
+ margin?: number;
54
+ /** Print speed (1-10, printer-dependent) */
55
+ speed?: number;
56
+ /** Print darkness/density (0-15) */
57
+ density?: number;
58
+ /** Print direction */
59
+ direction?: 0 | 1;
60
+ /** Number of copies */
61
+ copies?: number;
62
+ }
63
+ /** Text element options */
64
+ export interface TextOptions {
65
+ /** X position */
66
+ x?: number;
67
+ /** Y position */
68
+ y?: number;
69
+ /** Font name or ID */
70
+ font?: string;
71
+ /** Font size or magnification */
72
+ size?: number;
73
+ /** Horizontal magnification (1-10) */
74
+ xScale?: number;
75
+ /** Vertical magnification (1-10) */
76
+ yScale?: number;
77
+ /** Rotation */
78
+ rotation?: Rotation;
79
+ /** Bold */
80
+ bold?: boolean;
81
+ /** Underline */
82
+ underline?: boolean;
83
+ /** Reverse (white on black) */
84
+ reverse?: boolean;
85
+ /** Alignment */
86
+ align?: Alignment;
87
+ /** Max width for word-wrap (in dots) */
88
+ maxWidth?: number;
89
+ /** Max height for word-wrap/clipping (in dots) — TSC BLOCK height (default: maxWidth) */
90
+ maxHeight?: number;
91
+ /** Line spacing (in dots) */
92
+ lineSpacing?: number;
93
+ /**
94
+ * Average glyph width relative to the font height for text width estimates
95
+ * in the preview (default: the builder's charWidthFactor, 0.6). Tune per
96
+ * printer/font if centered text drifts in the preview.
97
+ */
98
+ charWidthFactor?: number;
99
+ }
100
+ /** Image element options */
101
+ export interface ImageOptions {
102
+ /** X position */
103
+ x?: number;
104
+ /** Y position */
105
+ y?: number;
106
+ /** Target width in dots (auto-scale if set) */
107
+ width?: number;
108
+ /** Target height in dots (auto-scale if set) */
109
+ height?: number;
110
+ /** Dithering algorithm (default: "threshold") */
111
+ dither?: DitherAlgorithm;
112
+ /** Threshold for monochrome conversion (0-255, default: 128) */
113
+ threshold?: number;
114
+ }
115
+ /** Box/rectangle element options */
116
+ export interface BoxOptions {
117
+ /** X position */
118
+ x: number;
119
+ /** Y position */
120
+ y: number;
121
+ /** Width */
122
+ width: number;
123
+ /** Height */
124
+ height: number;
125
+ /** Border thickness in dots (default: 1) */
126
+ thickness?: number;
127
+ /** Corner radius in dots */
128
+ radius?: number;
129
+ }
130
+ /** Line element options */
131
+ export interface LineOptions {
132
+ /** Start X */
133
+ x1: number;
134
+ /** Start Y */
135
+ y1: number;
136
+ /** End X */
137
+ x2: number;
138
+ /** End Y */
139
+ y2: number;
140
+ /** Line thickness in dots (default: 1) */
141
+ thickness?: number;
142
+ }
143
+ /** Circle element options */
144
+ export interface CircleOptions {
145
+ /** Center X */
146
+ x: number;
147
+ /** Center Y */
148
+ y: number;
149
+ /** Diameter in dots */
150
+ diameter: number;
151
+ /** Border thickness in dots (default: 1) */
152
+ thickness?: number;
153
+ }
154
+ /** 1-bit monochrome bitmap (universal intermediate format for images) */
155
+ export interface MonochromeBitmap {
156
+ /** Packed 1-bit pixel data, row-major, MSB-first */
157
+ data: Uint8Array;
158
+ /** Width in pixels */
159
+ width: number;
160
+ /** Height in pixels */
161
+ height: number;
162
+ /** Bytes per row = ceil(width / 8) */
163
+ bytesPerRow: number;
164
+ }
165
+ /** Ellipse element options */
166
+ export interface EllipseOptions {
167
+ x: number;
168
+ y: number;
169
+ width: number;
170
+ height: number;
171
+ thickness?: number;
172
+ }
173
+ /** Reverse region options (invert black/white) */
174
+ export interface ReverseOptions {
175
+ x: number;
176
+ y: number;
177
+ width: number;
178
+ height: number;
179
+ }
180
+ /** Erase region options (clear to white) */
181
+ export interface EraseOptions {
182
+ x: number;
183
+ y: number;
184
+ width: number;
185
+ height: number;
186
+ }
187
+ /**
188
+ * Barcode symbologies supported by .barcode(). The value is passed to etiket's
189
+ * encoders, so anything etiket supports works. `code128` uses the printer's
190
+ * native encoder; everything else is rasterized to a BITMAP/^GFA graphic.
191
+ */
192
+ export type BarcodeSymbology = string;
193
+ /** 1D barcode element options. */
194
+ export interface BarcodeOptions {
195
+ /** X position in dots */
196
+ x?: number;
197
+ /** Y position in dots */
198
+ y?: number;
199
+ /** Bar height in dots (default: 80) */
200
+ height?: number;
201
+ /** Narrow element width in dots (default: 2) */
202
+ moduleWidth?: number;
203
+ /** Wide:narrow ratio (TSC 1-4, ZPL 2 or 3; default: 2) */
204
+ ratio?: number;
205
+ /** Rotation (default: 0) */
206
+ rotation?: Rotation;
207
+ /** Human-readable text below the bars (default: true) */
208
+ readable?: boolean;
209
+ /** Human-readable font size (TSC 1-10, ZPL 0-5; default: 2) */
210
+ fontSize?: number;
211
+ /** etiket encoding passthrough */
212
+ code128Charset?: "auto" | "A" | "B" | "C";
213
+ msiCheckDigit?: "mod10" | "mod11" | "mod1010" | "mod1110" | "none";
214
+ code39CheckDigit?: boolean;
215
+ codabarStart?: string;
216
+ codabarStop?: string;
217
+ /** Render interpretable text (affects SVG preview; default true) */
218
+ showText?: boolean;
219
+ }
220
+ /** QR code element options. */
221
+ export interface QrCodeOptions {
222
+ /** X position in dots */
223
+ x?: number;
224
+ /** Y position in dots */
225
+ y?: number;
226
+ /** Module (cell) width in dots (default: 6) */
227
+ cellSize?: number;
228
+ /** Error correction level (default: "M") */
229
+ ecc?: "L" | "M" | "Q" | "H";
230
+ /** Rotation (default: 0) */
231
+ rotation?: Rotation;
232
+ /** etiket QR encoding passthrough */
233
+ version?: number;
234
+ mode?: "numeric" | "alphanumeric" | "byte" | "kanji" | "auto";
235
+ mask?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7;
236
+ eci?: number;
237
+ gs1?: boolean;
238
+ }
239
+ /** 2D barcode element options (etiket raster path). */
240
+ export interface MatrixBarcodeOptions {
241
+ /** X position in dots */
242
+ x?: number;
243
+ /** Y position in dots */
244
+ y?: number;
245
+ /** Module width in dots (default: 6) */
246
+ cellSize?: number;
247
+ /** Rotation (default: 0) */
248
+ rotation?: Rotation;
249
+ /** etiket encoding passthrough (per-symbology) */
250
+ [key: string]: unknown;
251
+ }
252
+ /** Internal label element union type */
253
+ export type LabelElement = {
254
+ type: "text";
255
+ content: string;
256
+ options: TextOptions;
257
+ } | {
258
+ type: "image";
259
+ bitmap: MonochromeBitmap;
260
+ options: ImageOptions;
261
+ } | {
262
+ type: "box";
263
+ options: BoxOptions;
264
+ } | {
265
+ type: "line";
266
+ options: LineOptions;
267
+ } | {
268
+ type: "circle";
269
+ options: CircleOptions;
270
+ } | {
271
+ type: "ellipse";
272
+ options: EllipseOptions;
273
+ } | {
274
+ type: "reverse";
275
+ options: ReverseOptions;
276
+ } | {
277
+ type: "erase";
278
+ options: EraseOptions;
279
+ } | {
280
+ type: "barcode";
281
+ content: string;
282
+ symbology: BarcodeSymbology;
283
+ options: BarcodeOptions;
284
+ } | {
285
+ type: "qrcode";
286
+ content: string;
287
+ options: QrCodeOptions;
288
+ } | {
289
+ type: "matrix";
290
+ content: string;
291
+ symbology: "datamatrix" | "pdf417" | "aztec";
292
+ options: MatrixBarcodeOptions;
293
+ } | {
294
+ type: "raw";
295
+ content: string | Uint8Array;
296
+ };
297
+ /** Resolved label configuration with computed values */
298
+ export interface ResolvedLabel {
299
+ /** Width in dots */
300
+ widthDots: number;
301
+ /** Height in dots (0 for continuous/receipt) */
302
+ heightDots: number;
303
+ /** DPI */
304
+ dpi: number;
305
+ /**
306
+ * TSPL font "0" base size in dots (12×24 @ 203, 18×36 @ 300), from the
307
+ * printer profile or config override.
308
+ */
309
+ fontBase: {
310
+ width: number;
311
+ height: number;
312
+ };
313
+ /**
314
+ * TSPL font "0" size mode: "multiplier" (of fontBase) or "points".
315
+ */
316
+ font0Mode: "multiplier" | "points";
317
+ /**
318
+ * Default average glyph width relative to the font height for text width
319
+ * estimates (preview centering), from config.
320
+ */
321
+ charWidthFactor: number;
322
+ /** Gap in dots */
323
+ gapDots: number;
324
+ /** Print margin in dots */
325
+ marginDots: number;
326
+ /** Speed */
327
+ speed: number;
328
+ /** Density */
329
+ density: number;
330
+ /** Direction */
331
+ direction: 0 | 1;
332
+ /** Copies */
333
+ copies: number;
334
+ /** All elements to render */
335
+ elements: LabelElement[];
336
+ }
package/dist/types.js ADDED
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Shared types for the label builder and compilers.
3
+ * Copied from portakal (https://github.com/productdevbook/portakal) — MIT.
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=types.js.map