11import { hidePropertiesIn , hidePropertyIn , Properties } from "@mendix/pluggable-widgets-tools" ;
22import { StructurePreviewProps } from "@mendix/widget-plugin-platform/preview/structure-preview-api" ;
33import { BarcodeGeneratorPreviewProps , CodeFormatEnum , CustomCodeFormatEnum } from "../typings/BarcodeGeneratorProps" ;
4- import { validateAddonValue , validateBarcodeValue } from "./config/validation" ;
4+ import { validateAddonValue , validateBarcodeValue , validateGs1DataMatrixValue } from "./config/validation" ;
55
66export type Problem = {
77 property ?: string ; // key of the property, at which the problem exists
@@ -13,7 +13,12 @@ export type Problem = {
1313} ;
1414
1515export function getProperties ( values : BarcodeGeneratorPreviewProps , defaultProperties : Properties ) : Properties {
16- if ( values . codeFormat === "QRCode" ) {
16+ const isQrCode = values . codeFormat === "QRCode" ;
17+ const isDataMatrix = values . codeFormat === "DataMatrix" ;
18+ // Both "Barcode" (CODE128) and "Custom" render as 1D barcodes through JsBarcode
19+ const isBarcode = ! isQrCode && ! isDataMatrix ;
20+
21+ if ( isQrCode ) {
1722 hidePropertiesIn ( defaultProperties , values , [ "codeWidth" , "codeHeight" , "displayValue" , "codeMargin" ] ) ;
1823 } else {
1924 hidePropertiesIn ( defaultProperties , values , [
@@ -26,7 +31,15 @@ export function getProperties(values: BarcodeGeneratorPreviewProps, defaultPrope
2631 ] ) ;
2732 }
2833
29- if ( values . codeFormat !== "QRCode" || ! values . qrOverlay ) {
34+ if ( isDataMatrix ) {
35+ // Data Matrix is a 2D symbol: bar width/height, the human-readable value and the
36+ // pixel-based 1D margin don't apply — it uses dmMargin (module units) instead
37+ hidePropertiesIn ( defaultProperties , values , [ "codeWidth" , "codeHeight" , "displayValue" , "codeMargin" ] ) ;
38+ } else {
39+ hidePropertiesIn ( defaultProperties , values , [ "dmGs1Mode" , "dmShape" , "dmSize" , "dmMargin" ] ) ;
40+ }
41+
42+ if ( ! isQrCode || ! values . qrOverlay ) {
3043 hidePropertiesIn ( defaultProperties , values , [
3144 "qrOverlaySrc" ,
3245 "qrOverlayCenter" ,
@@ -39,7 +52,8 @@ export function getProperties(values: BarcodeGeneratorPreviewProps, defaultPrope
3952 ] ) ;
4053 }
4154
42- if ( values . codeFormat === "QRCode" || ( values . codeFormat !== "CODE128" && values . customCodeFormat !== "CODE128" ) ) {
55+ // EAN-128 only applies to CODE128, either as the top-level format or the custom one
56+ if ( ! isBarcode || ( values . codeFormat === "Custom" && values . customCodeFormat !== "CODE128" ) ) {
4357 hidePropertyIn ( defaultProperties , values , "enableEan128" ) ;
4458 }
4559
@@ -63,29 +77,20 @@ export function getProperties(values: BarcodeGeneratorPreviewProps, defaultPrope
6377 }
6478
6579 // EAN addons are only supported for EAN-13, EAN-8, and UPC
66- if (
67- values . codeFormat === "QRCode" ||
68- values . codeFormat === "CODE128" ||
69- ( values . codeFormat === "Custom" &&
70- values . customCodeFormat !== "EAN13" &&
71- values . customCodeFormat !== "EAN8" &&
72- values . customCodeFormat !== "UPC" )
73- ) {
80+ const supportsAddons =
81+ values . codeFormat === "Custom" &&
82+ ( values . customCodeFormat === "EAN13" ||
83+ values . customCodeFormat === "EAN8" ||
84+ values . customCodeFormat === "UPC" ) ;
85+ if ( ! supportsAddons ) {
7486 hidePropertiesIn ( defaultProperties , values , [ "addonFormat" , "addonValue" , "addonSpacing" ] ) ;
7587 }
76- if (
77- values . codeFormat === "QRCode" ||
78- values . codeFormat === "CODE128" ||
79- ( values . codeFormat === "Custom" && values . addonFormat !== "EAN5" && values . addonFormat !== "EAN2" )
80- ) {
88+ if ( ! supportsAddons || ( values . addonFormat !== "EAN5" && values . addonFormat !== "EAN2" ) ) {
8189 hidePropertiesIn ( defaultProperties , values , [ "addonValue" , "addonSpacing" ] ) ;
8290 }
8391
84- if (
85- values . codeFormat === "QRCode" ||
86- values . codeFormat === "CODE128" ||
87- ( values . codeFormat === "Custom" && values . customCodeFormat !== "CODE39" )
88- ) {
92+ // Mod43 is a CODE39 check digit
93+ if ( ! ( values . codeFormat === "Custom" && values . customCodeFormat === "CODE39" ) ) {
8994 hidePropertyIn ( defaultProperties , values , "enableMod43" ) ;
9095 }
9196
@@ -118,30 +123,52 @@ export function getPreview(_: StructurePreviewProps, _isDarkMode: boolean): Stru
118123export function check ( _values : BarcodeGeneratorPreviewProps ) : Problem [ ] {
119124 const errors : Problem [ ] = [ ] ;
120125
121- if ( ! _values . codeWidth || _values . codeWidth < 1 ) {
122- errors . push ( {
123- property : `codeWidth` ,
124- severity : "error" ,
125- message : `The value of 'Bar width' must be at least 1.`
126- } ) ;
127- }
126+ // Only validate the sizing properties that are visible for the selected format
127+ if ( _values . codeFormat !== "QRCode" && _values . codeFormat !== "DataMatrix" ) {
128+ if ( ! _values . codeWidth || _values . codeWidth < 1 ) {
129+ errors . push ( {
130+ property : `codeWidth` ,
131+ severity : "error" ,
132+ message : `The value of 'Bar width' must be at least 1.`
133+ } ) ;
134+ }
128135
129- if ( ! _values . codeHeight || _values . codeHeight < 20 ) {
130- errors . push ( {
131- property : `codeHeight` ,
132- severity : "error" ,
133- message : `The value of 'Code height' must be at least 20.`
134- } ) ;
136+ if ( ! _values . codeHeight || _values . codeHeight < 20 ) {
137+ errors . push ( {
138+ property : `codeHeight` ,
139+ severity : "error" ,
140+ message : `The value of 'Code height' must be at least 20.`
141+ } ) ;
142+ }
135143 }
136144
137- if ( ! _values . qrSize || _values . qrSize < 50 ) {
145+ if ( _values . codeFormat === "QRCode" && ( ! _values . qrSize || _values . qrSize < 50 ) ) {
138146 errors . push ( {
139- property : `codeHeight ` ,
147+ property : `qrSize ` ,
140148 severity : "error" ,
141149 message : `The value of 'QR size' must be at least 50.`
142150 } ) ;
143151 }
144152
153+ if ( _values . codeFormat === "DataMatrix" ) {
154+ if ( ! _values . dmSize || _values . dmSize < 32 ) {
155+ errors . push ( {
156+ property : `dmSize` ,
157+ severity : "error" ,
158+ message : `The value of 'Data Matrix size' must be at least 32.`
159+ } ) ;
160+ }
161+
162+ // The Data Matrix spec requires a quiet zone of at least one module on every side
163+ if ( ! _values . dmMargin || _values . dmMargin < 1 ) {
164+ errors . push ( {
165+ property : `dmMargin` ,
166+ severity : "warning" ,
167+ message : `A Data Matrix needs a quiet zone of at least 1 module unit to stay scannable.`
168+ } ) ;
169+ }
170+ }
171+
145172 // Design-time validation for static barcode value(s)
146173 const valueProblems = validateCodeValues ( _values ) ;
147174 return errors . concat ( valueProblems ) ;
@@ -183,7 +210,8 @@ function getFormatHint(format: string): string {
183210 MSI : "MSI: numeric only (max 30 digits)" ,
184211 pharmacode : "Pharmacode: numeric only (max 7 digits)" ,
185212 codabar : "Codabar: digits, A-D start/stop, and - $ : / . + (max 20 chars)" ,
186- QRCode : "QR Code: any text (max 1200 chars recommended)"
213+ QRCode : "QR Code: any text (max 1200 chars recommended)" ,
214+ DataMatrix : "Data Matrix: any text; GS1 mode expects Application Identifier syntax, e.g. (01)09501101020917"
187215 } ;
188216 return hints [ format ] || "" ;
189217}
@@ -214,6 +242,11 @@ function validateCodeValues(values: BarcodeGeneratorPreviewProps): Problem[] {
214242 if ( ! result . valid ) {
215243 const msg = result . message || "Invalid barcode value for selected format." ;
216244 problems . push ( { property : "codeValue" , severity : "error" , message : msg } ) ;
245+ } else if ( format === "DataMatrix" && values . dmGs1Mode ) {
246+ const gs1Result = validateGs1DataMatrixValue ( val ) ;
247+ if ( ! gs1Result . valid ) {
248+ problems . push ( { property : "codeValue" , severity : "error" , message : gs1Result . message } ) ;
249+ }
217250 }
218251 }
219252 }
0 commit comments