react-id-card-generator 1.0.2 → 1.0.4
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 +0 -3
- package/dist/cjs/components/IDCardDesigner.js.map +1 -1
- package/dist/cjs/components/IDCardGenerator.js +0 -3
- package/dist/cjs/components/IDCardGenerator.js.map +1 -1
- package/dist/cjs/components/IDCardPreview.js +0 -3
- package/dist/cjs/components/IDCardPreview.js.map +1 -1
- package/dist/cjs/core/exportUtils.js +2 -2
- package/dist/cjs/core/exportUtils.js.map +1 -1
- package/dist/cjs/hooks/useIDCardTemplate.js +41 -12
- package/dist/cjs/hooks/useIDCardTemplate.js.map +1 -1
- package/dist/esm/components/IDCardDesigner.js +1 -1
- package/dist/esm/components/IDCardDesigner.js.map +1 -1
- package/dist/esm/components/IDCardGenerator.js +1 -1
- package/dist/esm/components/IDCardGenerator.js.map +1 -1
- package/dist/esm/components/IDCardPreview.js +1 -1
- package/dist/esm/components/IDCardPreview.js.map +1 -1
- package/dist/esm/core/exportUtils.js +1 -1
- package/dist/esm/hooks/useIDCardTemplate.js +41 -12
- package/dist/esm/hooks/useIDCardTemplate.js.map +1 -1
- package/dist/index.d.ts +484 -0
- package/dist/types/components/IDCardDesigner.d.ts +0 -1
- package/dist/types/components/IDCardGenerator.d.ts +0 -1
- package/dist/types/components/IDCardPreview.d.ts +0 -1
- package/package.json +6 -1
|
@@ -29,25 +29,42 @@ function useIDCardTemplate(initialTemplate) {
|
|
|
29
29
|
}, []);
|
|
30
30
|
// Update specific properties of a field
|
|
31
31
|
const updateField = useCallback((fieldId, updates) => {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
if (!fieldId || !updates)
|
|
33
|
+
return;
|
|
34
|
+
setTemplateState((prev) => {
|
|
35
|
+
const fieldExists = prev.fields.some((field) => field?.id === fieldId);
|
|
36
|
+
if (!fieldExists)
|
|
37
|
+
return prev;
|
|
38
|
+
return {
|
|
39
|
+
...prev,
|
|
40
|
+
updatedAt: new Date().toISOString(),
|
|
41
|
+
fields: prev.fields.map((field) => field?.id === fieldId ? { ...field, ...updates } : field).filter(Boolean),
|
|
42
|
+
};
|
|
43
|
+
});
|
|
37
44
|
}, []);
|
|
38
45
|
// Add a new field to the template
|
|
39
46
|
const addField = useCallback((field) => {
|
|
47
|
+
if (!field || !field.type || !field.position) {
|
|
48
|
+
console.warn('Invalid field object provided to addField:', field);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const validField = {
|
|
52
|
+
...field,
|
|
53
|
+
id: field.id || generateId('field'),
|
|
54
|
+
};
|
|
40
55
|
setTemplateState((prev) => ({
|
|
41
56
|
...prev,
|
|
42
57
|
updatedAt: new Date().toISOString(),
|
|
43
|
-
fields: [...prev.fields
|
|
58
|
+
fields: [...prev.fields.filter(Boolean), validField],
|
|
44
59
|
}));
|
|
45
60
|
}, []);
|
|
46
61
|
const removeField = useCallback((fieldId) => {
|
|
62
|
+
if (!fieldId)
|
|
63
|
+
return;
|
|
47
64
|
setTemplateState((prev) => ({
|
|
48
65
|
...prev,
|
|
49
66
|
updatedAt: new Date().toISOString(),
|
|
50
|
-
fields: prev.fields.filter((field) => field.id !== fieldId),
|
|
67
|
+
fields: prev.fields.filter((field) => field?.id && field.id !== fieldId),
|
|
51
68
|
}));
|
|
52
69
|
}, []);
|
|
53
70
|
const setBackground = useCallback((side, imageData) => {
|
|
@@ -94,9 +111,11 @@ function useIDCardTemplate(initialTemplate) {
|
|
|
94
111
|
}));
|
|
95
112
|
}, []);
|
|
96
113
|
const duplicateField = useCallback((fieldId) => {
|
|
114
|
+
if (!fieldId)
|
|
115
|
+
return;
|
|
97
116
|
setTemplateState((prev) => {
|
|
98
|
-
const field = prev.fields.find((f) => f
|
|
99
|
-
if (!field)
|
|
117
|
+
const field = prev.fields.find((f) => f?.id === fieldId);
|
|
118
|
+
if (!field || !field.position)
|
|
100
119
|
return prev;
|
|
101
120
|
const newField = {
|
|
102
121
|
...field,
|
|
@@ -110,15 +129,17 @@ function useIDCardTemplate(initialTemplate) {
|
|
|
110
129
|
return {
|
|
111
130
|
...prev,
|
|
112
131
|
updatedAt: new Date().toISOString(),
|
|
113
|
-
fields: [...prev.fields, newField],
|
|
132
|
+
fields: [...prev.fields.filter(Boolean), newField],
|
|
114
133
|
};
|
|
115
134
|
});
|
|
116
135
|
}, []);
|
|
117
136
|
const moveFieldToSide = useCallback((fieldId, side) => {
|
|
137
|
+
if (!fieldId || !side)
|
|
138
|
+
return;
|
|
118
139
|
setTemplateState((prev) => ({
|
|
119
140
|
...prev,
|
|
120
141
|
updatedAt: new Date().toISOString(),
|
|
121
|
-
fields: prev.fields.map((field) => field
|
|
142
|
+
fields: prev.fields.map((field) => field?.id === fieldId ? { ...field, side } : field).filter(Boolean),
|
|
122
143
|
}));
|
|
123
144
|
}, []);
|
|
124
145
|
const reset = useCallback(() => {
|
|
@@ -131,8 +152,16 @@ function useIDCardTemplate(initialTemplate) {
|
|
|
131
152
|
validationErrors: errors.map((e) => `${e.field}: ${e.message}`),
|
|
132
153
|
};
|
|
133
154
|
}, [template]);
|
|
155
|
+
// Ensure template always has valid fields array
|
|
156
|
+
const safeTemplate = useMemo(() => ({
|
|
157
|
+
...template,
|
|
158
|
+
fields: template.fields.filter((field) => Boolean(field) &&
|
|
159
|
+
Boolean(field.id) &&
|
|
160
|
+
Boolean(field.type) &&
|
|
161
|
+
Boolean(field.position)),
|
|
162
|
+
}), [template]);
|
|
134
163
|
return {
|
|
135
|
-
template,
|
|
164
|
+
template: safeTemplate,
|
|
136
165
|
setTemplate,
|
|
137
166
|
updateField,
|
|
138
167
|
addField,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useIDCardTemplate.js","sources":["../../../src/hooks/useIDCardTemplate.ts"],"sourcesContent":["import { useState, useCallback, useMemo } from 'react';\r\nimport type {\r\n IDCardTemplate,\r\n FieldMapping,\r\n CardSize,\r\n CardOrientation,\r\n CardSides,\r\n UseIDCardTemplateReturn,\r\n} from '../types';\r\nimport { createDefaultTemplate, generateId } from '../storage/templateStorage';\r\nimport { validateTemplate } from '../utils/validators';\r\n\r\n/**\r\n * Hook for managing ID card template state\r\n * Provides methods for updating fields, backgrounds, and card properties\r\n * Automatically updates the template's updatedAt timestamp on changes\r\n * \r\n * @param initialTemplate - Optional existing template to start with\r\n * @returns Template state and helper methods\r\n */\r\nexport function useIDCardTemplate(\r\n initialTemplate?: Partial<IDCardTemplate>\r\n): UseIDCardTemplateReturn {\r\n const [template, setTemplateState] = useState<IDCardTemplate>(() => {\r\n if (initialTemplate) {\r\n return {\r\n ...createDefaultTemplate(),\r\n ...initialTemplate,\r\n updatedAt: new Date().toISOString(),\r\n };\r\n }\r\n return createDefaultTemplate();\r\n });\r\n\r\n const setTemplate = useCallback((newTemplate: IDCardTemplate) => {\r\n setTemplateState({\r\n ...newTemplate,\r\n updatedAt: new Date().toISOString(),\r\n });\r\n }, []);\r\n\r\n // Update specific properties of a field\r\n const updateField = useCallback((fieldId: string, updates: Partial<FieldMapping>) => {\r\n setTemplateState((prev: IDCardTemplate) => ({\r\n ...prev,\r\n updatedAt: new Date().toISOString(),\r\n fields: prev.fields.map((field: FieldMapping) =>\r\n field.id === fieldId ? { ...field, ...updates } : field\r\n ),\r\n }));\r\n }, []);\r\n\r\n // Add a new field to the template\r\n const addField = useCallback((field: FieldMapping) => {\r\n setTemplateState((prev: IDCardTemplate) => ({\r\n ...prev,\r\n updatedAt: new Date().toISOString(),\r\n fields: [...prev.fields, { ...field, id: field.id || generateId('field') }],\r\n }));\r\n }, []);\r\n\r\n const removeField = useCallback((fieldId: string) => {\r\n setTemplateState((prev: IDCardTemplate) => ({\r\n ...prev,\r\n updatedAt: new Date().toISOString(),\r\n fields: prev.fields.filter((field: FieldMapping) => field.id !== fieldId),\r\n }));\r\n }, []);\r\n\r\n const setBackground = useCallback((side: 'front' | 'back', imageData: string) => {\r\n setTemplateState((prev: IDCardTemplate) => ({\r\n ...prev,\r\n updatedAt: new Date().toISOString(),\r\n backgrounds: {\r\n ...prev.backgrounds,\r\n [side]: imageData,\r\n },\r\n }));\r\n }, []);\r\n\r\n const setCardSize = useCallback((size: CardSize) => {\r\n setTemplateState((prev: IDCardTemplate) => ({\r\n ...prev,\r\n updatedAt: new Date().toISOString(),\r\n cardSize: size,\r\n }));\r\n }, []);\r\n\r\n const setOrientation = useCallback((orientation: CardOrientation) => {\r\n setTemplateState((prev: IDCardTemplate) => {\r\n // Swap dimensions if orientation changes\r\n const shouldSwap =\r\n (orientation === 'portrait' && prev.cardSize.width > prev.cardSize.height) ||\r\n (orientation === 'landscape' && prev.cardSize.height > prev.cardSize.width);\r\n\r\n return {\r\n ...prev,\r\n updatedAt: new Date().toISOString(),\r\n orientation,\r\n cardSize: shouldSwap\r\n ? {\r\n ...prev.cardSize,\r\n width: prev.cardSize.height,\r\n height: prev.cardSize.width,\r\n }\r\n : prev.cardSize,\r\n };\r\n });\r\n }, []);\r\n\r\n const setSides = useCallback((sides: CardSides) => {\r\n setTemplateState((prev: IDCardTemplate) => ({\r\n ...prev,\r\n updatedAt: new Date().toISOString(),\r\n sides,\r\n }));\r\n }, []);\r\n\r\n const duplicateField = useCallback((fieldId: string) => {\r\n setTemplateState((prev: IDCardTemplate) => {\r\n const field = prev.fields.find((f: FieldMapping) => f.id === fieldId);\r\n if (!field) return prev;\r\n\r\n const newField: FieldMapping = {\r\n ...field,\r\n id: generateId('field'),\r\n position: {\r\n ...field.position,\r\n x: field.position.x + 10,\r\n y: field.position.y + 10,\r\n },\r\n };\r\n\r\n return {\r\n ...prev,\r\n updatedAt: new Date().toISOString(),\r\n fields: [...prev.fields, newField],\r\n };\r\n });\r\n }, []);\r\n\r\n const moveFieldToSide = useCallback((fieldId: string, side: 'front' | 'back') => {\r\n setTemplateState((prev: IDCardTemplate) => ({\r\n ...prev,\r\n updatedAt: new Date().toISOString(),\r\n fields: prev.fields.map((field: FieldMapping) =>\r\n field.id === fieldId ? { ...field, side } : field\r\n ),\r\n }));\r\n }, []);\r\n\r\n const reset = useCallback(() => {\r\n setTemplateState(createDefaultTemplate());\r\n }, []);\r\n\r\n const validationResult = useMemo(() => {\r\n const errors = validateTemplate(template);\r\n return {\r\n isValid: errors.length === 0,\r\n validationErrors: errors.map((e) => `${e.field}: ${e.message}`),\r\n };\r\n }, [template]);\r\n\r\n return {\r\n template,\r\n setTemplate,\r\n updateField,\r\n addField,\r\n removeField,\r\n setBackground,\r\n setCardSize,\r\n setOrientation,\r\n setSides,\r\n duplicateField,\r\n moveFieldToSide,\r\n reset,\r\n isValid: validationResult.isValid,\r\n validationErrors: validationResult.validationErrors,\r\n };\r\n}\r\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useIDCardTemplate.js","sources":["../../../src/hooks/useIDCardTemplate.ts"],"sourcesContent":["import { useState, useCallback, useMemo } from 'react';\r\nimport type {\r\n IDCardTemplate,\r\n FieldMapping,\r\n CardSize,\r\n CardOrientation,\r\n CardSides,\r\n UseIDCardTemplateReturn,\r\n} from '../types';\r\nimport { createDefaultTemplate, generateId } from '../storage/templateStorage';\r\nimport { validateTemplate } from '../utils/validators';\r\n\r\n/**\r\n * Hook for managing ID card template state\r\n * Provides methods for updating fields, backgrounds, and card properties\r\n * Automatically updates the template's updatedAt timestamp on changes\r\n * \r\n * @param initialTemplate - Optional existing template to start with\r\n * @returns Template state and helper methods\r\n */\r\nexport function useIDCardTemplate(\r\n initialTemplate?: Partial<IDCardTemplate>\r\n): UseIDCardTemplateReturn {\r\n const [template, setTemplateState] = useState<IDCardTemplate>(() => {\r\n if (initialTemplate) {\r\n return {\r\n ...createDefaultTemplate(),\r\n ...initialTemplate,\r\n updatedAt: new Date().toISOString(),\r\n };\r\n }\r\n return createDefaultTemplate();\r\n });\r\n\r\n const setTemplate = useCallback((newTemplate: IDCardTemplate) => {\r\n setTemplateState({\r\n ...newTemplate,\r\n updatedAt: new Date().toISOString(),\r\n });\r\n }, []);\r\n\r\n // Update specific properties of a field\r\n const updateField = useCallback((fieldId: string, updates: Partial<FieldMapping>) => {\r\n if (!fieldId || !updates) return;\r\n \r\n setTemplateState((prev: IDCardTemplate) => {\r\n const fieldExists = prev.fields.some((field: FieldMapping) => field?.id === fieldId);\r\n if (!fieldExists) return prev;\r\n \r\n return {\r\n ...prev,\r\n updatedAt: new Date().toISOString(),\r\n fields: prev.fields.map((field: FieldMapping) =>\r\n field?.id === fieldId ? { ...field, ...updates } : field\r\n ).filter(Boolean),\r\n };\r\n });\r\n }, []);\r\n\r\n // Add a new field to the template\r\n const addField = useCallback((field: FieldMapping) => {\r\n if (!field || !field.type || !field.position) {\r\n console.warn('Invalid field object provided to addField:', field);\r\n return;\r\n }\r\n \r\n const validField = {\r\n ...field,\r\n id: field.id || generateId('field'),\r\n };\r\n \r\n setTemplateState((prev: IDCardTemplate) => ({\r\n ...prev,\r\n updatedAt: new Date().toISOString(),\r\n fields: [...prev.fields.filter(Boolean), validField],\r\n }));\r\n }, []);\r\n\r\n const removeField = useCallback((fieldId: string) => {\r\n if (!fieldId) return;\r\n \r\n setTemplateState((prev: IDCardTemplate) => ({\r\n ...prev,\r\n updatedAt: new Date().toISOString(),\r\n fields: prev.fields.filter((field: FieldMapping) => field?.id && field.id !== fieldId),\r\n }));\r\n }, []);\r\n\r\n const setBackground = useCallback((side: 'front' | 'back', imageData: string) => {\r\n setTemplateState((prev: IDCardTemplate) => ({\r\n ...prev,\r\n updatedAt: new Date().toISOString(),\r\n backgrounds: {\r\n ...prev.backgrounds,\r\n [side]: imageData,\r\n },\r\n }));\r\n }, []);\r\n\r\n const setCardSize = useCallback((size: CardSize) => {\r\n setTemplateState((prev: IDCardTemplate) => ({\r\n ...prev,\r\n updatedAt: new Date().toISOString(),\r\n cardSize: size,\r\n }));\r\n }, []);\r\n\r\n const setOrientation = useCallback((orientation: CardOrientation) => {\r\n setTemplateState((prev: IDCardTemplate) => {\r\n // Swap dimensions if orientation changes\r\n const shouldSwap =\r\n (orientation === 'portrait' && prev.cardSize.width > prev.cardSize.height) ||\r\n (orientation === 'landscape' && prev.cardSize.height > prev.cardSize.width);\r\n\r\n return {\r\n ...prev,\r\n updatedAt: new Date().toISOString(),\r\n orientation,\r\n cardSize: shouldSwap\r\n ? {\r\n ...prev.cardSize,\r\n width: prev.cardSize.height,\r\n height: prev.cardSize.width,\r\n }\r\n : prev.cardSize,\r\n };\r\n });\r\n }, []);\r\n\r\n const setSides = useCallback((sides: CardSides) => {\r\n setTemplateState((prev: IDCardTemplate) => ({\r\n ...prev,\r\n updatedAt: new Date().toISOString(),\r\n sides,\r\n }));\r\n }, []);\r\n\r\n const duplicateField = useCallback((fieldId: string) => {\r\n if (!fieldId) return;\r\n \r\n setTemplateState((prev: IDCardTemplate) => {\r\n const field = prev.fields.find((f: FieldMapping) => f?.id === fieldId);\r\n if (!field || !field.position) return prev;\r\n\r\n const newField: FieldMapping = {\r\n ...field,\r\n id: generateId('field'),\r\n position: {\r\n ...field.position,\r\n x: field.position.x + 10,\r\n y: field.position.y + 10,\r\n },\r\n };\r\n\r\n return {\r\n ...prev,\r\n updatedAt: new Date().toISOString(),\r\n fields: [...prev.fields.filter(Boolean), newField],\r\n };\r\n });\r\n }, []);\r\n\r\n const moveFieldToSide = useCallback((fieldId: string, side: 'front' | 'back') => {\r\n if (!fieldId || !side) return;\r\n \r\n setTemplateState((prev: IDCardTemplate) => ({\r\n ...prev,\r\n updatedAt: new Date().toISOString(),\r\n fields: prev.fields.map((field: FieldMapping) =>\r\n field?.id === fieldId ? { ...field, side } : field\r\n ).filter(Boolean),\r\n }));\r\n }, []);\r\n\r\n const reset = useCallback(() => {\r\n setTemplateState(createDefaultTemplate());\r\n }, []);\r\n\r\n const validationResult = useMemo(() => {\r\n const errors = validateTemplate(template);\r\n return {\r\n isValid: errors.length === 0,\r\n validationErrors: errors.map((e) => `${e.field}: ${e.message}`),\r\n };\r\n }, [template]);\r\n\r\n // Ensure template always has valid fields array\r\n const safeTemplate = useMemo(() => ({\r\n ...template,\r\n fields: template.fields.filter((field): field is FieldMapping => \r\n Boolean(field) && \r\n Boolean(field.id) && \r\n Boolean(field.type) && \r\n Boolean(field.position)\r\n ),\r\n }), [template]);\r\n\r\n return {\r\n template: safeTemplate,\r\n setTemplate,\r\n updateField,\r\n addField,\r\n removeField,\r\n setBackground,\r\n setCardSize,\r\n setOrientation,\r\n setSides,\r\n duplicateField,\r\n moveFieldToSide,\r\n reset,\r\n isValid: validationResult.isValid,\r\n validationErrors: validationResult.validationErrors,\r\n };\r\n}\r\n"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Position and dimensions of a field on the card
|
|
5
|
+
* All values are in pixels relative to the card's top-left corner
|
|
6
|
+
*/
|
|
7
|
+
interface FieldPosition {
|
|
8
|
+
x: number;
|
|
9
|
+
y: number;
|
|
10
|
+
width: number;
|
|
11
|
+
height: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* CSS-like styling options for text and container fields
|
|
15
|
+
* Values should be valid CSS strings (e.g., '12px', '#000000', '50%')
|
|
16
|
+
*/
|
|
17
|
+
interface FieldStyle {
|
|
18
|
+
fontSize?: string;
|
|
19
|
+
fontWeight?: 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900';
|
|
20
|
+
fontFamily?: string;
|
|
21
|
+
color?: string;
|
|
22
|
+
textAlign?: 'left' | 'center' | 'right';
|
|
23
|
+
textTransform?: 'none' | 'uppercase' | 'lowercase' | 'capitalize';
|
|
24
|
+
backgroundColor?: string;
|
|
25
|
+
borderRadius?: string;
|
|
26
|
+
padding?: string;
|
|
27
|
+
border?: string;
|
|
28
|
+
lineHeight?: string;
|
|
29
|
+
letterSpacing?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Available field types for ID cards
|
|
33
|
+
* - text: Dynamic text data (name, ID, etc.)
|
|
34
|
+
* - image: Photos or logos
|
|
35
|
+
* - qrcode: QR codes generated from card data
|
|
36
|
+
* - label: Static text that doesn't change
|
|
37
|
+
*/
|
|
38
|
+
type FieldType = 'text' | 'image' | 'qrcode' | 'label';
|
|
39
|
+
/**
|
|
40
|
+
* A single field on the ID card (text, image, QR code, etc.)
|
|
41
|
+
* This defines what the field displays and how it's styled
|
|
42
|
+
*/
|
|
43
|
+
interface FieldMapping {
|
|
44
|
+
id: string;
|
|
45
|
+
fieldKey: string;
|
|
46
|
+
label?: string;
|
|
47
|
+
placeholder?: string;
|
|
48
|
+
type: FieldType;
|
|
49
|
+
side: 'front' | 'back';
|
|
50
|
+
position: FieldPosition;
|
|
51
|
+
style?: FieldStyle;
|
|
52
|
+
required?: boolean;
|
|
53
|
+
qrFields?: string[];
|
|
54
|
+
aspectRatio?: number;
|
|
55
|
+
staticText?: string;
|
|
56
|
+
zIndex?: number;
|
|
57
|
+
}
|
|
58
|
+
type CardOrientation = 'portrait' | 'landscape';
|
|
59
|
+
type CardSides = 'single' | 'double';
|
|
60
|
+
/**
|
|
61
|
+
* Physical dimensions of the ID card
|
|
62
|
+
*/
|
|
63
|
+
interface CardSize {
|
|
64
|
+
width: number;
|
|
65
|
+
height: number;
|
|
66
|
+
unit: 'px' | 'mm' | 'in';
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Background images for card sides (base64 data URLs or HTTP URLs)
|
|
70
|
+
*/
|
|
71
|
+
interface CardBackground {
|
|
72
|
+
front?: string;
|
|
73
|
+
back?: string;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Complete ID card template definition
|
|
77
|
+
* This is the reusable template that can be filled with different user data
|
|
78
|
+
*/
|
|
79
|
+
interface IDCardTemplate {
|
|
80
|
+
id: string;
|
|
81
|
+
name: string;
|
|
82
|
+
version: string;
|
|
83
|
+
createdAt: string;
|
|
84
|
+
updatedAt: string;
|
|
85
|
+
orientation: CardOrientation;
|
|
86
|
+
sides: CardSides;
|
|
87
|
+
cardSize: CardSize;
|
|
88
|
+
backgrounds: CardBackground;
|
|
89
|
+
fields: FieldMapping[];
|
|
90
|
+
metadata?: Record<string, unknown>;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* User data to fill into the card template
|
|
94
|
+
* Keys should match fieldKey values in FieldMapping
|
|
95
|
+
* Example: { name: 'John Doe', photo: 'data:image/jpeg;base64,...' }
|
|
96
|
+
*/
|
|
97
|
+
interface IDCardData {
|
|
98
|
+
[key: string]: string | number | boolean | string[] | undefined;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Options for exporting cards to PDF or images
|
|
102
|
+
*/
|
|
103
|
+
interface ExportOptions {
|
|
104
|
+
format: 'pdf' | 'png' | 'jpeg';
|
|
105
|
+
scale?: number;
|
|
106
|
+
quality?: number;
|
|
107
|
+
filename?: string;
|
|
108
|
+
pages?: ('front' | 'back')[];
|
|
109
|
+
includeBleed?: boolean;
|
|
110
|
+
bleedSize?: number;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Result from an export operation
|
|
114
|
+
*/
|
|
115
|
+
interface ExportResult {
|
|
116
|
+
success: boolean;
|
|
117
|
+
blob?: Blob;
|
|
118
|
+
dataUrl?: string;
|
|
119
|
+
error?: string;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Props for IDCardGenerator - renders a filled ID card
|
|
123
|
+
*/
|
|
124
|
+
interface IDCardGeneratorProps {
|
|
125
|
+
template: IDCardTemplate;
|
|
126
|
+
data: IDCardData;
|
|
127
|
+
side?: 'front' | 'back';
|
|
128
|
+
scale?: number;
|
|
129
|
+
className?: string;
|
|
130
|
+
style?: React.CSSProperties;
|
|
131
|
+
onFieldClick?: (field: FieldMapping) => void;
|
|
132
|
+
editable?: boolean;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Props for IDCardDesigner - the visual template builder
|
|
136
|
+
*/
|
|
137
|
+
interface IDCardDesignerProps {
|
|
138
|
+
initialTemplate?: Partial<IDCardTemplate>;
|
|
139
|
+
onSave: (template: IDCardTemplate) => void;
|
|
140
|
+
onCancel?: () => void;
|
|
141
|
+
availableFields?: FieldDefinition[];
|
|
142
|
+
className?: string;
|
|
143
|
+
style?: React.CSSProperties;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Definition of a field type available in the designer
|
|
147
|
+
*/
|
|
148
|
+
interface FieldDefinition {
|
|
149
|
+
key: string;
|
|
150
|
+
label: string;
|
|
151
|
+
type: FieldType;
|
|
152
|
+
defaultStyle?: FieldStyle;
|
|
153
|
+
required?: boolean;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Props for IDCardPreview - interactive card preview with editing
|
|
157
|
+
*/
|
|
158
|
+
interface IDCardPreviewProps {
|
|
159
|
+
template: IDCardTemplate;
|
|
160
|
+
data: IDCardData;
|
|
161
|
+
side: 'front' | 'back';
|
|
162
|
+
scale?: number;
|
|
163
|
+
showGrid?: boolean;
|
|
164
|
+
onFieldSelect?: (field: FieldMapping | null) => void;
|
|
165
|
+
selectedFieldId?: string | null;
|
|
166
|
+
editable?: boolean;
|
|
167
|
+
onFieldUpdate?: (field: FieldMapping) => void;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Return value from useIDCardTemplate hook
|
|
171
|
+
* Provides template state management and helper methods
|
|
172
|
+
*/
|
|
173
|
+
interface UseIDCardTemplateReturn {
|
|
174
|
+
template: IDCardTemplate;
|
|
175
|
+
setTemplate: (template: IDCardTemplate) => void;
|
|
176
|
+
updateField: (fieldId: string, updates: Partial<FieldMapping>) => void;
|
|
177
|
+
addField: (field: FieldMapping) => void;
|
|
178
|
+
removeField: (fieldId: string) => void;
|
|
179
|
+
setBackground: (side: 'front' | 'back', imageData: string) => void;
|
|
180
|
+
setCardSize: (size: CardSize) => void;
|
|
181
|
+
setOrientation: (orientation: CardOrientation) => void;
|
|
182
|
+
setSides: (sides: CardSides) => void;
|
|
183
|
+
duplicateField: (fieldId: string) => void;
|
|
184
|
+
moveFieldToSide: (fieldId: string, side: 'front' | 'back') => void;
|
|
185
|
+
reset: () => void;
|
|
186
|
+
isValid: boolean;
|
|
187
|
+
validationErrors: string[];
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Return value from useIDCardExport hook
|
|
191
|
+
* Handles exporting cards to PDF or images
|
|
192
|
+
*/
|
|
193
|
+
interface UseIDCardExportReturn {
|
|
194
|
+
exportAsPDF: (options?: Partial<ExportOptions>) => Promise<ExportResult>;
|
|
195
|
+
exportAsImage: (options?: Partial<ExportOptions>) => Promise<ExportResult>;
|
|
196
|
+
isExporting: boolean;
|
|
197
|
+
progress: number;
|
|
198
|
+
error: string | null;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Return value from useFieldMapping hook
|
|
202
|
+
* Handles field selection, dragging, and resizing
|
|
203
|
+
*/
|
|
204
|
+
interface UseFieldMappingReturn {
|
|
205
|
+
selectedField: FieldMapping | null;
|
|
206
|
+
selectField: (field: FieldMapping | null) => void;
|
|
207
|
+
updatePosition: (position: Partial<FieldPosition>) => void;
|
|
208
|
+
updateStyle: (style: Partial<FieldStyle>) => void;
|
|
209
|
+
isDragging: boolean;
|
|
210
|
+
isResizing: boolean;
|
|
211
|
+
startDrag: (e: React.MouseEvent) => void;
|
|
212
|
+
startResize: (e: React.MouseEvent, handle: string) => void;
|
|
213
|
+
}
|
|
214
|
+
interface TemplateStorage {
|
|
215
|
+
save: (key: string, template: IDCardTemplate) => Promise<void>;
|
|
216
|
+
load: (key: string) => Promise<IDCardTemplate | null>;
|
|
217
|
+
list: () => Promise<string[]>;
|
|
218
|
+
remove: (key: string) => Promise<void>;
|
|
219
|
+
}
|
|
220
|
+
interface DragState {
|
|
221
|
+
isDragging: boolean;
|
|
222
|
+
startX: number;
|
|
223
|
+
startY: number;
|
|
224
|
+
currentX: number;
|
|
225
|
+
currentY: number;
|
|
226
|
+
fieldId: string | null;
|
|
227
|
+
}
|
|
228
|
+
interface ResizeState {
|
|
229
|
+
isResizing: boolean;
|
|
230
|
+
handle: 'n' | 's' | 'e' | 'w' | 'ne' | 'nw' | 'se' | 'sw' | null;
|
|
231
|
+
startX: number;
|
|
232
|
+
startY: number;
|
|
233
|
+
startWidth: number;
|
|
234
|
+
startHeight: number;
|
|
235
|
+
fieldId: string | null;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* IDCardGenerator - Renders a completed ID card
|
|
240
|
+
*
|
|
241
|
+
* Takes a template and user data, then renders the filled card.
|
|
242
|
+
* This is the component used to display actual ID cards for individual users.
|
|
243
|
+
*
|
|
244
|
+
* Example:
|
|
245
|
+
* ```tsx
|
|
246
|
+
* <IDCardGenerator
|
|
247
|
+
* template={myTemplate}
|
|
248
|
+
* data={{ name: 'John Doe', photo: '...' }}
|
|
249
|
+
* side="front"
|
|
250
|
+
* />
|
|
251
|
+
* ```
|
|
252
|
+
*/
|
|
253
|
+
declare const IDCardGenerator: React.FC<IDCardGeneratorProps>;
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* IDCardDesigner - Visual drag-and-drop template builder
|
|
257
|
+
*
|
|
258
|
+
* Allows users to:
|
|
259
|
+
* - Add and position fields on the card
|
|
260
|
+
* - Upload background images
|
|
261
|
+
* - Configure field styles (fonts, colors, etc.)
|
|
262
|
+
* - Choose card orientation and sides
|
|
263
|
+
* - Preview the card with sample data
|
|
264
|
+
*/
|
|
265
|
+
/**
|
|
266
|
+
* IDCardDesigner - Visual drag-and-drop ID card template builder
|
|
267
|
+
*/
|
|
268
|
+
declare const IDCardDesigner: React.FC<IDCardDesignerProps>;
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* IDCardPreview - Interactive card preview component
|
|
272
|
+
*
|
|
273
|
+
* Renders an ID card with:
|
|
274
|
+
* - Field selection and highlighting
|
|
275
|
+
* - Resize handles for selected fields
|
|
276
|
+
* - Grid overlay for alignment
|
|
277
|
+
* - Dynamic field rendering based on type
|
|
278
|
+
*
|
|
279
|
+
* Used inside the designer for visual editing
|
|
280
|
+
*/
|
|
281
|
+
declare const IDCardPreview: React.FC<IDCardPreviewProps>;
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Hook for managing ID card template state
|
|
285
|
+
* Provides methods for updating fields, backgrounds, and card properties
|
|
286
|
+
* Automatically updates the template's updatedAt timestamp on changes
|
|
287
|
+
*
|
|
288
|
+
* @param initialTemplate - Optional existing template to start with
|
|
289
|
+
* @returns Template state and helper methods
|
|
290
|
+
*/
|
|
291
|
+
declare function useIDCardTemplate(initialTemplate?: Partial<IDCardTemplate>): UseIDCardTemplateReturn;
|
|
292
|
+
|
|
293
|
+
interface ExportConfig {
|
|
294
|
+
frontElementId?: string;
|
|
295
|
+
backElementId?: string;
|
|
296
|
+
data?: IDCardData;
|
|
297
|
+
qrElementId?: string;
|
|
298
|
+
qrFields?: string[];
|
|
299
|
+
}
|
|
300
|
+
declare function useIDCardExport(config?: ExportConfig): UseIDCardExportReturn;
|
|
301
|
+
|
|
302
|
+
interface UseFieldMappingOptions {
|
|
303
|
+
onFieldUpdate?: (field: FieldMapping) => void;
|
|
304
|
+
containerRef?: React.RefObject<HTMLElement>;
|
|
305
|
+
gridSize?: number;
|
|
306
|
+
snapToGrid?: boolean;
|
|
307
|
+
}
|
|
308
|
+
declare function useFieldMapping(options?: UseFieldMappingOptions): UseFieldMappingReturn;
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Generate a QR code as a base64 data URL
|
|
312
|
+
* @param data - Data to encode in the QR code (will be JSON stringified)
|
|
313
|
+
* @param size - QR code size in pixels
|
|
314
|
+
* @param options - Customization options (error correction level, colors, etc.)
|
|
315
|
+
* @returns Base64 PNG data URL
|
|
316
|
+
*/
|
|
317
|
+
declare function generateQrCodeDataURL(data: Record<string, unknown>, size?: number, options?: {
|
|
318
|
+
level?: 'L' | 'M' | 'Q' | 'H';
|
|
319
|
+
padding?: number;
|
|
320
|
+
background?: string;
|
|
321
|
+
foreground?: string;
|
|
322
|
+
}): string;
|
|
323
|
+
/**
|
|
324
|
+
* Generate QR code from specific fields in the card data
|
|
325
|
+
* Only includes fields that exist in the data object
|
|
326
|
+
* @param data - Full card data object
|
|
327
|
+
* @param fields - Array of field keys to include in QR code
|
|
328
|
+
* @param size - QR code size in pixels
|
|
329
|
+
* @returns Base64 PNG data URL
|
|
330
|
+
*/
|
|
331
|
+
declare function generateQrCodeFromFields(data: IDCardData, fields: string[], size?: number): string;
|
|
332
|
+
/**
|
|
333
|
+
* Set QR code image src on a DOM element
|
|
334
|
+
*/
|
|
335
|
+
declare function setQrCodeOnElement(elementId: string, data: Record<string, unknown>, size?: number, container?: Document | HTMLElement): boolean;
|
|
336
|
+
|
|
337
|
+
interface DownloadIDCardOptions {
|
|
338
|
+
frontElementId?: string;
|
|
339
|
+
backElementId?: string;
|
|
340
|
+
filename?: string;
|
|
341
|
+
data?: IDCardData;
|
|
342
|
+
qrElementId?: string;
|
|
343
|
+
qrFields?: string[];
|
|
344
|
+
format?: 'pdf' | 'png' | 'jpeg';
|
|
345
|
+
scale?: number;
|
|
346
|
+
quality?: number;
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Download ID card(s) as a PDF file
|
|
350
|
+
* Captures DOM elements and converts them to a multi-page PDF
|
|
351
|
+
* @param options - Configuration for PDF export
|
|
352
|
+
* @returns Export result with success status and any errors
|
|
353
|
+
*/
|
|
354
|
+
declare function downloadIDCardAsPDF(options: DownloadIDCardOptions): Promise<ExportResult>;
|
|
355
|
+
/**
|
|
356
|
+
* Download ID card as image (PNG or JPEG)
|
|
357
|
+
*/
|
|
358
|
+
declare function downloadIDCardAsImage(options: DownloadIDCardOptions): Promise<ExportResult>;
|
|
359
|
+
/**
|
|
360
|
+
* Export ID card with unified options
|
|
361
|
+
*/
|
|
362
|
+
declare function exportIDCard(options: ExportOptions & {
|
|
363
|
+
frontElementId?: string;
|
|
364
|
+
backElementId?: string;
|
|
365
|
+
data?: IDCardData;
|
|
366
|
+
qrElementId?: string;
|
|
367
|
+
qrFields?: string[];
|
|
368
|
+
}): Promise<ExportResult>;
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Save a template to browser localStorage
|
|
372
|
+
* @param key - Unique identifier for the template
|
|
373
|
+
* @param template - The template to save
|
|
374
|
+
* @throws Error if localStorage is unavailable or quota exceeded
|
|
375
|
+
*/
|
|
376
|
+
declare function saveTemplateToLocal(key: string, template: IDCardTemplate): void;
|
|
377
|
+
/**
|
|
378
|
+
* Load a template from browser localStorage
|
|
379
|
+
* @param key - Template identifier
|
|
380
|
+
* @returns The template, or null if not found or invalid
|
|
381
|
+
*/
|
|
382
|
+
declare function loadTemplateFromLocal(key: string): IDCardTemplate | null;
|
|
383
|
+
/**
|
|
384
|
+
* Get all saved template keys from localStorage
|
|
385
|
+
* @returns Array of template keys (without the prefix)
|
|
386
|
+
*/
|
|
387
|
+
declare function listTemplatesFromLocal(): string[];
|
|
388
|
+
/**
|
|
389
|
+
* Remove a template from localStorage
|
|
390
|
+
* @param key - Template identifier to remove
|
|
391
|
+
*/
|
|
392
|
+
declare function removeTemplateFromLocal(key: string): void;
|
|
393
|
+
/**
|
|
394
|
+
* Export a template as a downloadable JSON file
|
|
395
|
+
* @param template - The template to export
|
|
396
|
+
* @param filename - Optional custom filename (defaults to template name)
|
|
397
|
+
*/
|
|
398
|
+
declare function exportTemplateAsJSON(template: IDCardTemplate, filename?: string): void;
|
|
399
|
+
/**
|
|
400
|
+
* Import a template from a JSON file
|
|
401
|
+
* @param file - The JSON file to read
|
|
402
|
+
* @returns Promise that resolves to the parsed template
|
|
403
|
+
*/
|
|
404
|
+
declare function importTemplateFromJSON(file: File): Promise<IDCardTemplate>;
|
|
405
|
+
/**
|
|
406
|
+
* Convert an image file to a base64 data URL
|
|
407
|
+
* Useful for embedding images in templates
|
|
408
|
+
* @param file - Image file (JPG, PNG, etc.)
|
|
409
|
+
* @returns Promise that resolves to a base64 data URL
|
|
410
|
+
*/
|
|
411
|
+
declare function imageFileToBase64(file: File): Promise<string>;
|
|
412
|
+
/**
|
|
413
|
+
* Generate a unique ID with timestamp and random component
|
|
414
|
+
* @param prefix - Prefix for the ID (e.g., 'field', 'template')
|
|
415
|
+
* @returns Unique string like 'field_1703234567890_abc123def'
|
|
416
|
+
*/
|
|
417
|
+
declare function generateId(prefix?: string): string;
|
|
418
|
+
/**
|
|
419
|
+
* Create a default template
|
|
420
|
+
*/
|
|
421
|
+
declare function createDefaultTemplate(name?: string): IDCardTemplate;
|
|
422
|
+
|
|
423
|
+
interface ValidationError {
|
|
424
|
+
field: string;
|
|
425
|
+
message: string;
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* Validate a complete ID card template
|
|
429
|
+
* Checks for required fields, valid dimensions, and proper field configuration
|
|
430
|
+
* @param template - The template to validate
|
|
431
|
+
* @returns Array of validation errors (empty if valid)
|
|
432
|
+
*/
|
|
433
|
+
declare function validateTemplate(template: IDCardTemplate): ValidationError[];
|
|
434
|
+
/**
|
|
435
|
+
* Validate a single field's configuration
|
|
436
|
+
* @param field - The field to validate
|
|
437
|
+
* @param index - Field index (for error messages)
|
|
438
|
+
* @returns Array of validation errors
|
|
439
|
+
*/
|
|
440
|
+
declare function validateField(field: FieldMapping, index: number): ValidationError[];
|
|
441
|
+
/**
|
|
442
|
+
* Validate card size against standard dimensions
|
|
443
|
+
*/
|
|
444
|
+
declare function validateCardSize(size: CardSize): boolean;
|
|
445
|
+
/**
|
|
446
|
+
* Check if a field is within card bounds
|
|
447
|
+
*/
|
|
448
|
+
declare function isFieldInBounds(field: FieldMapping, cardSize: CardSize): boolean;
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Convert a style object with kebab-case keys to React camelCase
|
|
452
|
+
* Useful when importing styles from external sources
|
|
453
|
+
*/
|
|
454
|
+
declare function toReactStyle(styleObj: Record<string, unknown> | undefined): React.CSSProperties;
|
|
455
|
+
/**
|
|
456
|
+
* Convert FieldStyle to React CSS properties
|
|
457
|
+
* @param style - The field style object
|
|
458
|
+
* @returns React-compatible CSS properties object
|
|
459
|
+
*/
|
|
460
|
+
declare function fieldStyleToCSS(style: FieldStyle | undefined): React.CSSProperties;
|
|
461
|
+
/**
|
|
462
|
+
* Merge multiple style objects
|
|
463
|
+
*/
|
|
464
|
+
declare function mergeStyles(...styles: (React.CSSProperties | undefined)[]): React.CSSProperties;
|
|
465
|
+
/**
|
|
466
|
+
* Generate position styles from field position
|
|
467
|
+
*/
|
|
468
|
+
declare function positionToStyle(position: {
|
|
469
|
+
x: number;
|
|
470
|
+
y: number;
|
|
471
|
+
width: number;
|
|
472
|
+
height: number;
|
|
473
|
+
}): React.CSSProperties;
|
|
474
|
+
/**
|
|
475
|
+
* Default styles for different field types
|
|
476
|
+
*/
|
|
477
|
+
declare const defaultFieldStyles: Record<string, FieldStyle>;
|
|
478
|
+
/**
|
|
479
|
+
* CSS class name generator
|
|
480
|
+
*/
|
|
481
|
+
declare function cn(...classes: (string | undefined | null | false)[]): string;
|
|
482
|
+
|
|
483
|
+
export { IDCardDesigner, IDCardGenerator, IDCardPreview, cn, createDefaultTemplate, defaultFieldStyles, downloadIDCardAsImage, downloadIDCardAsPDF, exportIDCard, exportTemplateAsJSON, fieldStyleToCSS, generateId, generateQrCodeDataURL, generateQrCodeFromFields, imageFileToBase64, importTemplateFromJSON, isFieldInBounds, listTemplatesFromLocal, loadTemplateFromLocal, mergeStyles, positionToStyle, removeTemplateFromLocal, saveTemplateToLocal, setQrCodeOnElement, toReactStyle, useFieldMapping, useIDCardExport, useIDCardTemplate, validateCardSize, validateField, validateTemplate };
|
|
484
|
+
export type { CardBackground, CardOrientation, CardSides, CardSize, DragState, ExportOptions, ExportResult, FieldDefinition, FieldMapping, FieldPosition, FieldStyle, FieldType, IDCardData, IDCardDesignerProps, IDCardGeneratorProps, IDCardPreviewProps, IDCardTemplate, ResizeState, TemplateStorage, UseFieldMappingReturn, UseIDCardExportReturn, UseIDCardTemplateReturn };
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-id-card-generator",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "A flexible React library for designing, configuring, and generating ID cards with drag-and-drop field positioning",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
|
+
"type": "module",
|
|
6
7
|
"module": "dist/esm/index.js",
|
|
7
8
|
"types": "dist/types/index.d.ts",
|
|
8
9
|
"exports": {
|
|
@@ -10,6 +11,10 @@
|
|
|
10
11
|
"import": "./dist/esm/index.js",
|
|
11
12
|
"require": "./dist/cjs/index.js",
|
|
12
13
|
"types": "./dist/types/index.d.ts"
|
|
14
|
+
},
|
|
15
|
+
"./styles.css": {
|
|
16
|
+
"import": "./dist/esm/styles.css",
|
|
17
|
+
"require": "./dist/cjs/styles.css"
|
|
13
18
|
}
|
|
14
19
|
},
|
|
15
20
|
"files": [
|