@nuvui/barcodes 0.0.0-stage → 0.1.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.
Files changed (40) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +60 -2
  3. package/dist/components/barcode/barcode.cjs +94 -0
  4. package/dist/components/barcode/barcode.d.cts +70 -0
  5. package/dist/components/barcode/barcode.d.ts +70 -0
  6. package/dist/components/barcode/barcode.js +94 -0
  7. package/dist/components/barcode/encode.cjs +86 -0
  8. package/dist/components/barcode/encode.d.cts +52 -0
  9. package/dist/components/barcode/encode.d.ts +52 -0
  10. package/dist/components/barcode/encode.js +85 -0
  11. package/dist/components/barcode/index.cjs +6 -0
  12. package/dist/components/barcode/index.d.cts +3 -0
  13. package/dist/components/barcode/index.d.ts +3 -0
  14. package/dist/components/barcode/index.js +3 -0
  15. package/dist/components/qrcode/encode.cjs +28 -0
  16. package/dist/components/qrcode/encode.d.cts +29 -0
  17. package/dist/components/qrcode/encode.d.ts +29 -0
  18. package/dist/components/qrcode/encode.js +28 -0
  19. package/dist/components/qrcode/index.cjs +6 -0
  20. package/dist/components/qrcode/index.d.cts +3 -0
  21. package/dist/components/qrcode/index.d.ts +3 -0
  22. package/dist/components/qrcode/index.js +3 -0
  23. package/dist/components/qrcode/qrcode.cjs +121 -0
  24. package/dist/components/qrcode/qrcode.d.cts +59 -0
  25. package/dist/components/qrcode/qrcode.d.ts +59 -0
  26. package/dist/components/qrcode/qrcode.js +120 -0
  27. package/dist/css/barcode.css +26 -0
  28. package/dist/css/qrcode.css +28 -0
  29. package/dist/index.cjs +15 -0
  30. package/dist/index.d.cts +8 -0
  31. package/dist/index.d.ts +8 -0
  32. package/dist/index.js +6 -0
  33. package/dist/save.cjs +120 -0
  34. package/dist/save.d.cts +38 -0
  35. package/dist/save.d.ts +38 -0
  36. package/dist/save.js +117 -0
  37. package/dist/styles.css +53 -0
  38. package/dist/utils/cx.cjs +6 -0
  39. package/dist/utils/cx.js +6 -0
  40. package/package.json +118 -3
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nuvraxis
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,61 @@
1
- # Temporary Holding Version
1
+ # @nuvui/barcodes
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Barcodes and QR codes for [`@nuvui/react`](https://www.npmjs.com/package/@nuvui/react), drawn as SVG.
4
+
5
+ This is early: the package is on npm as a 0.x version, and before 1.0 a minor version may rename or remove things. The [changelog](https://nuvui.nuvraxis.com/docs/changelog) says where one does, and the [repository README](https://github.com/Nuvraxis/nuvui#readme) says where things stand.
6
+
7
+ ```sh
8
+ pnpm add @nuvui/barcodes @nuvui/react
9
+ ```
10
+
11
+ ```tsx
12
+ import "@nuvui/react/styles.css";
13
+ import "@nuvui/barcodes/styles.css";
14
+ import { Barcode, QRCode } from "@nuvui/barcodes";
15
+
16
+ export function Label() {
17
+ return (
18
+ <>
19
+ <Barcode value="590123412345" type="ean13" aria-label="Item 5901234" />
20
+ <QRCode
21
+ value="https://example.com/orders/1042"
22
+ aria-label="Open order 1042"
23
+ />
24
+ </>
25
+ );
26
+ }
27
+ ```
28
+
29
+ ## What's in it
30
+
31
+ - `Barcode`: bars for a scanner, in seventeen kinds. Code 128, GS1-128, Code 39 with and without its check character, EAN-13, EAN-8, UPC-A, UPC-E, ITF, ITF-14, MSI with and without its check digits, Codabar and Pharmacode. The value is written under the bars.
32
+ - `QRCode`: a QR code at one of four levels of error correction, with room in the middle for a logo.
33
+ - `QRCodeSwissCross`: the cross in the middle of a Swiss QR-bill's code.
34
+ - `encodeBarcode` and `encodeQRCode`: the bars and the squares as data, or `null` for a value that can't be encoded. They need no browser, so they check a value in a form or on a server.
35
+ - `saveCode`, `codeToBlob` and `codeToSvg`: a code on the page as an SVG or a PNG file.
36
+
37
+ Each component has an entry of its own, `@nuvui/barcodes/barcode` and `@nuvui/barcodes/qrcode`, so a page with only QR codes doesn't carry every barcode's tables.
38
+
39
+ ## How it behaves
40
+
41
+ Both components are SVG with no state and no `"use client"`. A server component renders them as markup, and no script is sent for them.
42
+
43
+ A code is black on white in every theme, and where the browser forces colors. A scanner reads the difference between the two, and many don't read a light code on a dark ground. Two CSS variables change the colors if you have to.
44
+
45
+ A value that can't be a code of its kind, such as a letter in an EAN-13, is drawn as an empty box with a line through it, or as your `fallback`. It's never drawn as a code that reads as something else.
46
+
47
+ A code is a picture with a name. Give it `aria-label` for what it's for. Don't make a code the only way to get what it holds: put the text or a link next to it.
48
+
49
+ ## Dependencies
50
+
51
+ `@nuvui/react` is a peer dependency: the codes take their colors and their font from its tokens.
52
+
53
+ The bars are worked out by [JsBarcode](https://github.com/lindell/JsBarcode) and the squares by [uqr](https://github.com/unjs/uqr). Both are MIT, both are ordinary dependencies, and neither has dependencies of its own. Only their encoders are used. The drawing is done here.
54
+
55
+ It's a package of its own so that an app which only wants buttons and dialogs doesn't have to install either.
56
+
57
+ The docs are at https://nuvui.nuvraxis.com/docs/barcodes.
58
+
59
+ ## License
60
+
61
+ MIT
@@ -0,0 +1,94 @@
1
+ const require_cx = require("../../utils/cx.cjs");
2
+ const require_encode = require("./encode.cjs");
3
+ let react = require("react");
4
+ let react_jsx_runtime = require("react/jsx-runtime");
5
+ //#region src/components/barcode/barcode.tsx
6
+ const gap = 2;
7
+ const emptyModules = 96;
8
+ /**
9
+ * A barcode, drawn as an SVG. It's a picture with a name: say what the
10
+ * code is for with `aria-label`, and without one the name is the value.
11
+ *
12
+ * It has no state and needs no browser, so it can be a server component.
13
+ */
14
+ const Barcode = (0, react.forwardRef)(function Barcode({ value, type = "code128", barWidth = 2, height = 64, quietZone = 10, showText = true, text, textSize = 14, flat = false, fallback, className, "aria-label": label, "aria-labelledby": labelledBy, ...props }, ref) {
15
+ const encoding = require_encode.encodeBarcode(value, type, {
16
+ text,
17
+ flat
18
+ });
19
+ if (!encoding && fallback !== void 0) return fallback;
20
+ const edge = quietZone * barWidth;
21
+ const width = ((encoding?.modules ?? emptyModules) + quietZone * 2) * barWidth;
22
+ const total = showText ? height + gap + textSize * 1.25 : height;
23
+ const guardHeight = showText ? height + gap + textSize / 2 : height;
24
+ const name = labelledBy ? void 0 : label ?? encoding?.text ?? value;
25
+ const root = {
26
+ ref,
27
+ width,
28
+ height: total,
29
+ viewBox: `0 0 ${width} ${total}`,
30
+ ...props
31
+ };
32
+ if (!encoding) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
33
+ ...root,
34
+ role: "img",
35
+ "aria-label": name,
36
+ "aria-labelledby": labelledBy,
37
+ className: require_cx.cx("nuv-barcode", className),
38
+ "data-invalid": "",
39
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
40
+ className: "nuv-barcode__ground",
41
+ width: "100%",
42
+ height: "100%"
43
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
44
+ className: "nuv-barcode__mark",
45
+ d: `M0.5 0.5H${width - .5}V${total - .5}H0.5ZM0.5 ${total - .5}L${width - .5} 0.5`
46
+ })]
47
+ });
48
+ let bars = "";
49
+ const texts = [];
50
+ let start = edge;
51
+ for (const [index, part] of encoding.parts.entries()) {
52
+ const tall = part.guard ? guardHeight : height;
53
+ for (const run of part.bars.matchAll(/1+/g)) {
54
+ const x = start + run.index * barWidth;
55
+ const across = run[0].length * barWidth;
56
+ bars += `M${x} 0h${across}v${tall}h${-across}z`;
57
+ }
58
+ const end = start + part.bars.length * barWidth;
59
+ if (showText && part.text) {
60
+ const [x, anchor] = part.align === "start" ? [start, "start"] : part.align === "end" ? [end, "end"] : [(start + end) / 2, "middle"];
61
+ texts.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)("text", {
62
+ className: "nuv-barcode__text",
63
+ x,
64
+ y: height + gap + textSize,
65
+ textAnchor: anchor,
66
+ fontSize: textSize,
67
+ children: part.text
68
+ }, index));
69
+ }
70
+ start = end;
71
+ }
72
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
73
+ ...root,
74
+ role: "img",
75
+ "aria-label": name,
76
+ "aria-labelledby": labelledBy,
77
+ className: require_cx.cx("nuv-barcode", className),
78
+ "data-type": encoding.type,
79
+ children: [
80
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
81
+ className: "nuv-barcode__ground",
82
+ width: "100%",
83
+ height: "100%"
84
+ }),
85
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
86
+ className: "nuv-barcode__bars",
87
+ d: bars
88
+ }),
89
+ texts
90
+ ]
91
+ });
92
+ });
93
+ //#endregion
94
+ exports.Barcode = Barcode;
@@ -0,0 +1,70 @@
1
+ import { BarcodeType } from "./encode.cjs";
2
+ import { ReactNode, SVGAttributes } from "react";
3
+ //#region src/components/barcode/barcode.d.ts
4
+ export interface BarcodeOwnProps {
5
+ /** What the barcode holds. */
6
+ value: string;
7
+ /**
8
+ * The kind of barcode. Each takes its own values: an EAN-13 is twelve
9
+ * or thirteen digits, a Code 39 is capitals, digits and a few signs,
10
+ * and a Code 128 is any ASCII text.
11
+ * @default "code128"
12
+ */
13
+ type?: BarcodeType;
14
+ /**
15
+ * The width of the narrowest bar, in pixels. A scanner needs it to be
16
+ * a whole number of the screen's or the printer's dots.
17
+ * @default 2
18
+ */
19
+ barWidth?: number;
20
+ /**
21
+ * The height of the bars, in pixels. The text is under that.
22
+ * @default 64
23
+ */
24
+ height?: number;
25
+ /**
26
+ * The empty space at each end, counted in narrowest bars. A scanner
27
+ * finds the barcode by it, and most kinds ask for ten.
28
+ * @default 10
29
+ */
30
+ quietZone?: number;
31
+ /**
32
+ * Writes the value under the bars, for someone to type when it won't
33
+ * scan.
34
+ * @default true
35
+ */
36
+ showText?: boolean;
37
+ /**
38
+ * Written under the bars in place of the value: the same number with
39
+ * spaces in it, say. An EAN or a UPC writes its own digits whatever
40
+ * this is.
41
+ */
42
+ text?: string;
43
+ /**
44
+ * The size of the text, in pixels.
45
+ * @default 14
46
+ */
47
+ textSize?: number;
48
+ /**
49
+ * An EAN or a UPC with every bar the same height and its digits in one
50
+ * line, in place of the usual look with taller bars at the ends and in
51
+ * the middle.
52
+ * @default false
53
+ */
54
+ flat?: boolean;
55
+ /**
56
+ * What's drawn when the value can't be a barcode of this kind. Without
57
+ * it there's an empty box with a line through it, which no scanner
58
+ * reads as anything.
59
+ */
60
+ fallback?: ReactNode;
61
+ }
62
+ export interface BarcodeProps extends BarcodeOwnProps, Omit<SVGAttributes<SVGSVGElement>, keyof BarcodeOwnProps> {}
63
+ /**
64
+ * A barcode, drawn as an SVG. It's a picture with a name: say what the
65
+ * code is for with `aria-label`, and without one the name is the value.
66
+ *
67
+ * It has no state and needs no browser, so it can be a server component.
68
+ */
69
+ export declare const Barcode: import("react").ForwardRefExoticComponent<BarcodeProps & import("react").RefAttributes<SVGSVGElement>>;
70
+ //#endregion
@@ -0,0 +1,70 @@
1
+ import { BarcodeType } from "./encode.js";
2
+ import { ReactNode, SVGAttributes } from "react";
3
+ //#region src/components/barcode/barcode.d.ts
4
+ export interface BarcodeOwnProps {
5
+ /** What the barcode holds. */
6
+ value: string;
7
+ /**
8
+ * The kind of barcode. Each takes its own values: an EAN-13 is twelve
9
+ * or thirteen digits, a Code 39 is capitals, digits and a few signs,
10
+ * and a Code 128 is any ASCII text.
11
+ * @default "code128"
12
+ */
13
+ type?: BarcodeType;
14
+ /**
15
+ * The width of the narrowest bar, in pixels. A scanner needs it to be
16
+ * a whole number of the screen's or the printer's dots.
17
+ * @default 2
18
+ */
19
+ barWidth?: number;
20
+ /**
21
+ * The height of the bars, in pixels. The text is under that.
22
+ * @default 64
23
+ */
24
+ height?: number;
25
+ /**
26
+ * The empty space at each end, counted in narrowest bars. A scanner
27
+ * finds the barcode by it, and most kinds ask for ten.
28
+ * @default 10
29
+ */
30
+ quietZone?: number;
31
+ /**
32
+ * Writes the value under the bars, for someone to type when it won't
33
+ * scan.
34
+ * @default true
35
+ */
36
+ showText?: boolean;
37
+ /**
38
+ * Written under the bars in place of the value: the same number with
39
+ * spaces in it, say. An EAN or a UPC writes its own digits whatever
40
+ * this is.
41
+ */
42
+ text?: string;
43
+ /**
44
+ * The size of the text, in pixels.
45
+ * @default 14
46
+ */
47
+ textSize?: number;
48
+ /**
49
+ * An EAN or a UPC with every bar the same height and its digits in one
50
+ * line, in place of the usual look with taller bars at the ends and in
51
+ * the middle.
52
+ * @default false
53
+ */
54
+ flat?: boolean;
55
+ /**
56
+ * What's drawn when the value can't be a barcode of this kind. Without
57
+ * it there's an empty box with a line through it, which no scanner
58
+ * reads as anything.
59
+ */
60
+ fallback?: ReactNode;
61
+ }
62
+ export interface BarcodeProps extends BarcodeOwnProps, Omit<SVGAttributes<SVGSVGElement>, keyof BarcodeOwnProps> {}
63
+ /**
64
+ * A barcode, drawn as an SVG. It's a picture with a name: say what the
65
+ * code is for with `aria-label`, and without one the name is the value.
66
+ *
67
+ * It has no state and needs no browser, so it can be a server component.
68
+ */
69
+ export declare const Barcode: import("react").ForwardRefExoticComponent<BarcodeProps & import("react").RefAttributes<SVGSVGElement>>;
70
+ //#endregion
@@ -0,0 +1,94 @@
1
+ import { cx } from "../../utils/cx.js";
2
+ import { encodeBarcode } from "./encode.js";
3
+ import { forwardRef } from "react";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ //#region src/components/barcode/barcode.tsx
6
+ const gap = 2;
7
+ const emptyModules = 96;
8
+ /**
9
+ * A barcode, drawn as an SVG. It's a picture with a name: say what the
10
+ * code is for with `aria-label`, and without one the name is the value.
11
+ *
12
+ * It has no state and needs no browser, so it can be a server component.
13
+ */
14
+ const Barcode = forwardRef(function Barcode({ value, type = "code128", barWidth = 2, height = 64, quietZone = 10, showText = true, text, textSize = 14, flat = false, fallback, className, "aria-label": label, "aria-labelledby": labelledBy, ...props }, ref) {
15
+ const encoding = encodeBarcode(value, type, {
16
+ text,
17
+ flat
18
+ });
19
+ if (!encoding && fallback !== void 0) return fallback;
20
+ const edge = quietZone * barWidth;
21
+ const width = ((encoding?.modules ?? emptyModules) + quietZone * 2) * barWidth;
22
+ const total = showText ? height + gap + textSize * 1.25 : height;
23
+ const guardHeight = showText ? height + gap + textSize / 2 : height;
24
+ const name = labelledBy ? void 0 : label ?? encoding?.text ?? value;
25
+ const root = {
26
+ ref,
27
+ width,
28
+ height: total,
29
+ viewBox: `0 0 ${width} ${total}`,
30
+ ...props
31
+ };
32
+ if (!encoding) return /* @__PURE__ */ jsxs("svg", {
33
+ ...root,
34
+ role: "img",
35
+ "aria-label": name,
36
+ "aria-labelledby": labelledBy,
37
+ className: cx("nuv-barcode", className),
38
+ "data-invalid": "",
39
+ children: [/* @__PURE__ */ jsx("rect", {
40
+ className: "nuv-barcode__ground",
41
+ width: "100%",
42
+ height: "100%"
43
+ }), /* @__PURE__ */ jsx("path", {
44
+ className: "nuv-barcode__mark",
45
+ d: `M0.5 0.5H${width - .5}V${total - .5}H0.5ZM0.5 ${total - .5}L${width - .5} 0.5`
46
+ })]
47
+ });
48
+ let bars = "";
49
+ const texts = [];
50
+ let start = edge;
51
+ for (const [index, part] of encoding.parts.entries()) {
52
+ const tall = part.guard ? guardHeight : height;
53
+ for (const run of part.bars.matchAll(/1+/g)) {
54
+ const x = start + run.index * barWidth;
55
+ const across = run[0].length * barWidth;
56
+ bars += `M${x} 0h${across}v${tall}h${-across}z`;
57
+ }
58
+ const end = start + part.bars.length * barWidth;
59
+ if (showText && part.text) {
60
+ const [x, anchor] = part.align === "start" ? [start, "start"] : part.align === "end" ? [end, "end"] : [(start + end) / 2, "middle"];
61
+ texts.push(/* @__PURE__ */ jsx("text", {
62
+ className: "nuv-barcode__text",
63
+ x,
64
+ y: height + gap + textSize,
65
+ textAnchor: anchor,
66
+ fontSize: textSize,
67
+ children: part.text
68
+ }, index));
69
+ }
70
+ start = end;
71
+ }
72
+ return /* @__PURE__ */ jsxs("svg", {
73
+ ...root,
74
+ role: "img",
75
+ "aria-label": name,
76
+ "aria-labelledby": labelledBy,
77
+ className: cx("nuv-barcode", className),
78
+ "data-type": encoding.type,
79
+ children: [
80
+ /* @__PURE__ */ jsx("rect", {
81
+ className: "nuv-barcode__ground",
82
+ width: "100%",
83
+ height: "100%"
84
+ }),
85
+ /* @__PURE__ */ jsx("path", {
86
+ className: "nuv-barcode__bars",
87
+ d: bars
88
+ }),
89
+ texts
90
+ ]
91
+ });
92
+ });
93
+ //#endregion
94
+ export { Barcode };
@@ -0,0 +1,86 @@
1
+ let jsbarcode_bin_barcodes_CODE39_index_js = require("jsbarcode/bin/barcodes/CODE39/index.js");
2
+ let jsbarcode_bin_barcodes_CODE128_index_js = require("jsbarcode/bin/barcodes/CODE128/index.js");
3
+ let jsbarcode_bin_barcodes_codabar_index_js = require("jsbarcode/bin/barcodes/codabar/index.js");
4
+ let jsbarcode_bin_barcodes_EAN_UPC_index_js = require("jsbarcode/bin/barcodes/EAN_UPC/index.js");
5
+ let jsbarcode_bin_barcodes_ITF_index_js = require("jsbarcode/bin/barcodes/ITF/index.js");
6
+ let jsbarcode_bin_barcodes_MSI_index_js = require("jsbarcode/bin/barcodes/MSI/index.js");
7
+ let jsbarcode_bin_barcodes_pharmacode_index_js = require("jsbarcode/bin/barcodes/pharmacode/index.js");
8
+ //#region src/components/barcode/encode.ts
9
+ const encoders = {
10
+ code128: [jsbarcode_bin_barcodes_CODE128_index_js.CODE128, {}],
11
+ "gs1-128": [jsbarcode_bin_barcodes_CODE128_index_js.CODE128, { ean128: true }],
12
+ code39: [jsbarcode_bin_barcodes_CODE39_index_js.CODE39, {}],
13
+ "code39-mod43": [jsbarcode_bin_barcodes_CODE39_index_js.CODE39, { mod43: true }],
14
+ ean13: [jsbarcode_bin_barcodes_EAN_UPC_index_js.EAN13, {}],
15
+ ean8: [jsbarcode_bin_barcodes_EAN_UPC_index_js.EAN8, {}],
16
+ upca: [jsbarcode_bin_barcodes_EAN_UPC_index_js.UPC, {}],
17
+ upce: [jsbarcode_bin_barcodes_EAN_UPC_index_js.UPCE, {}],
18
+ itf: [jsbarcode_bin_barcodes_ITF_index_js.ITF, {}],
19
+ itf14: [jsbarcode_bin_barcodes_ITF_index_js.ITF14, {}],
20
+ msi: [jsbarcode_bin_barcodes_MSI_index_js.MSI, {}],
21
+ "msi-mod10": [jsbarcode_bin_barcodes_MSI_index_js.MSI10, {}],
22
+ "msi-mod11": [jsbarcode_bin_barcodes_MSI_index_js.MSI11, {}],
23
+ "msi-mod1010": [jsbarcode_bin_barcodes_MSI_index_js.MSI1010, {}],
24
+ "msi-mod1110": [jsbarcode_bin_barcodes_MSI_index_js.MSI1110, {}],
25
+ codabar: [jsbarcode_bin_barcodes_codabar_index_js.codabar, {}],
26
+ pharmacode: [jsbarcode_bin_barcodes_pharmacode_index_js.pharmacode, {}]
27
+ };
28
+ /** Every kind of barcode there is here. */
29
+ const barcodeTypes = Object.keys(encoders);
30
+ const grouped = /* @__PURE__ */ new Set([
31
+ "ean13",
32
+ "ean8",
33
+ "upca",
34
+ "upce"
35
+ ]);
36
+ const aligned = {
37
+ left: "start",
38
+ center: "center",
39
+ right: "end"
40
+ };
41
+ /**
42
+ * The bars for a value, or `null` if this kind of barcode can't hold it:
43
+ * a letter in an EAN, a check digit that's wrong, an odd number of digits
44
+ * in an ITF, nothing at all.
45
+ *
46
+ * It needs no browser, so it runs wherever the value is checked.
47
+ */
48
+ function encodeBarcode(value, type = "code128", { text, flat = false } = {}) {
49
+ const entry = encoders[type];
50
+ if (!entry || typeof value !== "string" || value === "") return null;
51
+ const [Encoder, extra] = entry;
52
+ let encoded;
53
+ try {
54
+ const encoder = new Encoder(value, {
55
+ ...extra,
56
+ text: grouped.has(type) ? void 0 : text,
57
+ flat,
58
+ displayValue: true,
59
+ fontSize: 0,
60
+ height: 0,
61
+ textMargin: 0,
62
+ width: 1
63
+ });
64
+ if (!encoder.valid()) return null;
65
+ encoded = encoder.encode();
66
+ } catch {
67
+ return null;
68
+ }
69
+ const parts = (Array.isArray(encoded) ? encoded : [encoded]).filter((part) => part.data.length > 0).map((part) => ({
70
+ bars: part.data,
71
+ text: part.text === void 0 ? void 0 : String(part.text),
72
+ guard: part.options?.height !== void 0,
73
+ align: aligned[part.options?.textAlign ?? "center"]
74
+ }));
75
+ const modules = parts.reduce((sum, part) => sum + part.bars.length, 0);
76
+ if (modules === 0) return null;
77
+ return {
78
+ type,
79
+ parts,
80
+ modules,
81
+ text: parts.map((part) => part.text ?? "").join("")
82
+ };
83
+ }
84
+ //#endregion
85
+ exports.barcodeTypes = barcodeTypes;
86
+ exports.encodeBarcode = encodeBarcode;
@@ -0,0 +1,52 @@
1
+ //#region src/components/barcode/encode.d.ts
2
+ /** The kinds of barcode there are here. */
3
+ export type BarcodeType = "code128" | "gs1-128" | "code39" | "code39-mod43" | "ean13" | "ean8" | "upca" | "upce" | "itf" | "itf14" | "msi" | "msi-mod10" | "msi-mod11" | "msi-mod1010" | "msi-mod1110" | "codabar" | "pharmacode";
4
+ /** Every kind of barcode there is here. */
5
+ export declare const barcodeTypes: BarcodeType[];
6
+ export interface BarcodePart {
7
+ /** "1" for a bar one module wide and "0" for a space as wide. */
8
+ bars: string;
9
+ /** What's written under this part, if anything. */
10
+ text?: string;
11
+ /**
12
+ * A guard: bars at the two ends and in the middle of an EAN or a UPC,
13
+ * drawn taller than the rest.
14
+ */
15
+ guard: boolean;
16
+ /** Where the text sits under the part. */
17
+ align: "start" | "center" | "end";
18
+ }
19
+ export interface BarcodeEncoding {
20
+ type: BarcodeType;
21
+ /** The parts from left to right. Most kinds have one. */
22
+ parts: BarcodePart[];
23
+ /** How many modules wide the bars are, all parts together. */
24
+ modules: number;
25
+ /**
26
+ * The whole of what's written under the bars, with a check digit the
27
+ * encoder worked out.
28
+ */
29
+ text: string;
30
+ }
31
+ export interface BarcodeEncodeOptions {
32
+ /**
33
+ * Written under the bars in place of the value. An EAN or a UPC writes
34
+ * its own digits whatever this is.
35
+ */
36
+ text?: string;
37
+ /**
38
+ * An EAN or a UPC in one part, with every bar the same height and no
39
+ * digit outside the bars.
40
+ * @default false
41
+ */
42
+ flat?: boolean;
43
+ }
44
+ /**
45
+ * The bars for a value, or `null` if this kind of barcode can't hold it:
46
+ * a letter in an EAN, a check digit that's wrong, an odd number of digits
47
+ * in an ITF, nothing at all.
48
+ *
49
+ * It needs no browser, so it runs wherever the value is checked.
50
+ */
51
+ export declare function encodeBarcode(value: string, type?: BarcodeType, { text, flat }?: BarcodeEncodeOptions): BarcodeEncoding | null;
52
+ //#endregion
@@ -0,0 +1,52 @@
1
+ //#region src/components/barcode/encode.d.ts
2
+ /** The kinds of barcode there are here. */
3
+ export type BarcodeType = "code128" | "gs1-128" | "code39" | "code39-mod43" | "ean13" | "ean8" | "upca" | "upce" | "itf" | "itf14" | "msi" | "msi-mod10" | "msi-mod11" | "msi-mod1010" | "msi-mod1110" | "codabar" | "pharmacode";
4
+ /** Every kind of barcode there is here. */
5
+ export declare const barcodeTypes: BarcodeType[];
6
+ export interface BarcodePart {
7
+ /** "1" for a bar one module wide and "0" for a space as wide. */
8
+ bars: string;
9
+ /** What's written under this part, if anything. */
10
+ text?: string;
11
+ /**
12
+ * A guard: bars at the two ends and in the middle of an EAN or a UPC,
13
+ * drawn taller than the rest.
14
+ */
15
+ guard: boolean;
16
+ /** Where the text sits under the part. */
17
+ align: "start" | "center" | "end";
18
+ }
19
+ export interface BarcodeEncoding {
20
+ type: BarcodeType;
21
+ /** The parts from left to right. Most kinds have one. */
22
+ parts: BarcodePart[];
23
+ /** How many modules wide the bars are, all parts together. */
24
+ modules: number;
25
+ /**
26
+ * The whole of what's written under the bars, with a check digit the
27
+ * encoder worked out.
28
+ */
29
+ text: string;
30
+ }
31
+ export interface BarcodeEncodeOptions {
32
+ /**
33
+ * Written under the bars in place of the value. An EAN or a UPC writes
34
+ * its own digits whatever this is.
35
+ */
36
+ text?: string;
37
+ /**
38
+ * An EAN or a UPC in one part, with every bar the same height and no
39
+ * digit outside the bars.
40
+ * @default false
41
+ */
42
+ flat?: boolean;
43
+ }
44
+ /**
45
+ * The bars for a value, or `null` if this kind of barcode can't hold it:
46
+ * a letter in an EAN, a check digit that's wrong, an odd number of digits
47
+ * in an ITF, nothing at all.
48
+ *
49
+ * It needs no browser, so it runs wherever the value is checked.
50
+ */
51
+ export declare function encodeBarcode(value: string, type?: BarcodeType, { text, flat }?: BarcodeEncodeOptions): BarcodeEncoding | null;
52
+ //#endregion