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.
- package/dist/cjs/components/IDCardDesigner.js +24 -4
- package/dist/cjs/components/IDCardDesigner.js.map +1 -1
- package/dist/cjs/components/IDCardGenerator.js +3 -0
- package/dist/cjs/components/IDCardGenerator.js.map +1 -1
- package/dist/cjs/components/IDCardPreview.js +3 -0
- package/dist/cjs/components/IDCardPreview.js.map +1 -1
- package/dist/cjs/node_modules/qrious/dist/qrious.js +1 -1
- package/dist/esm/components/IDCardDesigner.js +24 -4
- package/dist/esm/components/IDCardDesigner.js.map +1 -1
- package/dist/esm/components/IDCardGenerator.js +3 -0
- package/dist/esm/components/IDCardGenerator.js.map +1 -1
- package/dist/esm/components/IDCardPreview.js +3 -0
- package/dist/esm/components/IDCardPreview.js.map +1 -1
- package/dist/esm/node_modules/qrious/dist/qrious.js +1 -1
- package/package.json +2 -2
|
@@ -16,6 +16,16 @@ const defaultFieldTypes = [
|
|
|
16
16
|
{ type: 'qrcode', label: 'QR Code', icon: '📱' },
|
|
17
17
|
{ type: 'table', label: 'Table', icon: '▦' },
|
|
18
18
|
];
|
|
19
|
+
const getPhotoRadiusSliderValue = (borderRadius) => {
|
|
20
|
+
if (typeof borderRadius !== 'string') {
|
|
21
|
+
return 0;
|
|
22
|
+
}
|
|
23
|
+
const parsed = Number.parseFloat(borderRadius);
|
|
24
|
+
if (!Number.isFinite(parsed)) {
|
|
25
|
+
return 0;
|
|
26
|
+
}
|
|
27
|
+
return Math.max(0, Math.min(200, Math.round(parsed)));
|
|
28
|
+
};
|
|
19
29
|
/**
|
|
20
30
|
* IDCardDesigner - Visual drag-and-drop template builder
|
|
21
31
|
*
|
|
@@ -383,11 +393,15 @@ const IDCardDesigner = ({ initialTemplate, onSave, onCancel, className = '', sty
|
|
|
383
393
|
}, [selectedFieldId, removeField]);
|
|
384
394
|
// Keyboard shortcuts
|
|
385
395
|
react.useEffect(() => {
|
|
396
|
+
const handleLineHeightInputFocus = () => {
|
|
397
|
+
};
|
|
398
|
+
const handleLineHeightInputBlur = () => {
|
|
399
|
+
};
|
|
386
400
|
// Listen for focus/blur on line height input
|
|
387
401
|
const lhInput = document.getElementById('line-height-input');
|
|
388
402
|
if (lhInput) {
|
|
389
|
-
lhInput.addEventListener('focus',
|
|
390
|
-
lhInput.addEventListener('blur',
|
|
403
|
+
lhInput.addEventListener('focus', handleLineHeightInputFocus);
|
|
404
|
+
lhInput.addEventListener('blur', handleLineHeightInputBlur);
|
|
391
405
|
}
|
|
392
406
|
const handleKeyDown = (e) => {
|
|
393
407
|
if (selectedFieldId) {
|
|
@@ -437,7 +451,13 @@ const IDCardDesigner = ({ initialTemplate, onSave, onCancel, className = '', sty
|
|
|
437
451
|
}
|
|
438
452
|
};
|
|
439
453
|
document.addEventListener('keydown', handleKeyDown);
|
|
440
|
-
return () =>
|
|
454
|
+
return () => {
|
|
455
|
+
document.removeEventListener('keydown', handleKeyDown);
|
|
456
|
+
if (lhInput) {
|
|
457
|
+
lhInput.removeEventListener('focus', handleLineHeightInputFocus);
|
|
458
|
+
lhInput.removeEventListener('blur', handleLineHeightInputBlur);
|
|
459
|
+
}
|
|
460
|
+
};
|
|
441
461
|
}, [selectedFieldId, handleDeleteField, template.fields, template.cardSize, updateField]);
|
|
442
462
|
return (jsxRuntime.jsxs("div", { className: `idcard-designer ${className}`, style: style, children: [jsxRuntime.jsxs("div", { className: "designer-header", children: [jsxRuntime.jsx("input", { type: "text", value: templateName, onChange: (e) => setTemplateName(e.target.value), className: "template-name-input", placeholder: "Template Name" }), jsxRuntime.jsxs("div", { className: "header-actions", children: [onCancel && (jsxRuntime.jsx("button", { type: "button", onClick: onCancel, className: "btn btn-secondary", children: "Cancel" })), jsxRuntime.jsx("button", { type: "button", onClick: handleSave, className: "btn btn-primary", disabled: !isValid, children: "Save Template" })] })] }), jsxRuntime.jsxs("div", { className: "designer-body", children: [jsxRuntime.jsxs("div", { className: "designer-sidebar left-sidebar", children: [jsxRuntime.jsx("h3", { children: "Add Fields" }), jsxRuntime.jsx("div", { className: "field-types", children: defaultFieldTypes.map((fieldType) => (jsxRuntime.jsxs("button", { type: "button", onClick: () => handleAddField(fieldType.type), className: "field-type-btn", children: [jsxRuntime.jsx("span", { className: "field-icon", children: fieldType.icon }), jsxRuntime.jsx("span", { className: "field-label", children: fieldType.label })] }, fieldType.type))) }), jsxRuntime.jsx("h3", { children: "Card Settings" }), jsxRuntime.jsxs("div", { className: "card-settings", children: [jsxRuntime.jsxs("div", { className: "setting-group", children: [jsxRuntime.jsx("label", { children: "Orientation" }), jsxRuntime.jsxs("div", { className: "btn-group", children: [jsxRuntime.jsx("button", { type: "button", className: `btn ${template.orientation === 'landscape' ? 'active' : ''}`, onClick: () => handleOrientationChange('landscape'), children: "Landscape" }), jsxRuntime.jsx("button", { type: "button", className: `btn ${template.orientation === 'portrait' ? 'active' : ''}`, onClick: () => handleOrientationChange('portrait'), children: "Portrait" })] })] }), jsxRuntime.jsxs("div", { className: "setting-group", children: [jsxRuntime.jsx("label", { children: "Card Sides" }), jsxRuntime.jsxs("div", { className: "btn-group", children: [jsxRuntime.jsx("button", { type: "button", className: `btn ${template.sides === 'single' ? 'active' : ''}`, onClick: () => handleSidesChange('single'), children: "Single" }), jsxRuntime.jsx("button", { type: "button", className: `btn ${template.sides === 'double' ? 'active' : ''}`, onClick: () => handleSidesChange('double'), children: "Double" })] })] }), jsxRuntime.jsxs("div", { className: "setting-group", children: [jsxRuntime.jsx("label", { children: "Card Size (px)" }), jsxRuntime.jsxs("div", { className: "size-inputs", children: [jsxRuntime.jsx("input", { type: "number", value: template.cardSize.width, onChange: (e) => setCardSize({ ...template.cardSize, width: Number(e.target.value) }), placeholder: "Width" }), jsxRuntime.jsx("span", { children: "\u00D7" }), jsxRuntime.jsx("input", { type: "number", value: template.cardSize.height, onChange: (e) => setCardSize({ ...template.cardSize, height: Number(e.target.value) }), placeholder: "Height" })] })] })] }), jsxRuntime.jsx("h3", { children: "Background" }), jsxRuntime.jsxs("div", { className: "background-upload", children: [jsxRuntime.jsx("input", { type: "file", accept: "image/*", onChange: handleBackgroundUpload, id: "bg-upload", className: "file-input" }), jsxRuntime.jsxs("label", { htmlFor: "bg-upload", className: "btn btn-outline", children: ["Upload ", activeSide, " Background"] }), template.backgrounds[activeSide] && (jsxRuntime.jsx("button", { type: "button", className: "btn btn-danger btn-sm", onClick: () => setBackground(activeSide, ''), children: "Remove" }))] })] }), jsxRuntime.jsxs("div", { className: "designer-preview", children: [jsxRuntime.jsxs("div", { className: "side-tabs", children: [jsxRuntime.jsx("button", { type: "button", className: `tab ${activeSide === 'front' ? 'active' : ''}`, onClick: () => setActiveSide('front'), children: "Front" }), template.sides === 'double' && (jsxRuntime.jsx("button", { type: "button", className: `tab ${activeSide === 'back' ? 'active' : ''}`, onClick: () => setActiveSide('back'), children: "Back" })), jsxRuntime.jsxs("label", { className: "grid-toggle", children: [jsxRuntime.jsx("input", { type: "checkbox", checked: showGrid, onChange: (e) => setShowGrid(e.target.checked) }), "Show Grid"] })] }), jsxRuntime.jsx("div", { ref: previewContainerRef, className: "preview-wrapper", onMouseDown: handleMouseDown, children: jsxRuntime.jsx(IDCardPreview.IDCardPreview, { template: template, data: sampleData, side: activeSide, showGrid: showGrid, onFieldSelect: handleFieldSelect, selectedFieldId: selectedFieldId, editable: true }) }), jsxRuntime.jsxs("div", { className: "fields-list", children: [jsxRuntime.jsxs("h4", { children: ["Fields on ", activeSide, " side:"] }), template.fields
|
|
443
463
|
.filter((f) => f.side === activeSide)
|
|
@@ -489,7 +509,7 @@ const IDCardDesigner = ({ initialTemplate, onSave, onCancel, className = '', sty
|
|
|
489
509
|
? [...currentFields, field.fieldKey]
|
|
490
510
|
: currentFields.filter(f => f !== field.fieldKey);
|
|
491
511
|
handleFieldPropertyUpdate('qrFields', newFields);
|
|
492
|
-
}, style: { marginRight: '6px' } }), field.label || field.fieldKey] }, field.fieldKey))) })] })), selectedField.type !== 'text' && selectedField.type !== 'table' && jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("h4", { children: "Style" }), jsxRuntime.jsxs("div", { className: "property-group", children: [jsxRuntime.jsx("label", { children: "Font Size" }), jsxRuntime.jsx("input", { type: "text", value: selectedField.style?.fontSize || '12px', onChange: (e) => handleFieldPropertyUpdate('style.fontSize', e.target.value) })] }), jsxRuntime.jsxs("div", { className: "property-group", children: [jsxRuntime.jsx("label", { children: "Font Weight" }), jsxRuntime.jsxs("select", { value: selectedField.style?.fontWeight || 'normal', onChange: (e) => handleFieldPropertyUpdate('style.fontWeight', e.target.value), children: [jsxRuntime.jsx("option", { value: "normal", children: "Normal" }), jsxRuntime.jsx("option", { value: "bold", children: "Bold" }), jsxRuntime.jsx("option", { value: "100", children: "100" }), jsxRuntime.jsx("option", { value: "200", children: "200" }), jsxRuntime.jsx("option", { value: "300", children: "300" }), jsxRuntime.jsx("option", { value: "400", children: "400" }), jsxRuntime.jsx("option", { value: "500", children: "500" }), jsxRuntime.jsx("option", { value: "600", children: "600" }), jsxRuntime.jsx("option", { value: "700", children: "700" }), jsxRuntime.jsx("option", { value: "800", children: "800" }), jsxRuntime.jsx("option", { value: "900", children: "900" })] })] }), jsxRuntime.jsxs("div", { className: "property-group", children: [jsxRuntime.jsx("label", { children: "Text Color" }), jsxRuntime.jsx("input", { type: "color", value: selectedField.style?.color || '#000000', onChange: (e) => handleFieldPropertyUpdate('style.color', e.target.value) })] }), jsxRuntime.jsxs("div", { className: "property-group", children: [jsxRuntime.jsx("label", { children: "Text Align" }), jsxRuntime.jsxs("select", { value: selectedField.style?.textAlign || 'left', onChange: (e) => handleFieldPropertyUpdate('style.textAlign', e.target.value), children: [jsxRuntime.jsx("option", { value: "left", children: "Left" }), jsxRuntime.jsx("option", { value: "center", children: "Center" }), jsxRuntime.jsx("option", { value: "right", children: "Right" })] })] }), selectedField.type === 'label' && (jsxRuntime.jsxs("div", { className: "property-group", children: [jsxRuntime.jsx("label", { children: "Text Transform" }), jsxRuntime.jsxs("select", { value: selectedField.style?.labelTextTransform || 'none', onChange: (e) => handleFieldPropertyUpdate('style.labelTextTransform', e.target.value), children: [jsxRuntime.jsx("option", { value: "none", children: "None" }), jsxRuntime.jsx("option", { value: "uppercase", children: "UPPERCASE" }), jsxRuntime.jsx("option", { value: "lowercase", children: "lowercase" }), jsxRuntime.jsx("option", { value: "capitalize", children: "Capitalize" })] })] }))] }), selectedField.type === 'qrcode' ? (jsxRuntime.jsxs("div", { className: "property-group", children: [jsxRuntime.jsx("label", { children: "Background Color" }), jsxRuntime.jsx("div", { style: {
|
|
512
|
+
}, style: { marginRight: '6px' } }), field.label || field.fieldKey] }, field.fieldKey))) })] })), selectedField.type === 'image' && (jsxRuntime.jsxs("div", { className: "property-group", children: [jsxRuntime.jsx("label", { htmlFor: `photo-radius-input-${selectedField.id}`, children: "Photo Radius" }), jsxRuntime.jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 8 }, children: [jsxRuntime.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 } }), jsxRuntime.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 } })] }), jsxRuntime.jsxs("div", { style: { display: 'flex', gap: 8, marginTop: 8 }, children: [jsxRuntime.jsx("button", { type: "button", className: "btn btn-outline btn-sm", onClick: () => handleFieldPropertyUpdate('style.borderRadius', '0px'), children: "Square" }), jsxRuntime.jsx("button", { type: "button", className: "btn btn-outline btn-sm", onClick: () => handleFieldPropertyUpdate('style.borderRadius', '50%'), children: "Circle" })] })] })), selectedField.type !== 'text' && selectedField.type !== 'table' && jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("h4", { children: "Style" }), jsxRuntime.jsxs("div", { className: "property-group", children: [jsxRuntime.jsx("label", { children: "Font Size" }), jsxRuntime.jsx("input", { type: "text", value: selectedField.style?.fontSize || '12px', onChange: (e) => handleFieldPropertyUpdate('style.fontSize', e.target.value) })] }), jsxRuntime.jsxs("div", { className: "property-group", children: [jsxRuntime.jsx("label", { children: "Font Weight" }), jsxRuntime.jsxs("select", { value: selectedField.style?.fontWeight || 'normal', onChange: (e) => handleFieldPropertyUpdate('style.fontWeight', e.target.value), children: [jsxRuntime.jsx("option", { value: "normal", children: "Normal" }), jsxRuntime.jsx("option", { value: "bold", children: "Bold" }), jsxRuntime.jsx("option", { value: "100", children: "100" }), jsxRuntime.jsx("option", { value: "200", children: "200" }), jsxRuntime.jsx("option", { value: "300", children: "300" }), jsxRuntime.jsx("option", { value: "400", children: "400" }), jsxRuntime.jsx("option", { value: "500", children: "500" }), jsxRuntime.jsx("option", { value: "600", children: "600" }), jsxRuntime.jsx("option", { value: "700", children: "700" }), jsxRuntime.jsx("option", { value: "800", children: "800" }), jsxRuntime.jsx("option", { value: "900", children: "900" })] })] }), jsxRuntime.jsxs("div", { className: "property-group", children: [jsxRuntime.jsx("label", { children: "Text Color" }), jsxRuntime.jsx("input", { type: "color", value: selectedField.style?.color || '#000000', onChange: (e) => handleFieldPropertyUpdate('style.color', e.target.value) })] }), jsxRuntime.jsxs("div", { className: "property-group", children: [jsxRuntime.jsx("label", { children: "Text Align" }), jsxRuntime.jsxs("select", { value: selectedField.style?.textAlign || 'left', onChange: (e) => handleFieldPropertyUpdate('style.textAlign', e.target.value), children: [jsxRuntime.jsx("option", { value: "left", children: "Left" }), jsxRuntime.jsx("option", { value: "center", children: "Center" }), jsxRuntime.jsx("option", { value: "right", children: "Right" })] })] }), selectedField.type === 'label' && (jsxRuntime.jsxs("div", { className: "property-group", children: [jsxRuntime.jsx("label", { children: "Text Transform" }), jsxRuntime.jsxs("select", { value: selectedField.style?.labelTextTransform || 'none', onChange: (e) => handleFieldPropertyUpdate('style.labelTextTransform', e.target.value), children: [jsxRuntime.jsx("option", { value: "none", children: "None" }), jsxRuntime.jsx("option", { value: "uppercase", children: "UPPERCASE" }), jsxRuntime.jsx("option", { value: "lowercase", children: "lowercase" }), jsxRuntime.jsx("option", { value: "capitalize", children: "Capitalize" })] })] }))] }), selectedField.type === 'qrcode' ? (jsxRuntime.jsxs("div", { className: "property-group", children: [jsxRuntime.jsx("label", { children: "Background Color" }), jsxRuntime.jsx("div", { style: {
|
|
493
513
|
padding: '8px 10px',
|
|
494
514
|
border: '1px solid #ddd',
|
|
495
515
|
borderRadius: '4px',
|