@openlettermarketing/olc-react-sdk 2.1.6-beta.2 → 2.1.6-beta.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/build/index.js +77 -77
- package/build/index.js.map +1 -1
- package/build/types/src/assets/images/modal-icons/checkbox-checked.d.ts +3 -0
- package/build/types/src/assets/images/modal-icons/checkbox-unchecked.d.ts +3 -0
- package/build/types/src/assets/images/modal-icons/warning.d.ts +3 -0
- package/build/types/src/components/GenericUIBlocks/Dialog/V2/index.d.ts +2 -0
- package/build/types/src/components/GenericUIBlocks/Dialog/index.d.ts +1 -0
- package/build/types/src/components/TopNavigation/FieldValidationModal/index.d.ts +12 -0
- package/build/types/src/utils/message.d.ts +8 -0
- package/build/types/src/utils/template-builder.d.ts +26 -0
- package/build/types/src/utils/templateIdentifierArea/triFold.d.ts +0 -2
- package/build/types/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/assets/images/modal-icons/checkbox-checked.tsx +24 -0
- package/src/assets/images/modal-icons/checkbox-unchecked.tsx +13 -0
- package/src/assets/images/modal-icons/warning.tsx +15 -0
- package/src/components/GenericUIBlocks/Dialog/V2/index.tsx +8 -4
- package/src/components/GenericUIBlocks/Dialog/V2/styles.scss +10 -1
- package/src/components/GenericUIBlocks/Dialog/index.tsx +4 -2
- package/src/components/TopNavigation/FieldValidationModal/index.tsx +116 -0
- package/src/components/TopNavigation/FieldValidationModal/styles.scss +48 -0
- package/src/components/TopNavigation/index.tsx +68 -1
- package/src/utils/message.ts +9 -1
- package/src/utils/products.ts +1 -1
- package/src/utils/template-builder.ts +105 -3
- package/src/utils/templateIdentifierArea/triFold.ts +8 -26
- package/src/utils/templateRestrictedArea/triFold.ts +6 -8
- package/src/utils/templateSafetyBorders/triFold.ts +20 -27
- package/version.js +1 -1
|
@@ -84,10 +84,10 @@ export const selfMailerProduct = {
|
|
|
84
84
|
],
|
|
85
85
|
},
|
|
86
86
|
{
|
|
87
|
-
id: "11", defaultSize: "
|
|
87
|
+
id: "11", defaultSize: "12x9", title: "Self Mailer", productType: "Tri-Fold Self-Mailers", hasEnvelope: false, paper: '80# text', label: '8.5x11',
|
|
88
88
|
finish: 'Glass Coated', size: [{
|
|
89
89
|
id: "11",
|
|
90
|
-
size: "
|
|
90
|
+
size: "12x9",
|
|
91
91
|
label: "8.5x11"
|
|
92
92
|
}]
|
|
93
93
|
},
|
|
@@ -325,4 +325,106 @@ export const isValidQR = (pages: any) => {
|
|
|
325
325
|
}
|
|
326
326
|
}
|
|
327
327
|
return true;
|
|
328
|
-
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Interface for invalid field validation results
|
|
332
|
+
*/
|
|
333
|
+
export interface InvalidField {
|
|
334
|
+
field: string;
|
|
335
|
+
issue: 'INVALID_FORMAT' | 'NOT_UPPERCASE';
|
|
336
|
+
pageIndex: number;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Validates template fields for correct format and capitalization
|
|
341
|
+
* Returns array of invalid fields found in the template
|
|
342
|
+
*
|
|
343
|
+
* @param pages - Template pages array from store.toJSON()
|
|
344
|
+
* @returns Array of objects containing invalid fields and their issues
|
|
345
|
+
*/
|
|
346
|
+
export const validateTemplateFields = (pages: any): InvalidField[] => {
|
|
347
|
+
const invalidFields: InvalidField[] = [];
|
|
348
|
+
|
|
349
|
+
pages.forEach((page: any, pageIndex: number) => {
|
|
350
|
+
page.children?.forEach((child: any) => {
|
|
351
|
+
if (child.type === 'text' && child.text) {
|
|
352
|
+
const text = child.text;
|
|
353
|
+
|
|
354
|
+
// ── Step 1 - Find ALL complete brace expressions: anything from the first { to the last } on the same "group", including spaces inside.
|
|
355
|
+
const completePattern = /\{+[^{}]*\}+/g;
|
|
356
|
+
let match: RegExpExecArray | null;
|
|
357
|
+
|
|
358
|
+
// Track which character ranges are already covered so Steps 2 & 3 - don't double-report sub-strings of a complete match.
|
|
359
|
+
const coveredRanges: Array<[number, number]> = [];
|
|
360
|
+
|
|
361
|
+
const completeExec = new RegExp(completePattern.source, 'g');
|
|
362
|
+
while ((match = completeExec.exec(text)) !== null) {
|
|
363
|
+
coveredRanges.push([match.index, match.index + match[0].length]);
|
|
364
|
+
const token = match[0];
|
|
365
|
+
// Valid: EXACTLY {{UPPERCASE_CONTENT}} — no spaces, no lowercase
|
|
366
|
+
const isValidFormat = /^\{\{[A-Z0-9._]+\}\}$/.test(token);
|
|
367
|
+
|
|
368
|
+
if (!isValidFormat) {
|
|
369
|
+
const content = token.replace(/^\{+|\}+$/g, '');
|
|
370
|
+
const isDoubleBrace = /^\{\{[\s\S]+\}\}$/.test(token);
|
|
371
|
+
const hasOnlyValidChars = /^[A-Za-z0-9._]+$/.test(content);
|
|
372
|
+
if (isDoubleBrace && hasOnlyValidChars && content !== content.toUpperCase()) {
|
|
373
|
+
// e.g. {{c.last_name}} — correct braces but lowercase content
|
|
374
|
+
invalidFields.push({ field: token, issue: 'NOT_UPPERCASE', pageIndex });
|
|
375
|
+
} else {
|
|
376
|
+
invalidFields.push({ field: token, issue: 'INVALID_FORMAT', pageIndex });
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// Helper: returns true if the character at `idx` is inside a covered range
|
|
382
|
+
const isCovered = (idx: number): boolean =>
|
|
383
|
+
coveredRanges.some(([s, e]) => idx >= s && idx < e);
|
|
384
|
+
|
|
385
|
+
// ── Step 2 ─ Find incomplete patterns that have opening brace(s) but NO closing brace.e.g. "{C.LAST_NAME" or "{{C.LAST_NAME" at end of text.
|
|
386
|
+
const missingClosingExec = /\{+[^{}]*/g;
|
|
387
|
+
while ((match = missingClosingExec.exec(text)) !== null) {
|
|
388
|
+
if (!isCovered(match.index) && match[0].trim().length > 0) {
|
|
389
|
+
invalidFields.push({ field: match[0], issue: 'INVALID_FORMAT', pageIndex });
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// ── Step 3 ─ Find incomplete patterns that have closing brace(s) but NO opening brace. e.g. "C.LAST_NAME}" or "C.LAST_NAME}}".
|
|
394
|
+
const missingOpeningExec = /(?<!\{)[A-Z0-9][A-Z0-9._\s]*\}+/g;
|
|
395
|
+
while ((match = missingOpeningExec.exec(text)) !== null) {
|
|
396
|
+
if (!isCovered(match.index) && match[0].trim().length > 0) {
|
|
397
|
+
invalidFields.push({ field: match[0].trim(), issue: 'INVALID_FORMAT', pageIndex });
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
// Remove duplicates
|
|
405
|
+
const uniqueFields = invalidFields.filter((item: InvalidField, index: number, self: InvalidField[]) =>
|
|
406
|
+
index === self.findIndex((t: InvalidField) => t.field === item.field && t.issue === item.issue)
|
|
407
|
+
);
|
|
408
|
+
|
|
409
|
+
return uniqueFields;
|
|
410
|
+
};
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Validates that all dynamic field tokens used in the template exist in the allowed keys list.
|
|
414
|
+
* Scans the entire serialized template JSON for {{...}} patterns and returns any tokens
|
|
415
|
+
* that are not present in the provided allowedKeys list.
|
|
416
|
+
*
|
|
417
|
+
* @param templateJSON - Full template JSON object from store.toJSON()
|
|
418
|
+
* @param allowedKeys - Array of allowed {{...}} token strings (predefined + custom fields)
|
|
419
|
+
* @returns Array of unrecognized token strings; empty array means all fields are valid
|
|
420
|
+
*/
|
|
421
|
+
export const validateAllowedTemplateFields = (
|
|
422
|
+
templateJSON: any,
|
|
423
|
+
allowedKeys: string[]
|
|
424
|
+
): string[] => {
|
|
425
|
+
const templateStr = JSON.stringify(templateJSON);
|
|
426
|
+
const pattern = /\{\{[^{}]+\}\}/g;
|
|
427
|
+
const matches = templateStr.match(pattern) || [];
|
|
428
|
+
const unique = Array.from(new Set(matches));
|
|
429
|
+
return unique.filter(token => !allowedKeys.includes(token));
|
|
430
|
+
};
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { DPI } from "../constants";
|
|
2
|
-
|
|
3
1
|
// Define the type for the element being added
|
|
4
2
|
interface Element {
|
|
5
3
|
id: string;
|
|
@@ -45,8 +43,6 @@ interface Page {
|
|
|
45
43
|
|
|
46
44
|
// Define the type for the store
|
|
47
45
|
interface Store {
|
|
48
|
-
width: number;
|
|
49
|
-
height: number;
|
|
50
46
|
pages: Page[];
|
|
51
47
|
history: {
|
|
52
48
|
clear: () => void;
|
|
@@ -94,30 +90,16 @@ const createTextElement = (
|
|
|
94
90
|
|
|
95
91
|
export const addIdentifierAreaToTriFold = (store: Store): void => {
|
|
96
92
|
const page = store.pages[0];
|
|
97
|
-
const foldSectionHeight = store.height / 3;
|
|
98
|
-
const restrictedAreaHeight = 2.375 * DPI;
|
|
99
|
-
const restrictedAreaY = store.height - restrictedAreaHeight - 0.125 * DPI - foldSectionHeight;
|
|
100
|
-
const identifierY = restrictedAreaY + restrictedAreaHeight - 12;
|
|
101
|
-
|
|
102
|
-
// Keep the original right-side alignment behavior, but make it responsive to page width.
|
|
103
|
-
const contPlaceholderX = store.width - 185;
|
|
104
|
-
const contIdX = store.width - 177;
|
|
105
|
-
const sequencePlaceholderX = store.width - 149;
|
|
106
|
-
const sequenceX = store.width - 140;
|
|
107
|
-
const templatePlaceholderX = store.width - 114;
|
|
108
|
-
const templateIdX = store.width - 101.4;
|
|
109
|
-
const orderPlaceholderX = store.width - 72.4;
|
|
110
|
-
const orderIdX = store.width - 61.4;
|
|
111
93
|
|
|
112
94
|
const elements: Element[] = [
|
|
113
|
-
createTextElement("cont-id-placeholder", "C:",
|
|
114
|
-
createTextElement("contId", "0000001",
|
|
115
|
-
createTextElement("sequence-id-placeholder", "| S:",
|
|
116
|
-
createTextElement("sequence", "0000001",
|
|
117
|
-
createTextElement("template-id-placeholder", "| T:",
|
|
118
|
-
createTextElement("templateId", "0001034",
|
|
119
|
-
createTextElement("order-id-placeholder", "| O:",
|
|
120
|
-
createTextElement("orderId", "0000127",
|
|
95
|
+
createTextElement("cont-id-placeholder", "C:", 679, 739, 11),
|
|
96
|
+
createTextElement("contId", "0000001", 687, 739, 30),
|
|
97
|
+
createTextElement("sequence-id-placeholder", "| S:", 715, 739, 12),
|
|
98
|
+
createTextElement("sequence", "0000001", 724, 739, 29),
|
|
99
|
+
createTextElement("template-id-placeholder", "| T:", 750, 739, 14),
|
|
100
|
+
createTextElement("templateId", "0001034", 762.6, 739, 29),
|
|
101
|
+
createTextElement("order-id-placeholder", "| O:", 791.6, 739, 11),
|
|
102
|
+
createTextElement("orderId", "0000127", 802.6, 739, 29),
|
|
121
103
|
];
|
|
122
104
|
|
|
123
105
|
elements.forEach(element => page.addElement(element));
|
|
@@ -85,8 +85,6 @@ interface Store {
|
|
|
85
85
|
|
|
86
86
|
export const addRestrictedAreaToTriFold = (store: Store, size: [number, number], barcodeSrc: string): void => {
|
|
87
87
|
const page = store.pages[0];
|
|
88
|
-
const foldSectionHeight = store.height / 3;
|
|
89
|
-
const indiciaLeftShift = 8;
|
|
90
88
|
|
|
91
89
|
const elements: Element[] = [
|
|
92
90
|
{
|
|
@@ -100,7 +98,7 @@ export const addRestrictedAreaToTriFold = (store: Store, size: [number, number],
|
|
|
100
98
|
alwaysOnTop: true,
|
|
101
99
|
showInExport: true,
|
|
102
100
|
x: store.width - size[0] * DPI - 0.15 * DPI,
|
|
103
|
-
y: store.height - size[1] * DPI - 0.125 * DPI -
|
|
101
|
+
y: store.height - size[1] * DPI - 0.125 * DPI - 4 * DPI,
|
|
104
102
|
width: size[0] * DPI,
|
|
105
103
|
height: size[1] * DPI,
|
|
106
104
|
rotation: 0,
|
|
@@ -139,7 +137,7 @@ export const addRestrictedAreaToTriFold = (store: Store, size: [number, number],
|
|
|
139
137
|
alwaysOnTop: true,
|
|
140
138
|
showInExport: true,
|
|
141
139
|
x: store.width - size[0] * DPI - 0.15 * DPI + 5,
|
|
142
|
-
y: store.height - size[1] * DPI - 0.125 * DPI + 20 -
|
|
140
|
+
y: store.height - size[1] * DPI - 0.125 * DPI + 20 - 4 * DPI,
|
|
143
141
|
width: 240,
|
|
144
142
|
height: 20,
|
|
145
143
|
rotation: 0,
|
|
@@ -190,8 +188,8 @@ export const addRestrictedAreaToTriFold = (store: Store, size: [number, number],
|
|
|
190
188
|
removable: false,
|
|
191
189
|
alwaysOnTop: true,
|
|
192
190
|
showInExport: true,
|
|
193
|
-
x: store.width - 111 - 0.15 * DPI
|
|
194
|
-
y: store.height - size[1] * DPI + 10 -
|
|
191
|
+
x: store.width - 111 - 0.15 * DPI,
|
|
192
|
+
y: store.height - size[1] * DPI + 10 - 4 * DPI,
|
|
195
193
|
width: 111,
|
|
196
194
|
height: 40,
|
|
197
195
|
rotation: 0,
|
|
@@ -242,7 +240,7 @@ export const addRestrictedAreaToTriFold = (store: Store, size: [number, number],
|
|
|
242
240
|
removable: false,
|
|
243
241
|
alwaysOnTop: true,
|
|
244
242
|
showInExport: true,
|
|
245
|
-
y: store.height - 28 - size[1] * DPI + 100 -
|
|
243
|
+
y: store.height - 28 - size[1] * DPI + 100 - 4 * DPI,
|
|
246
244
|
x: store.width - size[0] * DPI - 0.15 * DPI + 5,
|
|
247
245
|
width: size[0] * DPI - 23,
|
|
248
246
|
height: 15,
|
|
@@ -284,7 +282,7 @@ export const addRestrictedAreaToTriFold = (store: Store, size: [number, number],
|
|
|
284
282
|
alwaysOnTop: true,
|
|
285
283
|
showInExport: true,
|
|
286
284
|
x: store.width - size[0] * DPI - 0.15 * DPI + 5,
|
|
287
|
-
y: store.height - size[1] * DPI - 0.125 * DPI + 120 -
|
|
285
|
+
y: store.height - size[1] * DPI - 0.125 * DPI + 120 - 4 * DPI,
|
|
288
286
|
width: 240,
|
|
289
287
|
height: 20,
|
|
290
288
|
rotation: 0,
|
|
@@ -3,13 +3,6 @@ import { Element, Store } from "./types"
|
|
|
3
3
|
|
|
4
4
|
export const addSafetyBordersToTriFold = (store: Store): void => {
|
|
5
5
|
const randomizedId = Math.random().toString(36).substring(2, 7);
|
|
6
|
-
const borderWidth = store.width + 2;
|
|
7
|
-
const borderHeight = store.height - 52;
|
|
8
|
-
const foldSectionHeight = store.height / 3;
|
|
9
|
-
const foldLineOneY = foldSectionHeight;
|
|
10
|
-
const foldLineTwoY = foldSectionHeight * 2 - 5;
|
|
11
|
-
const borderBottomY = store.height - 28.4;
|
|
12
|
-
const rightBorderX = store.width - 29;
|
|
13
6
|
|
|
14
7
|
const safetyBordersTextFirst = createSafetyTextElement(
|
|
15
8
|
`safety-text-1-${randomizedId}`,
|
|
@@ -22,8 +15,8 @@ export const addSafetyBordersToTriFold = (store: Store): void => {
|
|
|
22
15
|
const safetyLineTextFirst = createSafetyTextElement(
|
|
23
16
|
`safety-line-1-${randomizedId}`,
|
|
24
17
|
-2,
|
|
25
|
-
|
|
26
|
-
|
|
18
|
+
366,
|
|
19
|
+
866,
|
|
27
20
|
"Fold Line",
|
|
28
21
|
0
|
|
29
22
|
);
|
|
@@ -31,8 +24,8 @@ export const addSafetyBordersToTriFold = (store: Store): void => {
|
|
|
31
24
|
const safetySecondLineTextFirst = createSafetyTextElement(
|
|
32
25
|
`safety-line-2-${randomizedId}`,
|
|
33
26
|
-2,
|
|
34
|
-
|
|
35
|
-
|
|
27
|
+
744,
|
|
28
|
+
866,
|
|
36
29
|
"Fold Line",
|
|
37
30
|
0
|
|
38
31
|
);
|
|
@@ -47,12 +40,12 @@ export const addSafetyBordersToTriFold = (store: Store): void => {
|
|
|
47
40
|
alwaysOnTop: true,
|
|
48
41
|
showInExport: false,
|
|
49
42
|
children: [
|
|
50
|
-
createBorder(`top-1-${randomizedId}`, 26, 23.5,
|
|
51
|
-
createBorder(`bottom-1-${randomizedId}`, 26,
|
|
52
|
-
createBorder(`left-1-${randomizedId}`, 24.16,
|
|
53
|
-
createBorder(`right-1-${randomizedId}`,
|
|
54
|
-
createBorder(`fold-line-1-${randomizedId}`,
|
|
55
|
-
createBorder(`fold-line-2-${randomizedId}`,
|
|
43
|
+
createBorder(`top-1-${randomizedId}`, 26, 23.5, 811, 4, 0),
|
|
44
|
+
createBorder(`bottom-1-${randomizedId}`, 26, 1123.6, 811, 4, 0),
|
|
45
|
+
createBorder(`left-1-${randomizedId}`, 24.16, 1125, 1100, 4, -90),
|
|
46
|
+
createBorder(`right-1-${randomizedId}`, 835, 1125, 1100, 4, -90),
|
|
47
|
+
createBorder(`fold-line-1-${randomizedId}`, 866, 384, 866, 2, 180, 'rgba(208,2,27,1)'),
|
|
48
|
+
createBorder(`fold-line-2-${randomizedId}`, 866, 763, 866, 2, 180, 'rgba(208,2,27,1)'),
|
|
56
49
|
],
|
|
57
50
|
};
|
|
58
51
|
|
|
@@ -67,8 +60,8 @@ export const addSafetyBordersToTriFold = (store: Store): void => {
|
|
|
67
60
|
const safetyLineTextSecond = createSafetyTextElement(
|
|
68
61
|
`safety-line-2-1-${randomizedId}`,
|
|
69
62
|
-2,
|
|
70
|
-
|
|
71
|
-
|
|
63
|
+
366,
|
|
64
|
+
866,
|
|
72
65
|
"Fold Line",
|
|
73
66
|
0
|
|
74
67
|
);
|
|
@@ -76,8 +69,8 @@ export const addSafetyBordersToTriFold = (store: Store): void => {
|
|
|
76
69
|
const safetySecondLineTextSecond = createSafetyTextElement(
|
|
77
70
|
`safety-line-2-2-${randomizedId}`,
|
|
78
71
|
-2,
|
|
79
|
-
|
|
80
|
-
|
|
72
|
+
744,
|
|
73
|
+
866,
|
|
81
74
|
"Fold Line",
|
|
82
75
|
0
|
|
83
76
|
);
|
|
@@ -93,12 +86,12 @@ export const addSafetyBordersToTriFold = (store: Store): void => {
|
|
|
93
86
|
alwaysOnTop: true,
|
|
94
87
|
showInExport: false,
|
|
95
88
|
children: [
|
|
96
|
-
createBorder(`top-2-${randomizedId}`, 26, 23.5,
|
|
97
|
-
createBorder(`bottom-2-${randomizedId}`, 26,
|
|
98
|
-
createBorder(`left-2-${randomizedId}`, 24.16,
|
|
99
|
-
createBorder(`right-2-${randomizedId}`,
|
|
100
|
-
createBorder(`fold-line-2-1-${randomizedId}`,
|
|
101
|
-
createBorder(`fold-line-2-2-${randomizedId}`,
|
|
89
|
+
createBorder(`top-2-${randomizedId}`, 26, 23.5, 811, 4, 0),
|
|
90
|
+
createBorder(`bottom-2-${randomizedId}`, 26, 1123.6, 811, 4, 0),
|
|
91
|
+
createBorder(`left-2-${randomizedId}`, 24.16, 1125, 1100, 4, -90),
|
|
92
|
+
createBorder(`right-2-${randomizedId}`, 835, 1125, 1100, 4, -90),
|
|
93
|
+
createBorder(`fold-line-2-1-${randomizedId}`, 866, 384, 866, 2, 180, 'rgba(208,2,27,1)'),
|
|
94
|
+
createBorder(`fold-line-2-2-${randomizedId}`, 866, 763, 866, 2, 180, 'rgba(208,2,27,1)'),
|
|
102
95
|
],
|
|
103
96
|
};
|
|
104
97
|
|
package/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const SDK_VERSION = '2.1.6-beta.
|
|
1
|
+
export const SDK_VERSION = '2.1.6-beta.4';
|