diff --git a/packages/pluggableWidgets/barcode-generator-web/.prettierrc.js b/packages/pluggableWidgets/barcode-generator-web/.prettierrc.js
new file mode 100644
index 0000000000..0892704ab0
--- /dev/null
+++ b/packages/pluggableWidgets/barcode-generator-web/.prettierrc.js
@@ -0,0 +1 @@
+module.exports = require("@mendix/prettier-config-web-widgets");
diff --git a/packages/pluggableWidgets/barcode-generator-web/CHANGELOG.md b/packages/pluggableWidgets/barcode-generator-web/CHANGELOG.md
new file mode 100644
index 0000000000..861d88dfaf
--- /dev/null
+++ b/packages/pluggableWidgets/barcode-generator-web/CHANGELOG.md
@@ -0,0 +1,15 @@
+# Changelog
+
+All notable changes to this widget will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+## [Unreleased]
+
+## [1.0.0] - 2025-10-09
+
+### Added
+
+- Initial release of QR Code Generator widget
+- Generate QR codes from string input
+- Configurable QR code properties
diff --git a/packages/pluggableWidgets/barcode-generator-web/README.md b/packages/pluggableWidgets/barcode-generator-web/README.md
new file mode 100644
index 0000000000..da6c00ee01
--- /dev/null
+++ b/packages/pluggableWidgets/barcode-generator-web/README.md
@@ -0,0 +1 @@
+
diff --git a/packages/pluggableWidgets/barcode-generator-web/e2e/BarcodeGenerator.spec.js b/packages/pluggableWidgets/barcode-generator-web/e2e/BarcodeGenerator.spec.js
new file mode 100644
index 0000000000..573fa34389
--- /dev/null
+++ b/packages/pluggableWidgets/barcode-generator-web/e2e/BarcodeGenerator.spec.js
@@ -0,0 +1,24 @@
+import { test, expect } from "@playwright/test";
+
+test.afterEach("Cleanup session", async ({ page }) => {
+ // Because the test isolation that will open a new session for every test executed, and that exceeds Mendix's license limit of 5 sessions, so we need to force logout after each test.
+ await page.evaluate(() => window.mx.session.logout());
+});
+
+test.describe("BarcodeGenerator", () => {
+ test.beforeEach(async ({ page }) => {
+ await page.goto("/");
+ await page.waitForLoadState("networkidle");
+ });
+
+ test("renders barcode generator widget", async ({ page }) => {
+ // TODO: Replace with actual barcode generator test when implementation is complete
+ // Example test structure for barcode generator:
+ // await expect(page.locator(".mx-name-barcodeGenerator").first()).toBeVisible();
+ // await page.locator(".mx-name-textInput").fill("Test QR Code");
+ // await expect(page.locator(".mx-name-barcodeGenerator canvas")).toBeVisible();
+
+ // Placeholder test for now
+ await expect(page.locator("body")).toBeVisible();
+ });
+});
diff --git a/packages/pluggableWidgets/barcode-generator-web/eslint.config.mjs b/packages/pluggableWidgets/barcode-generator-web/eslint.config.mjs
new file mode 100644
index 0000000000..ed68ae9e78
--- /dev/null
+++ b/packages/pluggableWidgets/barcode-generator-web/eslint.config.mjs
@@ -0,0 +1,3 @@
+import config from "@mendix/eslint-config-web-widgets/widget-ts.mjs";
+
+export default config;
diff --git a/packages/pluggableWidgets/barcode-generator-web/package.json b/packages/pluggableWidgets/barcode-generator-web/package.json
new file mode 100644
index 0000000000..f11aecb8cb
--- /dev/null
+++ b/packages/pluggableWidgets/barcode-generator-web/package.json
@@ -0,0 +1,61 @@
+{
+ "name": "@mendix/barcode-generator-web",
+ "widgetName": "BarcodeGenerator",
+ "version": "1.0.0",
+ "description": "Generate barcodes and QR codes from a string input",
+ "copyright": "© Mendix Technology BV 2025. All rights reserved.",
+ "license": "Apache-2.0",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/mendix/web-widgets.git"
+ },
+ "config": {},
+ "mxpackage": {
+ "name": "BarcodeGenerator",
+ "type": "widget",
+ "mpkName": "BarcodeGenerator.mpk"
+ },
+ "packagePath": "com.mendix.widget.web",
+ "marketplace": {
+ "minimumMXVersion": "9.6.0",
+ "appNumber": -1,
+ "appName": "Barcode Generator",
+ "reactReady": true
+ },
+ "testProject": {
+ "githubUrl": "https://github.com/mendix/testProjects",
+ "branchName": "barcode-generator-web"
+ },
+ "scripts": {
+ "build": "pluggable-widgets-tools build:web",
+ "create-gh-release": "rui-create-gh-release",
+ "create-translation": "rui-create-translation",
+ "dev": "pluggable-widgets-tools start:web",
+ "e2e": "echo \"Skipping barcode-generator-web e2e tests\"",
+ "e2edev": "run-e2e dev --with-preps",
+ "format": "prettier --ignore-path ./node_modules/@mendix/prettier-config-web-widgets/global-prettierignore --write .",
+ "lint": "eslint src/ package.json",
+ "publish-marketplace": "rui-publish-marketplace",
+ "release": "pluggable-widgets-tools release:web",
+ "start": "pluggable-widgets-tools start:server",
+ "test": "pluggable-widgets-tools test:unit:web:enzyme-free",
+ "update-changelog": "rui-update-changelog-widget",
+ "verify": "rui-verify-package-format"
+ },
+ "dependencies": {
+ "classnames": "^2.5.1",
+ "jsbarcode": "^3.12.1",
+ "qrcode.react": "^4.2.0"
+ },
+ "devDependencies": {
+ "@mendix/automation-utils": "workspace:*",
+ "@mendix/eslint-config-web-widgets": "workspace:*",
+ "@mendix/pluggable-widgets-tools": "*",
+ "@mendix/prettier-config-web-widgets": "workspace:*",
+ "@mendix/run-e2e": "workspace:*",
+ "@mendix/widget-plugin-component-kit": "workspace:*",
+ "@mendix/widget-plugin-platform": "workspace:*",
+ "@mendix/widget-plugin-test-utils": "workspace:*",
+ "cross-env": "^7.0.3"
+ }
+}
diff --git a/packages/pluggableWidgets/barcode-generator-web/playwright.config.cjs b/packages/pluggableWidgets/barcode-generator-web/playwright.config.cjs
new file mode 100644
index 0000000000..29045fc372
--- /dev/null
+++ b/packages/pluggableWidgets/barcode-generator-web/playwright.config.cjs
@@ -0,0 +1 @@
+module.exports = require("@mendix/run-e2e/playwright.config.cjs");
diff --git a/packages/pluggableWidgets/barcode-generator-web/src/BarcodeGenerator.editorConfig.ts b/packages/pluggableWidgets/barcode-generator-web/src/BarcodeGenerator.editorConfig.ts
new file mode 100644
index 0000000000..077e6c5783
--- /dev/null
+++ b/packages/pluggableWidgets/barcode-generator-web/src/BarcodeGenerator.editorConfig.ts
@@ -0,0 +1,54 @@
+import { hidePropertiesIn, Properties } from "@mendix/pluggable-widgets-tools";
+import { BarcodeGeneratorPreviewProps } from "../typings/BarcodeGeneratorProps";
+
+export type Problem = {
+ property?: string; // key of the property, at which the problem exists
+ severity?: "error" | "warning" | "deprecation"; // default = "error"
+ message: string; // description of the problem
+ studioMessage?: string; // studio-specific message, defaults to message
+ url?: string; // link with more information about the problem
+ studioUrl?: string; // studio-specific link
+};
+
+export function getProperties(values: BarcodeGeneratorPreviewProps, defaultProperties: Properties): Properties {
+ if (values.codeFormat === "QRCode") {
+ hidePropertiesIn(defaultProperties, values, ["codeWidth", "codeHeight", "displayValue"]);
+ } else {
+ hidePropertiesIn(defaultProperties, values, ["qrSize"]);
+ }
+
+ if (values.codeFormat !== "Custom") {
+ hidePropertiesIn(defaultProperties, values, ["customCodeFormat"]);
+ }
+ return defaultProperties;
+}
+
+export function check(_values: BarcodeGeneratorPreviewProps): Problem[] {
+ const errors: Problem[] = [];
+
+ if (!_values.codeWidth || _values.codeWidth < 1) {
+ errors.push({
+ property: `codeWidth`,
+ severity: "error",
+ message: `The value of 'Bar width' must be at least 1.`
+ });
+ }
+
+ if (!_values.codeHeight || _values.codeHeight < 20) {
+ errors.push({
+ property: `codeHeight`,
+ severity: "error",
+ message: `The value of 'Code height' must be at least 20.`
+ });
+ }
+
+ if (!_values.qrSize || _values.qrSize < 50) {
+ errors.push({
+ property: `codeHeight`,
+ severity: "error",
+ message: `The value of 'QR size' must be at least 50.`
+ });
+ }
+
+ return errors;
+}
diff --git a/packages/pluggableWidgets/barcode-generator-web/src/BarcodeGenerator.editorPreview.tsx b/packages/pluggableWidgets/barcode-generator-web/src/BarcodeGenerator.editorPreview.tsx
new file mode 100644
index 0000000000..3d0cebc9ba
--- /dev/null
+++ b/packages/pluggableWidgets/barcode-generator-web/src/BarcodeGenerator.editorPreview.tsx
@@ -0,0 +1,13 @@
+import { ReactElement } from "react";
+import { BarcodeGeneratorPreviewProps } from "../typings/BarcodeGeneratorProps";
+import BarcodePreviewSVG from "./assets/BarcodeGeneratorPreview.svg";
+
+export function preview(_props: BarcodeGeneratorPreviewProps): ReactElement {
+ const doc = decodeURI(BarcodePreviewSVG);
+
+ return (
+
+

+
+ );
+}
diff --git a/packages/pluggableWidgets/barcode-generator-web/src/BarcodeGenerator.icon.dark.png b/packages/pluggableWidgets/barcode-generator-web/src/BarcodeGenerator.icon.dark.png
new file mode 100644
index 0000000000..b64899dac6
Binary files /dev/null and b/packages/pluggableWidgets/barcode-generator-web/src/BarcodeGenerator.icon.dark.png differ
diff --git a/packages/pluggableWidgets/barcode-generator-web/src/BarcodeGenerator.icon.png b/packages/pluggableWidgets/barcode-generator-web/src/BarcodeGenerator.icon.png
new file mode 100644
index 0000000000..7f5366d1e9
Binary files /dev/null and b/packages/pluggableWidgets/barcode-generator-web/src/BarcodeGenerator.icon.png differ
diff --git a/packages/pluggableWidgets/barcode-generator-web/src/BarcodeGenerator.tile.dark.png b/packages/pluggableWidgets/barcode-generator-web/src/BarcodeGenerator.tile.dark.png
new file mode 100644
index 0000000000..863f1f715d
Binary files /dev/null and b/packages/pluggableWidgets/barcode-generator-web/src/BarcodeGenerator.tile.dark.png differ
diff --git a/packages/pluggableWidgets/barcode-generator-web/src/BarcodeGenerator.tile.png b/packages/pluggableWidgets/barcode-generator-web/src/BarcodeGenerator.tile.png
new file mode 100644
index 0000000000..57de645b44
Binary files /dev/null and b/packages/pluggableWidgets/barcode-generator-web/src/BarcodeGenerator.tile.png differ
diff --git a/packages/pluggableWidgets/barcode-generator-web/src/BarcodeGenerator.tsx b/packages/pluggableWidgets/barcode-generator-web/src/BarcodeGenerator.tsx
new file mode 100644
index 0000000000..a6e3c41aae
--- /dev/null
+++ b/packages/pluggableWidgets/barcode-generator-web/src/BarcodeGenerator.tsx
@@ -0,0 +1,53 @@
+import JsBarcode from "jsbarcode";
+import { QRCodeSVG } from "qrcode.react";
+import { ReactElement, useEffect, useRef } from "react";
+import { BarcodeGeneratorContainerProps } from "../typings/BarcodeGeneratorProps";
+
+import "./ui/BarcodeGenerator.scss";
+
+export default function BarcodeGenerator({
+ codeValue,
+ codeWidth,
+ codeHeight,
+ codeFormat,
+ codeMargin,
+ displayValue,
+ qrSize,
+ tabIndex
+}: BarcodeGeneratorContainerProps): ReactElement {
+ const svgRef = useRef(null);
+
+ const value = codeValue?.status === "available" ? codeValue.value : "";
+ const width = codeWidth ?? 128;
+ const height = codeHeight ?? 128;
+ const format = codeFormat ?? "CODE128";
+ const margin = codeMargin ?? 2;
+ const showValue = displayValue ?? false;
+ const size = qrSize ?? 128;
+
+ useEffect(() => {
+ if (format !== "QRCode" && svgRef.current && value) {
+ try {
+ JsBarcode(svgRef.current, value, {
+ format,
+ width,
+ height,
+ margin,
+ displayValue: showValue
+ });
+ } catch (error) {
+ console.error("Error generating barcode:", error);
+ }
+ }
+ }, [value, width, height, format, margin, showValue]);
+
+ if (!value) {
+ return No barcode value provided;
+ }
+
+ return (
+
+ {format === "QRCode" ? : }
+
+ );
+}
diff --git a/packages/pluggableWidgets/barcode-generator-web/src/BarcodeGenerator.xml b/packages/pluggableWidgets/barcode-generator-web/src/BarcodeGenerator.xml
new file mode 100644
index 0000000000..d4ea655914
--- /dev/null
+++ b/packages/pluggableWidgets/barcode-generator-web/src/BarcodeGenerator.xml
@@ -0,0 +1,72 @@
+
+
+ Barcode Generator
+ Generate barcodes and QR codes from a string input
+ Display
+ Display
+
+
+
+
+
+ Dynamic value
+ String to encode in the QR code
+
+
+
+
+
+ Barcode Format
+ Choose between QR or other barcode types
+
+ Barcode
+ QR Code
+ Custom Format
+
+
+
+
+
+ Display value
+ Display the value below the code
+
+
+ Bar width
+ Width of the barcode bars
+
+
+ Code height
+ In pixels
+
+
+ QR Size
+ The size of the QR box
+
+
+ Margin size
+ In pixels
+
+
+
+
+
+ Barcode Format
+ Choose between barcode types format
+
+ CODE128
+ EAN-13
+ EAN-8
+ EAN-5
+ EAN-2
+ UPC
+ CODE39
+ ITF-14
+ MSI
+ Pharmacode
+ Codabar
+ CODE93
+
+
+
+
+
diff --git a/packages/pluggableWidgets/barcode-generator-web/src/__tests__/BarcodeGenerator.spec.tsx b/packages/pluggableWidgets/barcode-generator-web/src/__tests__/BarcodeGenerator.spec.tsx
new file mode 100644
index 0000000000..ff4c4e1464
--- /dev/null
+++ b/packages/pluggableWidgets/barcode-generator-web/src/__tests__/BarcodeGenerator.spec.tsx
@@ -0,0 +1,213 @@
+import "@testing-library/jest-dom";
+import { render, screen } from "@testing-library/react";
+import { EditableValueBuilder } from "@mendix/widget-plugin-test-utils";
+
+// Mock JsBarcode
+const mockJsBarcode = jest.fn();
+const barcodeDefaultValue = `default barcode value`;
+jest.mock("jsbarcode", () => mockJsBarcode);
+
+// Mock the QRCodeSVG component
+jest.mock("qrcode.react", () => ({
+ QRCodeSVG: ({ value, size }: { value: string; size: number }) => (
+
+ QR Code: {value}
+
+ )
+}));
+
+import BarcodeGenerator from "../BarcodeGenerator";
+import { CodeFormatEnum, CustomCodeFormatEnum } from "typings/BarcodeGeneratorProps";
+
+describe("BarcodeGenerator", () => {
+ const defaultProps = {
+ name: "barcodeGenerator1",
+ class: "mx-barcode-generator",
+ tabIndex: -1,
+ codeFormat: "QRCode" as CodeFormatEnum,
+ displayValue: false,
+ codeWidth: 2,
+ codeHeight: 200,
+ qrSize: 128,
+ codeMargin: 4,
+ customCodeFormat: "CODE128" as CustomCodeFormatEnum,
+ codeValue: new EditableValueBuilder().withValue(barcodeDefaultValue).build()
+ };
+
+ beforeEach(() => {
+ jest.clearAllMocks();
+ });
+
+ it("renders QR code when value is available", () => {
+ const props = {
+ ...defaultProps,
+ codeValue: {
+ value: "Hello World",
+ status: "available"
+ } as any
+ };
+
+ render();
+
+ expect(screen.getByTestId("qr-code")).toBeInTheDocument();
+ expect(screen.getByTestId("qr-code")).toHaveAttribute("data-value", "Hello World");
+ expect(screen.getByTestId("qr-code")).toHaveAttribute("data-size", "128");
+ });
+
+ it("shows no barcode message when data is loading", () => {
+ const props = {
+ ...defaultProps,
+ codeValue: {
+ value: "",
+ status: "loading"
+ } as any
+ };
+
+ render();
+
+ expect(screen.queryByTestId("qr-code")).not.toBeInTheDocument();
+ expect(screen.getByText("No barcode value provided")).toBeInTheDocument();
+ });
+
+ it("shows no barcode message when data is unavailable", () => {
+ const props = {
+ ...defaultProps,
+ codeValue: {
+ value: "",
+ status: "unavailable"
+ } as any
+ };
+
+ render();
+
+ expect(screen.queryByTestId("qr-code")).not.toBeInTheDocument();
+ expect(screen.getByText("No barcode value provided")).toBeInTheDocument();
+ });
+
+ it("renders CODE128 barcode when format is not QR", () => {
+ const props = {
+ ...defaultProps,
+ codeFormat: "CODE128" as const,
+ codeValue: {
+ value: "123456789",
+ status: "available"
+ } as any
+ };
+
+ render();
+
+ // Should not render QR code
+ expect(screen.queryByTestId("qr-code")).not.toBeInTheDocument();
+
+ // Should have called JsBarcode
+ expect(mockJsBarcode).toHaveBeenCalledWith(
+ expect.any(Object), // SVG element
+ "123456789",
+ {
+ format: "CODE128",
+ width: 2,
+ height: 200,
+ margin: 4,
+ displayValue: false
+ }
+ );
+ });
+
+ it("renders QR code with custom size", () => {
+ const props = {
+ ...defaultProps,
+ qrSize: 256,
+ codeValue: {
+ value: "Custom Size QR",
+ status: "available"
+ } as any
+ };
+
+ render();
+
+ expect(screen.getByTestId("qr-code")).toHaveAttribute("data-size", "256");
+ });
+
+ it("passes displayValue option to JSBarcode for non-QR codes", () => {
+ const props = {
+ ...defaultProps,
+ codeFormat: "CODE128" as const,
+ displayValue: true,
+ codeValue: {
+ value: "DISPLAY123",
+ status: "available"
+ } as any
+ };
+
+ render();
+
+ expect(mockJsBarcode).toHaveBeenCalledWith(
+ expect.any(Object),
+ "DISPLAY123",
+ expect.objectContaining({
+ displayValue: true
+ })
+ );
+ });
+
+ it("handles JSBarcode errors gracefully", () => {
+ const consoleSpy = jest.spyOn(console, "error").mockImplementation();
+ mockJsBarcode.mockImplementation(() => {
+ throw new Error("Invalid barcode format");
+ });
+
+ const props = {
+ ...defaultProps,
+ codeFormat: "CODE128" as const,
+ codeValue: {
+ value: "INVALID",
+ status: "available"
+ } as any
+ };
+
+ render();
+
+ expect(consoleSpy).toHaveBeenCalledWith("Error generating barcode:", expect.any(Error));
+ consoleSpy.mockRestore();
+ });
+
+ it("applies correct CSS class and tabIndex", () => {
+ const props = {
+ ...defaultProps,
+ class: "mx-barcode-generator custom-class",
+ tabIndex: 5,
+ codeValue: {
+ value: "CSS Test",
+ status: "available"
+ } as any
+ };
+
+ const { container } = render();
+
+ const widget = container.firstChild as HTMLElement;
+ expect(widget).toHaveClass("barcode-generator");
+ expect(widget).toHaveAttribute("tabIndex", "5");
+ });
+
+ it("uses fallback values when props are missing", () => {
+ const props = {
+ ...defaultProps,
+ codeFormat: "CODE128" as const,
+ codeValue: {
+ value: "DEFAULT_TEST",
+ status: "available"
+ } as any
+ };
+
+ // Component uses nullish coalescing to provide defaults
+ render();
+
+ expect(mockJsBarcode).toHaveBeenCalledWith(expect.any(Object), "DEFAULT_TEST", {
+ format: "CODE128",
+ width: 2, // from defaultProps
+ height: 200, // from defaultProps
+ margin: 4, // from defaultProps
+ displayValue: false
+ });
+ });
+});
diff --git a/packages/pluggableWidgets/barcode-generator-web/src/assets/BarcodeGeneratorPreview.svg b/packages/pluggableWidgets/barcode-generator-web/src/assets/BarcodeGeneratorPreview.svg
new file mode 100644
index 0000000000..aa5601290d
--- /dev/null
+++ b/packages/pluggableWidgets/barcode-generator-web/src/assets/BarcodeGeneratorPreview.svg
@@ -0,0 +1,9 @@
+
diff --git a/packages/pluggableWidgets/barcode-generator-web/src/package.xml b/packages/pluggableWidgets/barcode-generator-web/src/package.xml
new file mode 100644
index 0000000000..e32d216db0
--- /dev/null
+++ b/packages/pluggableWidgets/barcode-generator-web/src/package.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/pluggableWidgets/barcode-generator-web/src/ui/BarcodeGenerator.scss b/packages/pluggableWidgets/barcode-generator-web/src/ui/BarcodeGenerator.scss
new file mode 100644
index 0000000000..e219c30909
--- /dev/null
+++ b/packages/pluggableWidgets/barcode-generator-web/src/ui/BarcodeGenerator.scss
@@ -0,0 +1,6 @@
+// Barcode Generator Widget Styles
+$widget-prefix: "barcode-generator";
+
+.#{$widget-prefix} {
+ display: inline-block;
+}
diff --git a/packages/pluggableWidgets/barcode-generator-web/src/ui/BarcodeGeneratorPreview.scss b/packages/pluggableWidgets/barcode-generator-web/src/ui/BarcodeGeneratorPreview.scss
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/packages/pluggableWidgets/barcode-generator-web/tsconfig.json b/packages/pluggableWidgets/barcode-generator-web/tsconfig.json
new file mode 100644
index 0000000000..7aa60df0c9
--- /dev/null
+++ b/packages/pluggableWidgets/barcode-generator-web/tsconfig.json
@@ -0,0 +1,30 @@
+{
+ "include": ["./src", "./typings"],
+ "compilerOptions": {
+ "baseUrl": "./",
+ "noEmitOnError": true,
+ "sourceMap": true,
+ "module": "esnext",
+ "target": "es6",
+ "lib": ["esnext", "dom"],
+ "types": ["jest", "node"],
+ "moduleResolution": "node",
+ "declaration": false,
+ "noLib": false,
+ "forceConsistentCasingInFileNames": true,
+ "noFallthroughCasesInSwitch": true,
+ "strict": true,
+ "strictFunctionTypes": false,
+ "skipLibCheck": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "jsx": "react-jsx",
+ "allowSyntheticDefaultImports": true,
+ "esModuleInterop": true,
+ "useUnknownInCatchVariables": false,
+ "exactOptionalPropertyTypes": false,
+ "paths": {
+ "react-hot-loader/root": ["./hot-typescript.ts"]
+ }
+ }
+}
diff --git a/packages/pluggableWidgets/barcode-generator-web/typings/BarcodeGeneratorProps.d.ts b/packages/pluggableWidgets/barcode-generator-web/typings/BarcodeGeneratorProps.d.ts
new file mode 100644
index 0000000000..ff747ea4cf
--- /dev/null
+++ b/packages/pluggableWidgets/barcode-generator-web/typings/BarcodeGeneratorProps.d.ts
@@ -0,0 +1,47 @@
+/**
+ * This file was generated from BarcodeGenerator.xml
+ * WARNING: All changes made to this file will be overwritten
+ * @author Mendix Widgets Framework Team
+ */
+import { CSSProperties } from "react";
+import { EditableValue } from "mendix";
+
+export type CodeFormatEnum = "CODE128" | "QRCode" | "Custom";
+
+export type CustomCodeFormatEnum = "CODE128" | "EAN13" | "EAN8" | "EAN5" | "EAN2" | "UPC" | "CODE39" | "ITF14" | "MSI" | "pharmacode" | "codabar" | "CODE93";
+
+export interface BarcodeGeneratorContainerProps {
+ name: string;
+ class: string;
+ style?: CSSProperties;
+ tabIndex?: number;
+ codeValue: EditableValue;
+ codeFormat: CodeFormatEnum;
+ displayValue: boolean;
+ codeWidth: number;
+ codeHeight: number;
+ qrSize: number;
+ codeMargin: number;
+ customCodeFormat: CustomCodeFormatEnum;
+}
+
+export interface BarcodeGeneratorPreviewProps {
+ /**
+ * @deprecated Deprecated since version 9.18.0. Please use class property instead.
+ */
+ className: string;
+ class: string;
+ style: string;
+ styleObject?: CSSProperties;
+ readOnly: boolean;
+ renderMode: "design" | "xray" | "structure";
+ translate: (text: string) => string;
+ codeValue: string;
+ codeFormat: CodeFormatEnum;
+ displayValue: boolean;
+ codeWidth: number | null;
+ codeHeight: number | null;
+ qrSize: number | null;
+ codeMargin: number | null;
+ customCodeFormat: CustomCodeFormatEnum;
+}
diff --git a/packages/pluggableWidgets/barcode-generator-web/typings/declare-svg.ts b/packages/pluggableWidgets/barcode-generator-web/typings/declare-svg.ts
new file mode 100644
index 0000000000..e65f2cb5a6
--- /dev/null
+++ b/packages/pluggableWidgets/barcode-generator-web/typings/declare-svg.ts
@@ -0,0 +1,6 @@
+declare module "*.svg" {
+ const content: string;
+ export = content;
+}
+
+declare module '*.css';
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 5be557a0be..4fb47d0630 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -596,6 +596,46 @@ importers:
specifier: workspace:*
version: link:../../shared/widget-plugin-test-utils
+ packages/pluggableWidgets/barcode-generator-web:
+ dependencies:
+ classnames:
+ specifier: ^2.5.1
+ version: 2.5.1
+ jsbarcode:
+ specifier: ^3.12.1
+ version: 3.12.1
+ qrcode.react:
+ specifier: ^4.2.0
+ version: 4.2.0(react@18.3.1)
+ devDependencies:
+ '@mendix/automation-utils':
+ specifier: workspace:*
+ version: link:../../../automation/utils
+ '@mendix/eslint-config-web-widgets':
+ specifier: workspace:*
+ version: link:../../shared/eslint-config-web-widgets
+ '@mendix/pluggable-widgets-tools':
+ specifier: 10.21.2
+ version: 10.21.2(@jest/transform@29.7.0)(@jest/types@30.2.0)(@swc/core@1.13.5)(@types/babel__core@7.20.5)(@types/node@22.14.1)(jest-util@30.2.0)(picomatch@4.0.3)(react-dom@18.3.1(react@18.3.1))(react-native@0.82.0(@babel/core@7.28.4)(@types/react@19.2.2)(react@18.3.1))(react@18.3.1)(tslib@2.8.1)
+ '@mendix/prettier-config-web-widgets':
+ specifier: workspace:*
+ version: link:../../shared/prettier-config-web-widgets
+ '@mendix/run-e2e':
+ specifier: workspace:*
+ version: link:../../../automation/run-e2e
+ '@mendix/widget-plugin-component-kit':
+ specifier: workspace:*
+ version: link:../../shared/widget-plugin-component-kit
+ '@mendix/widget-plugin-platform':
+ specifier: workspace:*
+ version: link:../../shared/widget-plugin-platform
+ '@mendix/widget-plugin-test-utils':
+ specifier: workspace:*
+ version: link:../../shared/widget-plugin-test-utils
+ cross-env:
+ specifier: ^7.0.3
+ version: 7.0.3
+
packages/pluggableWidgets/barcode-scanner-web:
dependencies:
'@zxing/library':
@@ -7883,6 +7923,9 @@ packages:
resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
hasBin: true
+ jsbarcode@3.12.1:
+ resolution: {integrity: sha512-QZQSqIknC2Rr/YOUyOkCBqsoiBAOTYK+7yNN3JsqfoUtJtkazxNw1dmPpxuv7VVvqW13kA3/mKiLq+s/e3o9hQ==}
+
jsc-safe-url@0.2.4:
resolution: {integrity: sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q==}
@@ -9174,6 +9217,11 @@ packages:
pure-rand@6.1.0:
resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==}
+ qrcode.react@4.2.0:
+ resolution: {integrity: sha512-QpgqWi8rD9DsS9EP3z7BT+5lY5SFhsqGjpgW5DY/i3mK4M9DTBNz3ErMi8BWYEfI3L0d8GIbGmcdFAS1uIRGjA==}
+ peerDependencies:
+ react: '>=18.0.0 <19.0.0'
+
querystringify@2.2.0:
resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==}
@@ -16985,6 +17033,8 @@ snapshots:
dependencies:
argparse: 2.0.1
+ jsbarcode@3.12.1: {}
+
jsc-safe-url@0.2.4: {}
jsdom@20.0.3:
@@ -18494,6 +18544,10 @@ snapshots:
pure-rand@6.1.0: {}
+ qrcode.react@4.2.0(react@18.3.1):
+ dependencies:
+ react: 18.3.1
+
querystringify@2.2.0: {}
queue-microtask@1.2.3: {}