react-id-card-generator 1.1.0 → 1.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.
@@ -186,7 +186,10 @@ const IDCardGenerator = ({ template, data, side = 'front', scale = 1, className
186
186
  case 'image':
187
187
  return (jsxRuntime.jsx("div", { id: field.id, style: combinedStyle, onClick: handleClick, children: value ? (jsxRuntime.jsx("img", { src: String(value), alt: field.label || 'Image', style: {
188
188
  width: '100%',
189
+ height: '100%',
189
190
  display: 'block',
191
+ objectFit: 'cover',
192
+ objectPosition: 'center',
190
193
  } })) : (jsxRuntime.jsx("div", { style: {
191
194
  width: '100%',
192
195
  height: '100%',
@@ -1 +1 @@
1
- {"version":3,"file":"IDCardGenerator.js","sources":["../../../src/components/IDCardGenerator.tsx"],"sourcesContent":["import React, { useMemo } from 'react';\nimport type { IDCardGeneratorProps, FieldMapping, IDCardData, IDCardTemplate } from '../types';\nimport { fieldStyleToCSS, positionToStyle } from '../utils/styleUtils';\nimport { generateQrCodeFromFields, getQrCodeSize } from '../core/qrUtils';\nimport { IDCardTable } from './IDCardTable';\n\r\n/**\r\n * IDCardGenerator - Renders a completed ID card\r\n * \r\n * Takes a template and user data, then renders the filled card.\r\n * This is the component used to display actual ID cards for individual users.\r\n * \r\n * Example:\r\n * ```tsx\r\n * <IDCardGenerator \r\n * template={myTemplate}\r\n * data={{ name: 'John Doe', photo: '...' }}\r\n * side=\"front\"\r\n * />\r\n * ```\r\n */\r\nexport const IDCardGenerator: React.FC<IDCardGeneratorProps> = ({\r\n template,\r\n data,\r\n side = 'front',\r\n scale = 1,\r\n className = '',\r\n style = {},\r\n onFieldClick,\r\n editable = false,\r\n}: IDCardGeneratorProps) => {\r\n // Get fields for the current side only\r\n const fieldsToRender = useMemo(() => {\r\n return template.fields.filter((field: FieldMapping) => field.side === side);\r\n }, [template.fields, side]);\r\n\r\n // Get background for current side\r\n const backgroundImage = side === 'front' ? template.backgrounds.front : template.backgrounds.back;\r\n\r\n // Render a single field\r\n const renderField = (field: FieldMapping) => {\r\n const posStyle = positionToStyle(field.position);\r\n let fieldStyle = fieldStyleToCSS(field.style);\r\n \r\n // Determine flex direction and alignment for text fields\r\n let flexDirection: 'column' | 'row' = 'column';\r\n if (field.type === 'text' && field.style?.labelPosition === 'left') flexDirection = 'row';\r\n\r\n // Map verticalAlign and textAlign to flex properties\r\n let justifyContent: 'flex-start' | 'center' | 'flex-end' = 'flex-start';\r\n let alignItems: 'flex-start' | 'center' | 'flex-end' | undefined = 'flex-start';\r\n if (field.type === 'text') {\r\n const textAlign = field.style?.textTextAlign || field.style?.textAlign || 'left';\r\n const verticalAlign = field.style?.verticalAlign || 'top';\r\n \r\n if (flexDirection === 'column') {\r\n // For column: verticalAlign controls justifyContent (vertical), textAlign controls alignItems (horizontal)\r\n if (verticalAlign === 'middle') justifyContent = 'center';\r\n else if (verticalAlign === 'bottom') justifyContent = 'flex-end';\r\n else justifyContent = 'flex-start';\r\n \r\n if (textAlign === 'center') alignItems = 'center';\r\n else if (textAlign === 'right') alignItems = 'flex-end';\r\n else alignItems = 'flex-start';\r\n } else {\r\n // For row: don't set alignItems on container if individual alignments are specified\r\n // Let labelAlignSelf and textAlignSelf handle it\r\n if (field.style?.labelVerticalAlign || field.style?.textVerticalAlign) {\r\n alignItems = undefined;\r\n } else {\r\n // Fall back to general verticalAlign if individual ones aren't specified\r\n if (verticalAlign === 'middle') alignItems = 'center';\r\n else if (verticalAlign === 'bottom') alignItems = 'flex-end';\r\n else alignItems = 'flex-start';\r\n }\r\n }\r\n }\r\n\r\n // Remove fontSize for label fields so text field font size does not affect them\r\n if (field.type === 'label' && fieldStyle.fontSize) {\r\n const { fontSize, ...rest } = fieldStyle;\r\n fieldStyle = rest;\r\n }\r\n\r\n // Remove textTransform from container for text and label fields - applied directly to spans\r\n if ((field.type === 'text' || field.type === 'label') && fieldStyle.textTransform) {\r\n const { textTransform, ...rest } = fieldStyle;\r\n fieldStyle = rest;\r\n }\r\n\r\n const combinedStyle: React.CSSProperties = {\n ...posStyle,\n ...fieldStyle,\n backgroundColor: field.type === 'qrcode' ? 'transparent' : fieldStyle.backgroundColor,\n zIndex: field.zIndex || 1,\n boxSizing: 'border-box',\n overflow: 'hidden',\n cursor: editable ? 'pointer' : 'default',\n display: field.type === 'text' || field.type === 'qrcode' ? 'flex' : undefined,\n flexDirection: field.type === 'text' ? flexDirection : undefined,\n justifyContent: field.type === 'text' ? justifyContent : field.type === 'qrcode' ? 'center' : undefined,\n alignItems: field.type === 'text' ? alignItems : field.type === 'qrcode' ? 'center' : undefined,\n };\r\n\r\n const handleClick = (e: React.MouseEvent) => {\r\n if (onFieldClick) {\r\n e.stopPropagation();\r\n onFieldClick(field);\r\n }\r\n };\r\n\r\n const value = getFieldValue(field, data);\r\n\r\n switch (field.type) {\r\n case 'text': {\r\n // Label style properties\r\n let labelFontSize = field.style?.labelFontSize;\r\n if (!labelFontSize || labelFontSize === '0.75em') {\r\n labelFontSize = '12px';\r\n } else if (!labelFontSize.endsWith('px')) {\r\n const num = parseFloat(labelFontSize);\r\n if (!isNaN(num)) labelFontSize = num + 'px';\r\n else labelFontSize = '12px';\r\n }\r\n const labelFontWeight = field.style?.labelFontWeight || 'normal';\r\n const labelColor = field.style?.labelColor || '#666666';\r\n const labelTextTransform = field.style?.labelTextTransform || 'none';\r\n const labelTextAlign = field.style?.labelTextAlign || 'left';\r\n \r\n // Text/value style properties (separate from label)\r\n const textFontSize = field.style?.textFontSize || field.style?.fontSize || '1em';\r\n const textFontWeight = field.style?.textFontWeight || field.style?.fontWeight || 'normal';\r\n const textColor = field.style?.textColor || field.style?.color || '#000000';\r\n const textTextTransform = field.style?.textTransform || 'none';\r\n const textTextAlign = field.style?.textTextAlign || field.style?.textAlign || 'left';\r\n \r\n // For row layout (label on left), use individual span alignment\r\n if (field.style?.labelPosition === 'left') {\r\n let labelAlignSelf: React.CSSProperties['alignSelf'] = 'flex-start';\r\n if (field.style?.labelVerticalAlign === 'middle') labelAlignSelf = 'center';\r\n else if (field.style?.labelVerticalAlign === 'bottom') labelAlignSelf = 'flex-end';\r\n \r\n let textAlignSelf: React.CSSProperties['alignSelf'] = 'flex-start';\r\n if (field.style?.textVerticalAlign === 'middle') textAlignSelf = 'center';\r\n else if (field.style?.textVerticalAlign === 'bottom') textAlignSelf = 'flex-end';\r\n \r\n const labelStyle: React.CSSProperties = { \r\n fontSize: labelFontSize, \n fontWeight: labelFontWeight, \n color: labelColor, \n marginRight: 8, \n alignSelf: labelAlignSelf, \n whiteSpace: 'nowrap', \n textTransform: labelTextTransform \r\n };\r\n \r\n const textStyle: React.CSSProperties = { \r\n textTransform: textTextTransform, \r\n fontSize: textFontSize, \r\n fontWeight: textFontWeight, \r\n color: textColor, \r\n alignSelf: textAlignSelf\r\n };\r\n \r\n return (\r\n <div\r\n key={field.id}\r\n id={field.id}\r\n style={combinedStyle}\r\n onClick={handleClick}\r\n className=\"idcard-field idcard-field-text\"\r\n >\r\n {field.label && (\r\n <span className=\"idcard-field-label\" style={labelStyle}>\r\n {field.label}\r\n </span>\r\n )}\r\n <span style={{ width: '100%', textAlign: textTextAlign }}>\r\n <span className=\"idcard-field-value\" style={textStyle}>{String(value || field.placeholder || '')}</span>\r\n </span>\r\n </div>\r\n );\r\n } else {\r\n // For column layout (label on top), let container alignment handle positioning\r\n const labelStyle: React.CSSProperties = { \r\n fontSize: labelFontSize, \n fontWeight: labelFontWeight, \n color: labelColor, \n textTransform: labelTextTransform,\n width: '100%',\n textAlign: labelTextAlign\n };\r\n \r\n const textStyle: React.CSSProperties = { \r\n textTransform: textTextTransform, \r\n fontSize: textFontSize, \r\n fontWeight: textFontWeight, \r\n color: textColor,\r\n width: '100%',\r\n textAlign: textTextAlign\r\n };\r\n \r\n return (\r\n <div\r\n key={field.id}\r\n id={field.id}\r\n style={combinedStyle}\r\n onClick={handleClick}\r\n className=\"idcard-field idcard-field-text\"\r\n >\r\n {field.label && (\r\n <span className=\"idcard-field-label\" style={labelStyle}>\r\n {field.label}\r\n </span>\r\n )}\r\n <span className=\"idcard-field-value\" style={textStyle}>{String(value || field.placeholder || '')}</span>\r\n </div>\r\n );\r\n }\r\n }\r\n\r\n case 'label': {\r\n const labelTextTransform = field.style?.labelTextTransform || 'none';\r\n return (\r\n <div\r\n key={field.id}\r\n id={field.id}\r\n style={combinedStyle}\r\n onClick={handleClick}\r\n className=\"idcard-field idcard-field-label\"\r\n >\r\n <span style={{ textTransform: labelTextTransform }}>{field.staticText || field.label || ''}</span>\r\n </div>\r\n );\r\n }\r\n\r\n case 'image':\r\n return (\r\n <div\r\n key={field.id}\r\n id={field.id}\r\n style={combinedStyle}\r\n onClick={handleClick}\r\n >\r\n {value ? (\r\n <img\r\n src={String(value)}\r\n alt={field.label || 'Image'}\r\n style={{\r\n width: '100%',\r\n display: 'block',\r\n }}\r\n />\r\n ) : (\r\n <div\r\n style={{\r\n width: '100%',\r\n height: '100%',\r\n backgroundColor: '#e0e0e0',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n fontSize: '10px',\r\n color: '#666',\r\n }}\r\n >\r\n {field.label || 'Photo'}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n\n case 'qrcode':\n const qrSize = getQrCodeSize(field.position.width, field.position.height);\n const qrDataUrl = field.qrFields?.length\n ? generateQrCodeFromFields(\n data,\n field.qrFields,\n qrSize\n )\n : '';\n\n return (\n <div\n key={field.id}\n id={field.id}\n style={combinedStyle}\n onClick={handleClick}\n className=\"idcard-field idcard-field-qrcode\"\n >\n {qrDataUrl ? (\n <img\n src={qrDataUrl}\n alt=\"QR Code\"\n data-qr-code-image=\"true\"\n style={{\n width: `${qrSize}px`,\n height: `${qrSize}px`,\n display: 'block',\n backgroundColor: 'transparent',\n objectFit: 'contain',\n objectPosition: 'center',\n maxWidth: '100%',\n maxHeight: '100%',\n flexShrink: 0,\n }}\n />\n ) : (\n <div\r\n style={{\r\n width: '100%',\r\n height: '100%',\r\n backgroundColor: '#f0f0f0',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n fontSize: '10px',\r\n color: '#666',\r\n }}\r\n >\r\n QR Code\r\n </div>\r\n )}\n </div>\n );\n\n case 'table':\n return (\n <div\n key={field.id}\n id={field.id}\n style={combinedStyle}\n onClick={handleClick}\n className=\"idcard-field idcard-field-table\"\n >\n <IDCardTable field={field} data={data} />\n </div>\n );\n\n default:\n return null;\n }\n };\n\r\n // Card container style\r\n const cardStyle: React.CSSProperties = {\r\n width: Math.round(template.cardSize.width),\r\n height: Math.round(template.cardSize.height),\r\n position: 'relative',\r\n overflow: 'hidden',\r\n backgroundColor: '#fff',\r\n ...style,\r\n };\r\n\r\n return (\r\n <div\r\n id={side === 'front' ? 'idcardfront' : 'idcardback'}\r\n className={`idcard-container idcard-${side} ${className}`}\r\n style={cardStyle}\r\n >\r\n {/* Background */}\r\n {backgroundImage && (\r\n <img\r\n src={backgroundImage}\r\n alt={`${side} background`}\r\n style={{\r\n position: 'absolute',\r\n top: 0,\r\n left: 0,\r\n width: `${Math.round(template.cardSize.width)}px`,\r\n height: `${Math.round(template.cardSize.height)}px`,\r\n zIndex: 0,\r\n }}\r\n />\r\n )}\r\n\r\n {/* Fields */}\r\n {fieldsToRender.map(renderField)}\r\n </div>\r\n );\r\n};\r\n\r\n/**\r\n * Get field value from data based on field configuration\r\n */\r\nfunction getFieldValue(field: FieldMapping, data: IDCardData): string | number | undefined {\n if (field.type === 'label') {\n return field.staticText;\n }\n\n const value = data[field.fieldKey];\n\n // Handle array values (like department)\n if (Array.isArray(value)) {\n const firstValue = value[0];\n if (firstValue && typeof firstValue === 'object') {\n return undefined;\n }\n\n return firstValue;\n }\n\n return value as string | number | undefined;\n}\n\r\n"],"names":["useMemo","positionToStyle","fieldStyleToCSS","_jsxs","_jsx","getQrCodeSize","generateQrCodeFromFields","IDCardTable"],"mappings":"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"}
1
+ {"version":3,"file":"IDCardGenerator.js","sources":["../../../src/components/IDCardGenerator.tsx"],"sourcesContent":["import React, { useMemo } from 'react';\nimport type { IDCardGeneratorProps, FieldMapping, IDCardData, IDCardTemplate } from '../types';\nimport { fieldStyleToCSS, positionToStyle } from '../utils/styleUtils';\nimport { generateQrCodeFromFields, getQrCodeSize } from '../core/qrUtils';\nimport { IDCardTable } from './IDCardTable';\n\r\n/**\r\n * IDCardGenerator - Renders a completed ID card\r\n * \r\n * Takes a template and user data, then renders the filled card.\r\n * This is the component used to display actual ID cards for individual users.\r\n * \r\n * Example:\r\n * ```tsx\r\n * <IDCardGenerator \r\n * template={myTemplate}\r\n * data={{ name: 'John Doe', photo: '...' }}\r\n * side=\"front\"\r\n * />\r\n * ```\r\n */\r\nexport const IDCardGenerator: React.FC<IDCardGeneratorProps> = ({\r\n template,\r\n data,\r\n side = 'front',\r\n scale = 1,\r\n className = '',\r\n style = {},\r\n onFieldClick,\r\n editable = false,\r\n}: IDCardGeneratorProps) => {\r\n // Get fields for the current side only\r\n const fieldsToRender = useMemo(() => {\r\n return template.fields.filter((field: FieldMapping) => field.side === side);\r\n }, [template.fields, side]);\r\n\r\n // Get background for current side\r\n const backgroundImage = side === 'front' ? template.backgrounds.front : template.backgrounds.back;\r\n\r\n // Render a single field\r\n const renderField = (field: FieldMapping) => {\r\n const posStyle = positionToStyle(field.position);\r\n let fieldStyle = fieldStyleToCSS(field.style);\r\n \r\n // Determine flex direction and alignment for text fields\r\n let flexDirection: 'column' | 'row' = 'column';\r\n if (field.type === 'text' && field.style?.labelPosition === 'left') flexDirection = 'row';\r\n\r\n // Map verticalAlign and textAlign to flex properties\r\n let justifyContent: 'flex-start' | 'center' | 'flex-end' = 'flex-start';\r\n let alignItems: 'flex-start' | 'center' | 'flex-end' | undefined = 'flex-start';\r\n if (field.type === 'text') {\r\n const textAlign = field.style?.textTextAlign || field.style?.textAlign || 'left';\r\n const verticalAlign = field.style?.verticalAlign || 'top';\r\n \r\n if (flexDirection === 'column') {\r\n // For column: verticalAlign controls justifyContent (vertical), textAlign controls alignItems (horizontal)\r\n if (verticalAlign === 'middle') justifyContent = 'center';\r\n else if (verticalAlign === 'bottom') justifyContent = 'flex-end';\r\n else justifyContent = 'flex-start';\r\n \r\n if (textAlign === 'center') alignItems = 'center';\r\n else if (textAlign === 'right') alignItems = 'flex-end';\r\n else alignItems = 'flex-start';\r\n } else {\r\n // For row: don't set alignItems on container if individual alignments are specified\r\n // Let labelAlignSelf and textAlignSelf handle it\r\n if (field.style?.labelVerticalAlign || field.style?.textVerticalAlign) {\r\n alignItems = undefined;\r\n } else {\r\n // Fall back to general verticalAlign if individual ones aren't specified\r\n if (verticalAlign === 'middle') alignItems = 'center';\r\n else if (verticalAlign === 'bottom') alignItems = 'flex-end';\r\n else alignItems = 'flex-start';\r\n }\r\n }\r\n }\r\n\r\n // Remove fontSize for label fields so text field font size does not affect them\r\n if (field.type === 'label' && fieldStyle.fontSize) {\r\n const { fontSize, ...rest } = fieldStyle;\r\n fieldStyle = rest;\r\n }\r\n\r\n // Remove textTransform from container for text and label fields - applied directly to spans\r\n if ((field.type === 'text' || field.type === 'label') && fieldStyle.textTransform) {\r\n const { textTransform, ...rest } = fieldStyle;\r\n fieldStyle = rest;\r\n }\r\n\r\n const combinedStyle: React.CSSProperties = {\n ...posStyle,\n ...fieldStyle,\n backgroundColor: field.type === 'qrcode' ? 'transparent' : fieldStyle.backgroundColor,\n zIndex: field.zIndex || 1,\n boxSizing: 'border-box',\n overflow: 'hidden',\n cursor: editable ? 'pointer' : 'default',\n display: field.type === 'text' || field.type === 'qrcode' ? 'flex' : undefined,\n flexDirection: field.type === 'text' ? flexDirection : undefined,\n justifyContent: field.type === 'text' ? justifyContent : field.type === 'qrcode' ? 'center' : undefined,\n alignItems: field.type === 'text' ? alignItems : field.type === 'qrcode' ? 'center' : undefined,\n };\r\n\r\n const handleClick = (e: React.MouseEvent) => {\r\n if (onFieldClick) {\r\n e.stopPropagation();\r\n onFieldClick(field);\r\n }\r\n };\r\n\r\n const value = getFieldValue(field, data);\r\n\r\n switch (field.type) {\r\n case 'text': {\r\n // Label style properties\r\n let labelFontSize = field.style?.labelFontSize;\r\n if (!labelFontSize || labelFontSize === '0.75em') {\r\n labelFontSize = '12px';\r\n } else if (!labelFontSize.endsWith('px')) {\r\n const num = parseFloat(labelFontSize);\r\n if (!isNaN(num)) labelFontSize = num + 'px';\r\n else labelFontSize = '12px';\r\n }\r\n const labelFontWeight = field.style?.labelFontWeight || 'normal';\r\n const labelColor = field.style?.labelColor || '#666666';\r\n const labelTextTransform = field.style?.labelTextTransform || 'none';\r\n const labelTextAlign = field.style?.labelTextAlign || 'left';\r\n \r\n // Text/value style properties (separate from label)\r\n const textFontSize = field.style?.textFontSize || field.style?.fontSize || '1em';\r\n const textFontWeight = field.style?.textFontWeight || field.style?.fontWeight || 'normal';\r\n const textColor = field.style?.textColor || field.style?.color || '#000000';\r\n const textTextTransform = field.style?.textTransform || 'none';\r\n const textTextAlign = field.style?.textTextAlign || field.style?.textAlign || 'left';\r\n \r\n // For row layout (label on left), use individual span alignment\r\n if (field.style?.labelPosition === 'left') {\r\n let labelAlignSelf: React.CSSProperties['alignSelf'] = 'flex-start';\r\n if (field.style?.labelVerticalAlign === 'middle') labelAlignSelf = 'center';\r\n else if (field.style?.labelVerticalAlign === 'bottom') labelAlignSelf = 'flex-end';\r\n \r\n let textAlignSelf: React.CSSProperties['alignSelf'] = 'flex-start';\r\n if (field.style?.textVerticalAlign === 'middle') textAlignSelf = 'center';\r\n else if (field.style?.textVerticalAlign === 'bottom') textAlignSelf = 'flex-end';\r\n \r\n const labelStyle: React.CSSProperties = { \r\n fontSize: labelFontSize, \n fontWeight: labelFontWeight, \n color: labelColor, \n marginRight: 8, \n alignSelf: labelAlignSelf, \n whiteSpace: 'nowrap', \n textTransform: labelTextTransform \r\n };\r\n \r\n const textStyle: React.CSSProperties = { \r\n textTransform: textTextTransform, \r\n fontSize: textFontSize, \r\n fontWeight: textFontWeight, \r\n color: textColor, \r\n alignSelf: textAlignSelf\r\n };\r\n \r\n return (\r\n <div\r\n key={field.id}\r\n id={field.id}\r\n style={combinedStyle}\r\n onClick={handleClick}\r\n className=\"idcard-field idcard-field-text\"\r\n >\r\n {field.label && (\r\n <span className=\"idcard-field-label\" style={labelStyle}>\r\n {field.label}\r\n </span>\r\n )}\r\n <span style={{ width: '100%', textAlign: textTextAlign }}>\r\n <span className=\"idcard-field-value\" style={textStyle}>{String(value || field.placeholder || '')}</span>\r\n </span>\r\n </div>\r\n );\r\n } else {\r\n // For column layout (label on top), let container alignment handle positioning\r\n const labelStyle: React.CSSProperties = { \r\n fontSize: labelFontSize, \n fontWeight: labelFontWeight, \n color: labelColor, \n textTransform: labelTextTransform,\n width: '100%',\n textAlign: labelTextAlign\n };\r\n \r\n const textStyle: React.CSSProperties = { \r\n textTransform: textTextTransform, \r\n fontSize: textFontSize, \r\n fontWeight: textFontWeight, \r\n color: textColor,\r\n width: '100%',\r\n textAlign: textTextAlign\r\n };\r\n \r\n return (\r\n <div\r\n key={field.id}\r\n id={field.id}\r\n style={combinedStyle}\r\n onClick={handleClick}\r\n className=\"idcard-field idcard-field-text\"\r\n >\r\n {field.label && (\r\n <span className=\"idcard-field-label\" style={labelStyle}>\r\n {field.label}\r\n </span>\r\n )}\r\n <span className=\"idcard-field-value\" style={textStyle}>{String(value || field.placeholder || '')}</span>\r\n </div>\r\n );\r\n }\r\n }\r\n\r\n case 'label': {\r\n const labelTextTransform = field.style?.labelTextTransform || 'none';\r\n return (\r\n <div\r\n key={field.id}\r\n id={field.id}\r\n style={combinedStyle}\r\n onClick={handleClick}\r\n className=\"idcard-field idcard-field-label\"\r\n >\r\n <span style={{ textTransform: labelTextTransform }}>{field.staticText || field.label || ''}</span>\r\n </div>\r\n );\r\n }\r\n\r\n case 'image':\r\n return (\r\n <div\r\n key={field.id}\r\n id={field.id}\r\n style={combinedStyle}\r\n onClick={handleClick}\r\n >\r\n {value ? (\r\n <img\r\n src={String(value)}\r\n alt={field.label || 'Image'}\r\n style={{\n width: '100%',\n height: '100%',\n display: 'block',\n objectFit: 'cover',\n objectPosition: 'center',\n }}\n />\n ) : (\r\n <div\r\n style={{\r\n width: '100%',\r\n height: '100%',\r\n backgroundColor: '#e0e0e0',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n fontSize: '10px',\r\n color: '#666',\r\n }}\r\n >\r\n {field.label || 'Photo'}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n\n case 'qrcode':\n const qrSize = getQrCodeSize(field.position.width, field.position.height);\n const qrDataUrl = field.qrFields?.length\n ? generateQrCodeFromFields(\n data,\n field.qrFields,\n qrSize\n )\n : '';\n\n return (\n <div\n key={field.id}\n id={field.id}\n style={combinedStyle}\n onClick={handleClick}\n className=\"idcard-field idcard-field-qrcode\"\n >\n {qrDataUrl ? (\n <img\n src={qrDataUrl}\n alt=\"QR Code\"\n data-qr-code-image=\"true\"\n style={{\n width: `${qrSize}px`,\n height: `${qrSize}px`,\n display: 'block',\n backgroundColor: 'transparent',\n objectFit: 'contain',\n objectPosition: 'center',\n maxWidth: '100%',\n maxHeight: '100%',\n flexShrink: 0,\n }}\n />\n ) : (\n <div\r\n style={{\r\n width: '100%',\r\n height: '100%',\r\n backgroundColor: '#f0f0f0',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n fontSize: '10px',\r\n color: '#666',\r\n }}\r\n >\r\n QR Code\r\n </div>\r\n )}\n </div>\n );\n\n case 'table':\n return (\n <div\n key={field.id}\n id={field.id}\n style={combinedStyle}\n onClick={handleClick}\n className=\"idcard-field idcard-field-table\"\n >\n <IDCardTable field={field} data={data} />\n </div>\n );\n\n default:\n return null;\n }\n };\n\r\n // Card container style\r\n const cardStyle: React.CSSProperties = {\r\n width: Math.round(template.cardSize.width),\r\n height: Math.round(template.cardSize.height),\r\n position: 'relative',\r\n overflow: 'hidden',\r\n backgroundColor: '#fff',\r\n ...style,\r\n };\r\n\r\n return (\r\n <div\r\n id={side === 'front' ? 'idcardfront' : 'idcardback'}\r\n className={`idcard-container idcard-${side} ${className}`}\r\n style={cardStyle}\r\n >\r\n {/* Background */}\r\n {backgroundImage && (\r\n <img\r\n src={backgroundImage}\r\n alt={`${side} background`}\r\n style={{\r\n position: 'absolute',\r\n top: 0,\r\n left: 0,\r\n width: `${Math.round(template.cardSize.width)}px`,\r\n height: `${Math.round(template.cardSize.height)}px`,\r\n zIndex: 0,\r\n }}\r\n />\r\n )}\r\n\r\n {/* Fields */}\r\n {fieldsToRender.map(renderField)}\r\n </div>\r\n );\r\n};\r\n\r\n/**\r\n * Get field value from data based on field configuration\r\n */\r\nfunction getFieldValue(field: FieldMapping, data: IDCardData): string | number | undefined {\n if (field.type === 'label') {\n return field.staticText;\n }\n\n const value = data[field.fieldKey];\n\n // Handle array values (like department)\n if (Array.isArray(value)) {\n const firstValue = value[0];\n if (firstValue && typeof firstValue === 'object') {\n return undefined;\n }\n\n return firstValue;\n }\n\n return value as string | number | undefined;\n}\n\r\n"],"names":["useMemo","positionToStyle","fieldStyleToCSS","_jsxs","_jsx","getQrCodeSize","generateQrCodeFromFields","IDCardTable"],"mappings":"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"}
@@ -205,7 +205,10 @@ const IDCardPreview = ({ template, data, side, scale = 1, showGrid = false, onFi
205
205
  case 'image':
206
206
  return value ? (jsxRuntime.jsx("img", { src: String(value), alt: field.label || 'Image', style: {
207
207
  width: '100%',
208
+ height: '100%',
208
209
  display: 'block',
210
+ objectFit: 'cover',
211
+ objectPosition: 'center',
209
212
  } })) : (jsxRuntime.jsxs("div", { style: {
210
213
  width: '100%',
211
214
  height: '100%',
@@ -1 +1 @@
1
- {"version":3,"file":"IDCardPreview.js","sources":["../../../src/components/IDCardPreview.tsx"],"sourcesContent":["import React, { useMemo } from 'react';\nimport type { IDCardPreviewProps, FieldMapping } from '../types';\nimport { fieldStyleToCSS, positionToStyle } from '../utils/styleUtils';\nimport { generateQrCodeFromFields, getQrCodeSize } from '../core/qrUtils';\nimport { IDCardTable } from './IDCardTable';\n\r\n/**\r\n * IDCardPreview - Interactive card preview component\r\n * \r\n * Renders an ID card with:\r\n * - Field selection and highlighting\r\n * - Resize handles for selected fields\r\n * - Grid overlay for alignment\r\n * - Dynamic field rendering based on type\r\n * \r\n * Used inside the designer for visual editing\r\n */\r\nexport const IDCardPreview: React.FC<IDCardPreviewProps> = ({\r\n template,\r\n data,\r\n side,\r\n scale = 1,\r\n showGrid = false,\r\n onFieldSelect,\r\n selectedFieldId,\r\n editable = true,\r\n onFieldUpdate,\r\n}: IDCardPreviewProps) => {\r\n // Get only fields that belong to the current side\r\n const fieldsToRender = useMemo(() => {\r\n return template.fields.filter((field: FieldMapping) => field.side === side);\r\n }, [template.fields, side]);\r\n\r\n // Get background for current side\r\n const backgroundImage = side === 'front' ? template.backgrounds.front : template.backgrounds.back;\r\n\r\n // Render resize handles for selected field\r\n const renderResizeHandles = (field: FieldMapping) => {\r\n if (field.id !== selectedFieldId || !editable) return null;\r\n\r\n const handles = ['n', 's', 'e', 'w', 'ne', 'nw', 'se', 'sw'];\r\n const handleStyle: React.CSSProperties = {\r\n position: 'absolute',\r\n width: '8px',\r\n height: '8px',\r\n backgroundColor: '#2196F3',\r\n border: '1px solid #fff',\r\n borderRadius: '2px',\r\n zIndex: 1000,\r\n };\r\n\r\n const positions: Record<string, React.CSSProperties> = {\r\n n: { top: '-4px', left: '50%', transform: 'translateX(-50%)', cursor: 'n-resize' },\r\n s: { bottom: '-4px', left: '50%', transform: 'translateX(-50%)', cursor: 's-resize' },\r\n e: { right: '-4px', top: '50%', transform: 'translateY(-50%)', cursor: 'e-resize' },\r\n w: { left: '-4px', top: '50%', transform: 'translateY(-50%)', cursor: 'w-resize' },\r\n ne: { top: '-4px', right: '-4px', cursor: 'ne-resize' },\r\n nw: { top: '-4px', left: '-4px', cursor: 'nw-resize' },\r\n se: { bottom: '-4px', right: '-4px', cursor: 'se-resize' },\r\n sw: { bottom: '-4px', left: '-4px', cursor: 'sw-resize' },\r\n };\r\n\r\n return handles.map((handle) => (\r\n <div\r\n key={handle}\r\n className={`resize-handle resize-handle-${handle}`}\r\n style={{ ...handleStyle, ...positions[handle] }}\r\n data-handle={handle}\r\n />\r\n ));\r\n };\r\n\r\n // Render a single field\r\n const renderField = (field: FieldMapping) => {\r\n const posStyle = positionToStyle(field.position);\r\n let fieldStyle = fieldStyleToCSS(field.style);\r\n const isSelected = field.id === selectedFieldId;\r\n\r\n // Determine flex direction and alignment for text fields\r\n let flexDirection: 'column' | 'row' = 'column';\r\n if (field.type === 'text' && field.style?.labelPosition === 'left') flexDirection = 'row';\r\n\r\n // Map verticalAlign and textAlign to flex properties\r\n let justifyContent: 'flex-start' | 'center' | 'flex-end' = 'flex-start';\r\n let alignItems: 'flex-start' | 'center' | 'flex-end' = 'flex-start';\r\n if (field.type === 'text') {\r\n const textAlign = field.style?.textTextAlign || field.style?.textAlign || 'left';\r\n const verticalAlign = field.style?.verticalAlign || 'top';\r\n \r\n if (flexDirection === 'column') {\r\n // For column: verticalAlign controls justifyContent (vertical), textAlign controls alignItems (horizontal)\r\n if (verticalAlign === 'middle') justifyContent = 'center';\r\n else if (verticalAlign === 'bottom') justifyContent = 'flex-end';\r\n else justifyContent = 'flex-start';\r\n \r\n if (textAlign === 'center') alignItems = 'center';\r\n else if (textAlign === 'right') alignItems = 'flex-end';\r\n else alignItems = 'flex-start';\r\n } else {\r\n // For row: verticalAlign controls alignItems (vertical)\r\n if (verticalAlign === 'middle') alignItems = 'center';\r\n else if (verticalAlign === 'bottom') alignItems = 'flex-end';\r\n else alignItems = 'flex-start';\r\n // justifyContent can be left as default for row\r\n }\r\n }\r\n\r\n // Remove fontSize for label fields so text field font size does not affect them\r\n if (field.type === 'label' && fieldStyle.fontSize) {\r\n const { fontSize, ...rest } = fieldStyle;\r\n fieldStyle = rest;\r\n }\r\n\r\n // Remove textTransform from container for text and label fields - applied directly to spans\r\n if ((field.type === 'text' || field.type === 'label') && fieldStyle.textTransform) {\r\n const { textTransform, ...rest } = fieldStyle;\r\n fieldStyle = rest;\r\n }\r\n\r\n const combinedStyle: React.CSSProperties = {\n ...posStyle,\n ...fieldStyle,\n backgroundColor: field.type === 'qrcode' ? 'transparent' : fieldStyle.backgroundColor,\n zIndex: field.zIndex || 1,\n boxSizing: 'border-box',\n overflow: 'hidden',\n cursor: editable ? 'move' : 'default',\n outline: isSelected ? '2px solid #2196F3' : 'none',\n outlineOffset: '1px',\n display: field.type === 'text' || field.type === 'qrcode' ? 'flex' : undefined,\n flexDirection: field.type === 'text' ? flexDirection : undefined,\n justifyContent: field.type === 'text' ? justifyContent : field.type === 'qrcode' ? 'center' : undefined,\n alignItems: field.type === 'text' ? alignItems : field.type === 'qrcode' ? 'center' : undefined,\n };\r\n\r\n const handleClick = (e: React.MouseEvent) => {\r\n e.stopPropagation();\r\n onFieldSelect?.(field);\r\n };\r\n\r\n const value = data[field.fieldKey];\r\n\r\n const content = (() => {\r\n\r\n switch (field.type) {\r\n case 'text': {\r\n // Label style properties\r\n // Always use px for label font size, default 12px\r\n let labelFontSize = field.style?.labelFontSize;\r\n if (!labelFontSize || labelFontSize === '0.75em') {\r\n labelFontSize = '12px';\r\n } else if (!labelFontSize.endsWith('px')) {\r\n const num = parseFloat(labelFontSize);\r\n if (!isNaN(num)) labelFontSize = num + 'px';\r\n else labelFontSize = '12px';\r\n }\r\n const labelFontWeight = field.style?.labelFontWeight || 'normal';\r\n const labelColor = field.style?.labelColor || '#666666';\r\n const labelTextTransform = field.style?.labelTextTransform || 'none';\r\n const labelTextAlign = field.style?.labelTextAlign || 'left';\r\n \r\n // Text/value style properties (separate from label)\r\n const textFontSize = field.style?.textFontSize || field.style?.fontSize || '1em';\r\n const textFontWeight = field.style?.textFontWeight || field.style?.fontWeight || 'normal';\r\n const textColor = field.style?.textColor || field.style?.color || '#000000';\r\n const textTextTransform = field.style?.textTransform || 'none';\r\n const textTextAlign = field.style?.textTextAlign || field.style?.textAlign || 'left';\r\n \r\n // For row layout (label on left), use individual span alignment\r\n if (field.style?.labelPosition === 'left') {\r\n let labelAlignSelf: React.CSSProperties['alignSelf'] = 'flex-start';\r\n if (field.style?.labelVerticalAlign === 'middle') labelAlignSelf = 'center';\r\n else if (field.style?.labelVerticalAlign === 'bottom') labelAlignSelf = 'flex-end';\r\n \r\n let textAlignSelf: React.CSSProperties['alignSelf'] = 'flex-start';\r\n if (field.style?.textVerticalAlign === 'middle') textAlignSelf = 'center';\r\n else if (field.style?.textVerticalAlign === 'bottom') textAlignSelf = 'flex-end';\r\n \r\n const labelStyle: React.CSSProperties = { \r\n fontSize: labelFontSize, \n fontWeight: labelFontWeight, \n color: labelColor, \n marginRight: 8, \n alignSelf: labelAlignSelf, \n whiteSpace: 'nowrap', \n textTransform: labelTextTransform \r\n };\r\n \r\n const textStyle: React.CSSProperties = { \r\n textTransform: textTextTransform, \r\n fontSize: textFontSize, \r\n fontWeight: textFontWeight, \r\n color: textColor, \r\n alignSelf: textAlignSelf\r\n };\r\n \r\n return (\r\n <>\r\n {field.label && (\r\n <span style={labelStyle}>\r\n {field.label}\r\n </span>\r\n )}\r\n <span style={{ width: '100%', textAlign: textTextAlign }}>\r\n <span style={textStyle}>{String(value || field.placeholder || field.fieldKey)}</span>\r\n </span>\r\n </>\r\n );\r\n } else {\r\n // For column layout (label on top), let container alignment handle positioning\r\n const labelStyle: React.CSSProperties = { \r\n fontSize: labelFontSize, \n fontWeight: labelFontWeight, \n color: labelColor, \n textTransform: labelTextTransform,\n width: '100%',\n textAlign: labelTextAlign\n };\r\n \r\n const textStyle: React.CSSProperties = { \r\n textTransform: textTextTransform, \r\n fontSize: textFontSize, \r\n fontWeight: textFontWeight, \r\n color: textColor,\r\n width: '100%',\r\n textAlign: textTextAlign\r\n };\r\n \r\n return (\r\n <>\r\n {field.label && (\r\n <span style={labelStyle}>\r\n {field.label}\r\n </span>\r\n )}\r\n <span style={textStyle}>{String(value || field.placeholder || field.fieldKey)}</span>\r\n </>\r\n );\r\n }\r\n }\r\n\r\n case 'label': {\r\n const labelTextTransform = field.style?.labelTextTransform || 'none';\r\n return <span style={{ textTransform: labelTextTransform }}>{field.staticText || field.label || 'Label'}</span>;\r\n }\r\n\r\n case 'image':\r\n return value ? (\r\n <img\r\n src={String(value)}\r\n alt={field.label || 'Image'}\r\n style={{\r\n width: '100%',\r\n display: 'block',\r\n }}\r\n />\r\n ) : (\r\n <div\r\n style={{\r\n width: '100%',\r\n height: '100%',\r\n backgroundColor: '#e0e0e0',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n fontSize: '10px',\r\n color: '#666',\r\n flexDirection: 'column',\r\n }}\r\n >\r\n <span>📷</span>\r\n <span>{field.label || 'Photo'}</span>\r\n </div>\r\n );\r\n\n case 'qrcode':\n const qrSize = getQrCodeSize(field.position.width, field.position.height);\n const qrDataUrl = field.qrFields?.length\n ? generateQrCodeFromFields(data, field.qrFields, qrSize)\n : '';\n\r\n return qrDataUrl ? (\r\n <img\n src={qrDataUrl}\n alt=\"QR Code\"\n data-qr-code-image=\"true\"\n style={{\n width: `${qrSize}px`,\n height: `${qrSize}px`,\n display: 'block',\n pointerEvents: 'none',\n backgroundColor: 'transparent',\n objectFit: 'contain',\n objectPosition: 'center',\n maxWidth: '100%',\n maxHeight: '100%',\n flexShrink: 0,\n }}\n />\n ) : (\n <div\r\n style={{\r\n width: '100%',\r\n height: '100%',\r\n backgroundColor: '#f0f0f0',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n fontSize: '10px',\r\n color: '#666',\r\n border: '1px dashed #ccc',\r\n }}\r\n >\r\n QR Code\r\n </div>\r\n );\n\n case 'table':\n return <IDCardTable field={field} data={data} />;\n\n default:\n return null;\n }\n })();\r\n\r\n return (\r\n <div\r\n key={field.id}\r\n id={`preview-${field.id}`}\r\n style={combinedStyle}\r\n onClick={handleClick}\r\n className={`preview-field preview-field-${field.type} ${isSelected ? 'selected' : ''}`}\r\n >\r\n {content}\r\n {renderResizeHandles(field)}\r\n </div>\r\n );\r\n };\r\n\r\n // Card container style\r\n const cardStyle: React.CSSProperties = {\r\n width: Math.round(template.cardSize.width),\r\n height: Math.round(template.cardSize.height),\r\n position: 'relative',\r\n overflow: 'hidden',\r\n backgroundColor: backgroundImage ? 'transparent' : '#f5f5f5',\r\n border: '1px solid #ddd',\r\n };\r\n\r\n // Grid overlay style\r\n const gridStyle: React.CSSProperties = {\r\n position: 'absolute',\r\n top: 0,\r\n left: 0,\r\n width: '100%',\r\n height: '100%',\r\n backgroundImage: showGrid\r\n ? 'linear-gradient(to right, rgba(0,0,0,0.05) 1px, transparent 1px), linear-gradient(to bottom, rgba(0,0,0,0.05) 1px, transparent 1px)'\r\n : 'none',\r\n backgroundSize: '10px 10px',\r\n pointerEvents: 'none',\r\n zIndex: 999,\r\n };\r\n\r\n const handleContainerClick = () => {\r\n onFieldSelect?.(null);\r\n };\r\n\r\n return (\r\n <div\r\n className=\"idcard-preview-container\"\r\n style={cardStyle}\r\n onClick={handleContainerClick}\r\n >\r\n {/* Background */}\r\n {backgroundImage && (\r\n <img\r\n src={backgroundImage}\r\n alt={`${side} background`}\r\n style={{\r\n position: 'absolute',\r\n top: 0,\r\n left: 0,\r\n width: `${Math.round(template.cardSize.width)}px`,\r\n height: `${Math.round(template.cardSize.height)}px`,\r\n zIndex: 0,\r\n pointerEvents: 'none',\r\n }}\r\n />\r\n )}\r\n\r\n {/* Fields */}\r\n {fieldsToRender.map(renderField)}\r\n\r\n {/* Grid overlay */}\r\n {showGrid && <div style={gridStyle} />}\r\n\r\n {/* Empty state */}\r\n {!backgroundImage && fieldsToRender.length === 0 && (\r\n <div\r\n style={{\r\n position: 'absolute',\r\n top: '50%',\r\n left: '50%',\r\n transform: 'translate(-50%, -50%)',\r\n textAlign: 'center',\r\n color: '#999',\r\n fontSize: '14px',\r\n }}\r\n >\r\n <p>Upload a background image</p>\r\n <p>and add fields to get started</p>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\n"],"names":["useMemo","_jsx","positionToStyle","fieldStyleToCSS","_jsxs","_Fragment","getQrCodeSize","generateQrCodeFromFields","IDCardTable"],"mappings":"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"}
1
+ {"version":3,"file":"IDCardPreview.js","sources":["../../../src/components/IDCardPreview.tsx"],"sourcesContent":["import React, { useMemo } from 'react';\nimport type { IDCardPreviewProps, FieldMapping } from '../types';\nimport { fieldStyleToCSS, positionToStyle } from '../utils/styleUtils';\nimport { generateQrCodeFromFields, getQrCodeSize } from '../core/qrUtils';\nimport { IDCardTable } from './IDCardTable';\n\r\n/**\r\n * IDCardPreview - Interactive card preview component\r\n * \r\n * Renders an ID card with:\r\n * - Field selection and highlighting\r\n * - Resize handles for selected fields\r\n * - Grid overlay for alignment\r\n * - Dynamic field rendering based on type\r\n * \r\n * Used inside the designer for visual editing\r\n */\r\nexport const IDCardPreview: React.FC<IDCardPreviewProps> = ({\r\n template,\r\n data,\r\n side,\r\n scale = 1,\r\n showGrid = false,\r\n onFieldSelect,\r\n selectedFieldId,\r\n editable = true,\r\n onFieldUpdate,\r\n}: IDCardPreviewProps) => {\r\n // Get only fields that belong to the current side\r\n const fieldsToRender = useMemo(() => {\r\n return template.fields.filter((field: FieldMapping) => field.side === side);\r\n }, [template.fields, side]);\r\n\r\n // Get background for current side\r\n const backgroundImage = side === 'front' ? template.backgrounds.front : template.backgrounds.back;\r\n\r\n // Render resize handles for selected field\r\n const renderResizeHandles = (field: FieldMapping) => {\r\n if (field.id !== selectedFieldId || !editable) return null;\r\n\r\n const handles = ['n', 's', 'e', 'w', 'ne', 'nw', 'se', 'sw'];\r\n const handleStyle: React.CSSProperties = {\r\n position: 'absolute',\r\n width: '8px',\r\n height: '8px',\r\n backgroundColor: '#2196F3',\r\n border: '1px solid #fff',\r\n borderRadius: '2px',\r\n zIndex: 1000,\r\n };\r\n\r\n const positions: Record<string, React.CSSProperties> = {\r\n n: { top: '-4px', left: '50%', transform: 'translateX(-50%)', cursor: 'n-resize' },\r\n s: { bottom: '-4px', left: '50%', transform: 'translateX(-50%)', cursor: 's-resize' },\r\n e: { right: '-4px', top: '50%', transform: 'translateY(-50%)', cursor: 'e-resize' },\r\n w: { left: '-4px', top: '50%', transform: 'translateY(-50%)', cursor: 'w-resize' },\r\n ne: { top: '-4px', right: '-4px', cursor: 'ne-resize' },\r\n nw: { top: '-4px', left: '-4px', cursor: 'nw-resize' },\r\n se: { bottom: '-4px', right: '-4px', cursor: 'se-resize' },\r\n sw: { bottom: '-4px', left: '-4px', cursor: 'sw-resize' },\r\n };\r\n\r\n return handles.map((handle) => (\r\n <div\r\n key={handle}\r\n className={`resize-handle resize-handle-${handle}`}\r\n style={{ ...handleStyle, ...positions[handle] }}\r\n data-handle={handle}\r\n />\r\n ));\r\n };\r\n\r\n // Render a single field\r\n const renderField = (field: FieldMapping) => {\r\n const posStyle = positionToStyle(field.position);\r\n let fieldStyle = fieldStyleToCSS(field.style);\r\n const isSelected = field.id === selectedFieldId;\r\n\r\n // Determine flex direction and alignment for text fields\r\n let flexDirection: 'column' | 'row' = 'column';\r\n if (field.type === 'text' && field.style?.labelPosition === 'left') flexDirection = 'row';\r\n\r\n // Map verticalAlign and textAlign to flex properties\r\n let justifyContent: 'flex-start' | 'center' | 'flex-end' = 'flex-start';\r\n let alignItems: 'flex-start' | 'center' | 'flex-end' = 'flex-start';\r\n if (field.type === 'text') {\r\n const textAlign = field.style?.textTextAlign || field.style?.textAlign || 'left';\r\n const verticalAlign = field.style?.verticalAlign || 'top';\r\n \r\n if (flexDirection === 'column') {\r\n // For column: verticalAlign controls justifyContent (vertical), textAlign controls alignItems (horizontal)\r\n if (verticalAlign === 'middle') justifyContent = 'center';\r\n else if (verticalAlign === 'bottom') justifyContent = 'flex-end';\r\n else justifyContent = 'flex-start';\r\n \r\n if (textAlign === 'center') alignItems = 'center';\r\n else if (textAlign === 'right') alignItems = 'flex-end';\r\n else alignItems = 'flex-start';\r\n } else {\r\n // For row: verticalAlign controls alignItems (vertical)\r\n if (verticalAlign === 'middle') alignItems = 'center';\r\n else if (verticalAlign === 'bottom') alignItems = 'flex-end';\r\n else alignItems = 'flex-start';\r\n // justifyContent can be left as default for row\r\n }\r\n }\r\n\r\n // Remove fontSize for label fields so text field font size does not affect them\r\n if (field.type === 'label' && fieldStyle.fontSize) {\r\n const { fontSize, ...rest } = fieldStyle;\r\n fieldStyle = rest;\r\n }\r\n\r\n // Remove textTransform from container for text and label fields - applied directly to spans\r\n if ((field.type === 'text' || field.type === 'label') && fieldStyle.textTransform) {\r\n const { textTransform, ...rest } = fieldStyle;\r\n fieldStyle = rest;\r\n }\r\n\r\n const combinedStyle: React.CSSProperties = {\n ...posStyle,\n ...fieldStyle,\n backgroundColor: field.type === 'qrcode' ? 'transparent' : fieldStyle.backgroundColor,\n zIndex: field.zIndex || 1,\n boxSizing: 'border-box',\n overflow: 'hidden',\n cursor: editable ? 'move' : 'default',\n outline: isSelected ? '2px solid #2196F3' : 'none',\n outlineOffset: '1px',\n display: field.type === 'text' || field.type === 'qrcode' ? 'flex' : undefined,\n flexDirection: field.type === 'text' ? flexDirection : undefined,\n justifyContent: field.type === 'text' ? justifyContent : field.type === 'qrcode' ? 'center' : undefined,\n alignItems: field.type === 'text' ? alignItems : field.type === 'qrcode' ? 'center' : undefined,\n };\r\n\r\n const handleClick = (e: React.MouseEvent) => {\r\n e.stopPropagation();\r\n onFieldSelect?.(field);\r\n };\r\n\r\n const value = data[field.fieldKey];\r\n\r\n const content = (() => {\r\n\r\n switch (field.type) {\r\n case 'text': {\r\n // Label style properties\r\n // Always use px for label font size, default 12px\r\n let labelFontSize = field.style?.labelFontSize;\r\n if (!labelFontSize || labelFontSize === '0.75em') {\r\n labelFontSize = '12px';\r\n } else if (!labelFontSize.endsWith('px')) {\r\n const num = parseFloat(labelFontSize);\r\n if (!isNaN(num)) labelFontSize = num + 'px';\r\n else labelFontSize = '12px';\r\n }\r\n const labelFontWeight = field.style?.labelFontWeight || 'normal';\r\n const labelColor = field.style?.labelColor || '#666666';\r\n const labelTextTransform = field.style?.labelTextTransform || 'none';\r\n const labelTextAlign = field.style?.labelTextAlign || 'left';\r\n \r\n // Text/value style properties (separate from label)\r\n const textFontSize = field.style?.textFontSize || field.style?.fontSize || '1em';\r\n const textFontWeight = field.style?.textFontWeight || field.style?.fontWeight || 'normal';\r\n const textColor = field.style?.textColor || field.style?.color || '#000000';\r\n const textTextTransform = field.style?.textTransform || 'none';\r\n const textTextAlign = field.style?.textTextAlign || field.style?.textAlign || 'left';\r\n \r\n // For row layout (label on left), use individual span alignment\r\n if (field.style?.labelPosition === 'left') {\r\n let labelAlignSelf: React.CSSProperties['alignSelf'] = 'flex-start';\r\n if (field.style?.labelVerticalAlign === 'middle') labelAlignSelf = 'center';\r\n else if (field.style?.labelVerticalAlign === 'bottom') labelAlignSelf = 'flex-end';\r\n \r\n let textAlignSelf: React.CSSProperties['alignSelf'] = 'flex-start';\r\n if (field.style?.textVerticalAlign === 'middle') textAlignSelf = 'center';\r\n else if (field.style?.textVerticalAlign === 'bottom') textAlignSelf = 'flex-end';\r\n \r\n const labelStyle: React.CSSProperties = { \r\n fontSize: labelFontSize, \n fontWeight: labelFontWeight, \n color: labelColor, \n marginRight: 8, \n alignSelf: labelAlignSelf, \n whiteSpace: 'nowrap', \n textTransform: labelTextTransform \r\n };\r\n \r\n const textStyle: React.CSSProperties = { \r\n textTransform: textTextTransform, \r\n fontSize: textFontSize, \r\n fontWeight: textFontWeight, \r\n color: textColor, \r\n alignSelf: textAlignSelf\r\n };\r\n \r\n return (\r\n <>\r\n {field.label && (\r\n <span style={labelStyle}>\r\n {field.label}\r\n </span>\r\n )}\r\n <span style={{ width: '100%', textAlign: textTextAlign }}>\r\n <span style={textStyle}>{String(value || field.placeholder || field.fieldKey)}</span>\r\n </span>\r\n </>\r\n );\r\n } else {\r\n // For column layout (label on top), let container alignment handle positioning\r\n const labelStyle: React.CSSProperties = { \r\n fontSize: labelFontSize, \n fontWeight: labelFontWeight, \n color: labelColor, \n textTransform: labelTextTransform,\n width: '100%',\n textAlign: labelTextAlign\n };\r\n \r\n const textStyle: React.CSSProperties = { \r\n textTransform: textTextTransform, \r\n fontSize: textFontSize, \r\n fontWeight: textFontWeight, \r\n color: textColor,\r\n width: '100%',\r\n textAlign: textTextAlign\r\n };\r\n \r\n return (\r\n <>\r\n {field.label && (\r\n <span style={labelStyle}>\r\n {field.label}\r\n </span>\r\n )}\r\n <span style={textStyle}>{String(value || field.placeholder || field.fieldKey)}</span>\r\n </>\r\n );\r\n }\r\n }\r\n\r\n case 'label': {\r\n const labelTextTransform = field.style?.labelTextTransform || 'none';\r\n return <span style={{ textTransform: labelTextTransform }}>{field.staticText || field.label || 'Label'}</span>;\r\n }\r\n\r\n case 'image':\r\n return value ? (\r\n <img\r\n src={String(value)}\r\n alt={field.label || 'Image'}\r\n style={{\n width: '100%',\n height: '100%',\n display: 'block',\n objectFit: 'cover',\n objectPosition: 'center',\n }}\n />\n ) : (\r\n <div\r\n style={{\r\n width: '100%',\r\n height: '100%',\r\n backgroundColor: '#e0e0e0',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n fontSize: '10px',\r\n color: '#666',\r\n flexDirection: 'column',\r\n }}\r\n >\r\n <span>📷</span>\r\n <span>{field.label || 'Photo'}</span>\r\n </div>\r\n );\r\n\n case 'qrcode':\n const qrSize = getQrCodeSize(field.position.width, field.position.height);\n const qrDataUrl = field.qrFields?.length\n ? generateQrCodeFromFields(data, field.qrFields, qrSize)\n : '';\n\r\n return qrDataUrl ? (\r\n <img\n src={qrDataUrl}\n alt=\"QR Code\"\n data-qr-code-image=\"true\"\n style={{\n width: `${qrSize}px`,\n height: `${qrSize}px`,\n display: 'block',\n pointerEvents: 'none',\n backgroundColor: 'transparent',\n objectFit: 'contain',\n objectPosition: 'center',\n maxWidth: '100%',\n maxHeight: '100%',\n flexShrink: 0,\n }}\n />\n ) : (\n <div\r\n style={{\r\n width: '100%',\r\n height: '100%',\r\n backgroundColor: '#f0f0f0',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n fontSize: '10px',\r\n color: '#666',\r\n border: '1px dashed #ccc',\r\n }}\r\n >\r\n QR Code\r\n </div>\r\n );\n\n case 'table':\n return <IDCardTable field={field} data={data} />;\n\n default:\n return null;\n }\n })();\r\n\r\n return (\r\n <div\r\n key={field.id}\r\n id={`preview-${field.id}`}\r\n style={combinedStyle}\r\n onClick={handleClick}\r\n className={`preview-field preview-field-${field.type} ${isSelected ? 'selected' : ''}`}\r\n >\r\n {content}\r\n {renderResizeHandles(field)}\r\n </div>\r\n );\r\n };\r\n\r\n // Card container style\r\n const cardStyle: React.CSSProperties = {\r\n width: Math.round(template.cardSize.width),\r\n height: Math.round(template.cardSize.height),\r\n position: 'relative',\r\n overflow: 'hidden',\r\n backgroundColor: backgroundImage ? 'transparent' : '#f5f5f5',\r\n border: '1px solid #ddd',\r\n };\r\n\r\n // Grid overlay style\r\n const gridStyle: React.CSSProperties = {\r\n position: 'absolute',\r\n top: 0,\r\n left: 0,\r\n width: '100%',\r\n height: '100%',\r\n backgroundImage: showGrid\r\n ? 'linear-gradient(to right, rgba(0,0,0,0.05) 1px, transparent 1px), linear-gradient(to bottom, rgba(0,0,0,0.05) 1px, transparent 1px)'\r\n : 'none',\r\n backgroundSize: '10px 10px',\r\n pointerEvents: 'none',\r\n zIndex: 999,\r\n };\r\n\r\n const handleContainerClick = () => {\r\n onFieldSelect?.(null);\r\n };\r\n\r\n return (\r\n <div\r\n className=\"idcard-preview-container\"\r\n style={cardStyle}\r\n onClick={handleContainerClick}\r\n >\r\n {/* Background */}\r\n {backgroundImage && (\r\n <img\r\n src={backgroundImage}\r\n alt={`${side} background`}\r\n style={{\r\n position: 'absolute',\r\n top: 0,\r\n left: 0,\r\n width: `${Math.round(template.cardSize.width)}px`,\r\n height: `${Math.round(template.cardSize.height)}px`,\r\n zIndex: 0,\r\n pointerEvents: 'none',\r\n }}\r\n />\r\n )}\r\n\r\n {/* Fields */}\r\n {fieldsToRender.map(renderField)}\r\n\r\n {/* Grid overlay */}\r\n {showGrid && <div style={gridStyle} />}\r\n\r\n {/* Empty state */}\r\n {!backgroundImage && fieldsToRender.length === 0 && (\r\n <div\r\n style={{\r\n position: 'absolute',\r\n top: '50%',\r\n left: '50%',\r\n transform: 'translate(-50%, -50%)',\r\n textAlign: 'center',\r\n color: '#999',\r\n fontSize: '14px',\r\n }}\r\n >\r\n <p>Upload a background image</p>\r\n <p>and add fields to get started</p>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\n"],"names":["useMemo","_jsx","positionToStyle","fieldStyleToCSS","_jsxs","_Fragment","getQrCodeSize","generateQrCodeFromFields","IDCardTable"],"mappings":"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"}
@@ -27,7 +27,7 @@ var hasRequiredQrious;
27
27
  function requireQrious () {
28
28
  if (hasRequiredQrious) return qrious$1.__module.exports;
29
29
  hasRequiredQrious = 1;
30
- (function (module, exports$1) {
30
+ (function (module, exports) {
31
31
  (function (global, factory) {
32
32
  module.exports = factory() ;
33
33
  }(qrious, (function () {
@@ -14,6 +14,16 @@ const defaultFieldTypes = [
14
14
  { type: 'qrcode', label: 'QR Code', icon: '📱' },
15
15
  { type: 'table', label: 'Table', icon: '▦' },
16
16
  ];
17
+ const getPhotoRadiusSliderValue = (borderRadius) => {
18
+ if (typeof borderRadius !== 'string') {
19
+ return 0;
20
+ }
21
+ const parsed = Number.parseFloat(borderRadius);
22
+ if (!Number.isFinite(parsed)) {
23
+ return 0;
24
+ }
25
+ return Math.max(0, Math.min(200, Math.round(parsed)));
26
+ };
17
27
  /**
18
28
  * IDCardDesigner - Visual drag-and-drop template builder
19
29
  *
@@ -381,11 +391,15 @@ const IDCardDesigner = ({ initialTemplate, onSave, onCancel, className = '', sty
381
391
  }, [selectedFieldId, removeField]);
382
392
  // Keyboard shortcuts
383
393
  useEffect(() => {
394
+ const handleLineHeightInputFocus = () => {
395
+ };
396
+ const handleLineHeightInputBlur = () => {
397
+ };
384
398
  // Listen for focus/blur on line height input
385
399
  const lhInput = document.getElementById('line-height-input');
386
400
  if (lhInput) {
387
- lhInput.addEventListener('focus', () => { });
388
- lhInput.addEventListener('blur', () => { });
401
+ lhInput.addEventListener('focus', handleLineHeightInputFocus);
402
+ lhInput.addEventListener('blur', handleLineHeightInputBlur);
389
403
  }
390
404
  const handleKeyDown = (e) => {
391
405
  if (selectedFieldId) {
@@ -435,7 +449,13 @@ const IDCardDesigner = ({ initialTemplate, onSave, onCancel, className = '', sty
435
449
  }
436
450
  };
437
451
  document.addEventListener('keydown', handleKeyDown);
438
- return () => document.removeEventListener('keydown', handleKeyDown);
452
+ return () => {
453
+ document.removeEventListener('keydown', handleKeyDown);
454
+ if (lhInput) {
455
+ lhInput.removeEventListener('focus', handleLineHeightInputFocus);
456
+ lhInput.removeEventListener('blur', handleLineHeightInputBlur);
457
+ }
458
+ };
439
459
  }, [selectedFieldId, handleDeleteField, template.fields, template.cardSize, updateField]);
440
460
  return (jsxs("div", { className: `idcard-designer ${className}`, style: style, children: [jsxs("div", { className: "designer-header", children: [jsx("input", { type: "text", value: templateName, onChange: (e) => setTemplateName(e.target.value), className: "template-name-input", placeholder: "Template Name" }), jsxs("div", { className: "header-actions", children: [onCancel && (jsx("button", { type: "button", onClick: onCancel, className: "btn btn-secondary", children: "Cancel" })), jsx("button", { type: "button", onClick: handleSave, className: "btn btn-primary", disabled: !isValid, children: "Save Template" })] })] }), jsxs("div", { className: "designer-body", children: [jsxs("div", { className: "designer-sidebar left-sidebar", children: [jsx("h3", { children: "Add Fields" }), jsx("div", { className: "field-types", children: defaultFieldTypes.map((fieldType) => (jsxs("button", { type: "button", onClick: () => handleAddField(fieldType.type), className: "field-type-btn", children: [jsx("span", { className: "field-icon", children: fieldType.icon }), jsx("span", { className: "field-label", children: fieldType.label })] }, fieldType.type))) }), jsx("h3", { children: "Card Settings" }), jsxs("div", { className: "card-settings", children: [jsxs("div", { className: "setting-group", children: [jsx("label", { children: "Orientation" }), jsxs("div", { className: "btn-group", children: [jsx("button", { type: "button", className: `btn ${template.orientation === 'landscape' ? 'active' : ''}`, onClick: () => handleOrientationChange('landscape'), children: "Landscape" }), jsx("button", { type: "button", className: `btn ${template.orientation === 'portrait' ? 'active' : ''}`, onClick: () => handleOrientationChange('portrait'), children: "Portrait" })] })] }), jsxs("div", { className: "setting-group", children: [jsx("label", { children: "Card Sides" }), jsxs("div", { className: "btn-group", children: [jsx("button", { type: "button", className: `btn ${template.sides === 'single' ? 'active' : ''}`, onClick: () => handleSidesChange('single'), children: "Single" }), jsx("button", { type: "button", className: `btn ${template.sides === 'double' ? 'active' : ''}`, onClick: () => handleSidesChange('double'), children: "Double" })] })] }), jsxs("div", { className: "setting-group", children: [jsx("label", { children: "Card Size (px)" }), jsxs("div", { className: "size-inputs", children: [jsx("input", { type: "number", value: template.cardSize.width, onChange: (e) => setCardSize({ ...template.cardSize, width: Number(e.target.value) }), placeholder: "Width" }), jsx("span", { children: "\u00D7" }), jsx("input", { type: "number", value: template.cardSize.height, onChange: (e) => setCardSize({ ...template.cardSize, height: Number(e.target.value) }), placeholder: "Height" })] })] })] }), jsx("h3", { children: "Background" }), jsxs("div", { className: "background-upload", children: [jsx("input", { type: "file", accept: "image/*", onChange: handleBackgroundUpload, id: "bg-upload", className: "file-input" }), jsxs("label", { htmlFor: "bg-upload", className: "btn btn-outline", children: ["Upload ", activeSide, " Background"] }), template.backgrounds[activeSide] && (jsx("button", { type: "button", className: "btn btn-danger btn-sm", onClick: () => setBackground(activeSide, ''), children: "Remove" }))] })] }), jsxs("div", { className: "designer-preview", children: [jsxs("div", { className: "side-tabs", children: [jsx("button", { type: "button", className: `tab ${activeSide === 'front' ? 'active' : ''}`, onClick: () => setActiveSide('front'), children: "Front" }), template.sides === 'double' && (jsx("button", { type: "button", className: `tab ${activeSide === 'back' ? 'active' : ''}`, onClick: () => setActiveSide('back'), children: "Back" })), jsxs("label", { className: "grid-toggle", children: [jsx("input", { type: "checkbox", checked: showGrid, onChange: (e) => setShowGrid(e.target.checked) }), "Show Grid"] })] }), jsx("div", { ref: previewContainerRef, className: "preview-wrapper", onMouseDown: handleMouseDown, children: jsx(IDCardPreview, { template: template, data: sampleData, side: activeSide, showGrid: showGrid, onFieldSelect: handleFieldSelect, selectedFieldId: selectedFieldId, editable: true }) }), jsxs("div", { className: "fields-list", children: [jsxs("h4", { children: ["Fields on ", activeSide, " side:"] }), template.fields
441
461
  .filter((f) => f.side === activeSide)
@@ -487,7 +507,7 @@ const IDCardDesigner = ({ initialTemplate, onSave, onCancel, className = '', sty
487
507
  ? [...currentFields, field.fieldKey]
488
508
  : currentFields.filter(f => f !== field.fieldKey);
489
509
  handleFieldPropertyUpdate('qrFields', newFields);
490
- }, style: { marginRight: '6px' } }), field.label || field.fieldKey] }, field.fieldKey))) })] })), selectedField.type !== 'text' && selectedField.type !== 'table' && jsxs(Fragment, { children: [jsx("h4", { children: "Style" }), jsxs("div", { className: "property-group", children: [jsx("label", { children: "Font Size" }), jsx("input", { type: "text", value: selectedField.style?.fontSize || '12px', onChange: (e) => handleFieldPropertyUpdate('style.fontSize', e.target.value) })] }), jsxs("div", { className: "property-group", children: [jsx("label", { children: "Font Weight" }), jsxs("select", { value: selectedField.style?.fontWeight || 'normal', onChange: (e) => handleFieldPropertyUpdate('style.fontWeight', e.target.value), children: [jsx("option", { value: "normal", children: "Normal" }), jsx("option", { value: "bold", children: "Bold" }), jsx("option", { value: "100", children: "100" }), jsx("option", { value: "200", children: "200" }), jsx("option", { value: "300", children: "300" }), jsx("option", { value: "400", children: "400" }), jsx("option", { value: "500", children: "500" }), jsx("option", { value: "600", children: "600" }), jsx("option", { value: "700", children: "700" }), jsx("option", { value: "800", children: "800" }), jsx("option", { value: "900", children: "900" })] })] }), jsxs("div", { className: "property-group", children: [jsx("label", { children: "Text Color" }), jsx("input", { type: "color", value: selectedField.style?.color || '#000000', onChange: (e) => handleFieldPropertyUpdate('style.color', e.target.value) })] }), jsxs("div", { className: "property-group", children: [jsx("label", { children: "Text Align" }), jsxs("select", { value: selectedField.style?.textAlign || 'left', onChange: (e) => handleFieldPropertyUpdate('style.textAlign', e.target.value), children: [jsx("option", { value: "left", children: "Left" }), jsx("option", { value: "center", children: "Center" }), jsx("option", { value: "right", children: "Right" })] })] }), selectedField.type === 'label' && (jsxs("div", { className: "property-group", children: [jsx("label", { children: "Text Transform" }), jsxs("select", { value: selectedField.style?.labelTextTransform || 'none', onChange: (e) => handleFieldPropertyUpdate('style.labelTextTransform', e.target.value), children: [jsx("option", { value: "none", children: "None" }), jsx("option", { value: "uppercase", children: "UPPERCASE" }), jsx("option", { value: "lowercase", children: "lowercase" }), jsx("option", { value: "capitalize", children: "Capitalize" })] })] }))] }), selectedField.type === 'qrcode' ? (jsxs("div", { className: "property-group", children: [jsx("label", { children: "Background Color" }), jsx("div", { style: {
510
+ }, style: { marginRight: '6px' } }), field.label || field.fieldKey] }, field.fieldKey))) })] })), selectedField.type === 'image' && (jsxs("div", { className: "property-group", children: [jsx("label", { htmlFor: `photo-radius-input-${selectedField.id}`, children: "Photo Radius" }), jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 8 }, children: [jsx("input", { type: "range", min: "0", max: "200", value: getPhotoRadiusSliderValue(selectedField.style?.borderRadius), onChange: (e) => handleFieldPropertyUpdate('style.borderRadius', `${e.target.value}px`), "aria-label": "Photo radius slider", style: { flex: 1 } }), jsx("input", { id: `photo-radius-input-${selectedField.id}`, type: "text", value: selectedField.style?.borderRadius || '0px', onChange: (e) => handleFieldPropertyUpdate('style.borderRadius', e.target.value.trim() || '0px'), style: { width: 72 } })] }), jsxs("div", { style: { display: 'flex', gap: 8, marginTop: 8 }, children: [jsx("button", { type: "button", className: "btn btn-outline btn-sm", onClick: () => handleFieldPropertyUpdate('style.borderRadius', '0px'), children: "Square" }), jsx("button", { type: "button", className: "btn btn-outline btn-sm", onClick: () => handleFieldPropertyUpdate('style.borderRadius', '50%'), children: "Circle" })] })] })), selectedField.type !== 'text' && selectedField.type !== 'table' && jsxs(Fragment, { children: [jsx("h4", { children: "Style" }), jsxs("div", { className: "property-group", children: [jsx("label", { children: "Font Size" }), jsx("input", { type: "text", value: selectedField.style?.fontSize || '12px', onChange: (e) => handleFieldPropertyUpdate('style.fontSize', e.target.value) })] }), jsxs("div", { className: "property-group", children: [jsx("label", { children: "Font Weight" }), jsxs("select", { value: selectedField.style?.fontWeight || 'normal', onChange: (e) => handleFieldPropertyUpdate('style.fontWeight', e.target.value), children: [jsx("option", { value: "normal", children: "Normal" }), jsx("option", { value: "bold", children: "Bold" }), jsx("option", { value: "100", children: "100" }), jsx("option", { value: "200", children: "200" }), jsx("option", { value: "300", children: "300" }), jsx("option", { value: "400", children: "400" }), jsx("option", { value: "500", children: "500" }), jsx("option", { value: "600", children: "600" }), jsx("option", { value: "700", children: "700" }), jsx("option", { value: "800", children: "800" }), jsx("option", { value: "900", children: "900" })] })] }), jsxs("div", { className: "property-group", children: [jsx("label", { children: "Text Color" }), jsx("input", { type: "color", value: selectedField.style?.color || '#000000', onChange: (e) => handleFieldPropertyUpdate('style.color', e.target.value) })] }), jsxs("div", { className: "property-group", children: [jsx("label", { children: "Text Align" }), jsxs("select", { value: selectedField.style?.textAlign || 'left', onChange: (e) => handleFieldPropertyUpdate('style.textAlign', e.target.value), children: [jsx("option", { value: "left", children: "Left" }), jsx("option", { value: "center", children: "Center" }), jsx("option", { value: "right", children: "Right" })] })] }), selectedField.type === 'label' && (jsxs("div", { className: "property-group", children: [jsx("label", { children: "Text Transform" }), jsxs("select", { value: selectedField.style?.labelTextTransform || 'none', onChange: (e) => handleFieldPropertyUpdate('style.labelTextTransform', e.target.value), children: [jsx("option", { value: "none", children: "None" }), jsx("option", { value: "uppercase", children: "UPPERCASE" }), jsx("option", { value: "lowercase", children: "lowercase" }), jsx("option", { value: "capitalize", children: "Capitalize" })] })] }))] }), selectedField.type === 'qrcode' ? (jsxs("div", { className: "property-group", children: [jsx("label", { children: "Background Color" }), jsx("div", { style: {
491
511
  padding: '8px 10px',
492
512
  border: '1px solid #ddd',
493
513
  borderRadius: '4px',