@openlettermarketing/olc-react-sdk 2.1.6-beta.3 → 2.1.6-beta.5

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.
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ declare const CheckboxChecked: (props: any) => React.JSX.Element;
3
+ export default CheckboxChecked;
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ declare const CheckboxUnchecked: (props: any) => React.JSX.Element;
3
+ export default CheckboxUnchecked;
@@ -18,6 +18,7 @@ interface DialogProps {
18
18
  currentTheme?: string | null | undefined;
19
19
  isQRCode?: boolean;
20
20
  hideButtons?: boolean;
21
+ submitDisabled?: boolean;
21
22
  }
22
23
  declare const DialogV2: React.FC<DialogProps>;
23
24
  export default DialogV2;
@@ -16,6 +16,7 @@ interface DialogProps {
16
16
  children?: ReactNode;
17
17
  isGallery?: boolean;
18
18
  currentTheme?: string | null | undefined;
19
+ submitDisabled?: boolean;
19
20
  }
20
21
  declare const Dialog: React.FC<DialogProps>;
21
22
  export default Dialog;
@@ -6,7 +6,7 @@ interface FieldValidationModalProps {
6
6
  currentTheme?: string | null | undefined;
7
7
  loading?: boolean;
8
8
  handleClose: () => void;
9
- handleContinue: () => void;
9
+ handleContinue: (acknowledged: boolean) => void;
10
10
  }
11
11
  declare const FieldValidationModal: React.FC<FieldValidationModalProps>;
12
12
  export default FieldValidationModal;
@@ -139,7 +139,9 @@ export declare const MESSAGES: {
139
139
  readonly FIELD_VALIDATION: {
140
140
  readonly TITLE: "Invalid Fields";
141
141
  readonly HEADING: "The following fields are not recognized";
142
- readonly DESCRIPTION: (fieldNames: string) => string;
142
+ readonly DESCRIPTION: "The following field(s) used in this template are not recognized by the system. You can save the template as is, but these fields will not populate with data. To resolve this, remove or replace them with valid field names.";
143
+ readonly LIST_REGION_LABEL: "Unrecognized template fields";
144
+ readonly ACKNOWLEDGE_LABEL: "I understand that saving now will preserve these invalid fields, but they will not be populated with data.";
143
145
  readonly CONTINUE_BUTTON: "Continue Saving";
144
146
  readonly CANCEL_BUTTON: "Cancel";
145
147
  };
@@ -1 +1 @@
1
- export const SDK_VERSION: "2.1.6-beta.3";
1
+ export const SDK_VERSION: "2.1.6-beta.5";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@openlettermarketing/olc-react-sdk",
3
3
  "private": false,
4
- "version": "2.1.6-beta.3",
4
+ "version": "2.1.6-beta.5",
5
5
  "type": "module",
6
6
  "description": "Simplify template builder integration for any product.",
7
7
  "main": "build/index.js",
@@ -0,0 +1,24 @@
1
+ import React from 'react';
2
+
3
+ const CheckboxChecked = (props: any) => {
4
+ const { fill = 'var(--primary-color)' } = props;
5
+
6
+ return (
7
+ <svg width="18" height="18" viewBox="0 0 14 15" fill="none" xmlns="http://www.w3.org/2000/svg">
8
+ <rect y="0.5" width="14" height="14" rx="2" fill={fill} />
9
+ <g clipPath="url(#clip0_checkbox_checked)">
10
+ <path
11
+ d="M11.7909 4.97078C11.5124 4.69194 11.0602 4.69212 10.7814 4.97078L6.23808 9.51428L4.21877 7.49498C3.93994 7.21615 3.48796 7.21615 3.20912 7.49498C2.93029 7.77381 2.93029 8.2258 3.20912 8.50463L5.73315 11.0287C5.87248 11.168 6.05518 11.2378 6.23789 11.2378C6.4206 11.2378 6.60347 11.1682 6.7428 11.0287L11.7909 5.98041C12.0697 5.70177 12.0697 5.24959 11.7909 4.97078Z"
12
+ fill="white"
13
+ />
14
+ </g>
15
+ <defs>
16
+ <clipPath id="clip0_checkbox_checked">
17
+ <rect width="9" height="9" fill="white" transform="translate(3 3.5)" />
18
+ </clipPath>
19
+ </defs>
20
+ </svg>
21
+ );
22
+ };
23
+
24
+ export default CheckboxChecked;
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+
3
+ const CheckboxUnchecked = (props: any) => {
4
+ const { stroke = '#303030' } = props;
5
+
6
+ return (
7
+ <svg width="18" height="18" viewBox="0 0 14 15" fill="none" xmlns="http://www.w3.org/2000/svg">
8
+ <rect x="0.25" y="0.75" width="13.5" height="13.5" rx="1.75" stroke={stroke} strokeWidth="0.5" />
9
+ </svg>
10
+ );
11
+ };
12
+
13
+ export default CheckboxUnchecked;
@@ -28,6 +28,7 @@ interface DialogProps {
28
28
  currentTheme?: string | null | undefined;
29
29
  isQRCode?: boolean;
30
30
  hideButtons?: boolean;
31
+ submitDisabled?: boolean;
31
32
  }
32
33
 
33
34
  const buttonStyles: CSSProperties = {
@@ -82,7 +83,8 @@ const DialogV2: React.FC<DialogProps> = ({
82
83
  isGallery = false,
83
84
  currentTheme = "default",
84
85
  isQRCode = false,
85
- hideButtons = false
86
+ hideButtons = false,
87
+ submitDisabled = false,
86
88
  }) => {
87
89
  const contentAdjust = submitText.length > 6 ? "fit-content" : "100px";
88
90
 
@@ -164,7 +166,7 @@ const DialogV2: React.FC<DialogProps> = ({
164
166
  <div className="modal-footer">
165
167
  {(!isGallery || isQRCode) &&
166
168
  <>
167
- <button onClick={onSubmit} disabled={loading}>
169
+ <button onClick={onSubmit} disabled={loading || submitDisabled}>
168
170
  {loading ? <CircularProgress style={progressStyles} /> : submitText}
169
171
  </button>
170
172
  <button onClick={onCancel}>
@@ -208,7 +210,7 @@ const DialogV2: React.FC<DialogProps> = ({
208
210
  <div className="confirm-modal-footer">
209
211
  {!isGallery && !hideButtons &&
210
212
  <>
211
- <button onClick={onSubmit} disabled={loading}>
213
+ <button onClick={onSubmit} disabled={loading || submitDisabled}>
212
214
  {loading ? <CircularProgress style={progressStyles} /> : submitText}
213
215
  </button>
214
216
  <button onClick={onCancel}>
@@ -249,9 +249,14 @@
249
249
  justify-content: center;
250
250
  align-items: center;
251
251
 
252
- &:hover{
252
+ &:hover:not(:disabled){
253
253
  background-color: var(--primary-color-btn-hover);
254
254
  }
255
+
256
+ &:disabled{
257
+ opacity: 0.45;
258
+ cursor: not-allowed;
259
+ }
255
260
  }
256
261
 
257
262
  &:last-child{
@@ -28,6 +28,7 @@ interface DialogProps {
28
28
  children?: ReactNode;
29
29
  isGallery?: boolean;
30
30
  currentTheme?: string | null | undefined;
31
+ submitDisabled?: boolean;
31
32
  }
32
33
 
33
34
  const buttonStyles: CSSProperties = {
@@ -73,7 +74,8 @@ const Dialog: React.FC<DialogProps> = ({
73
74
  submitText = "",
74
75
  children = [],
75
76
  isGallery = false,
76
- currentTheme = "default"
77
+ currentTheme = "default",
78
+ submitDisabled = false,
77
79
  }) => {
78
80
  const contentAdjust = submitText.length > 6 ? "fit-content" : "100px";
79
81
 
@@ -170,7 +172,7 @@ const Dialog: React.FC<DialogProps> = ({
170
172
  <Button
171
173
  style={{ ...buttonStyles, border: 'none', maxWidth: contentAdjust }}
172
174
  onClick={onSubmit}
173
- disabled={loading}
175
+ disabled={loading || submitDisabled}
174
176
  >
175
177
  {loading ? <CircularProgress style={progressStyles} /> : submitText}
176
178
  </Button>
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { useState, useEffect } from 'react';
2
2
 
3
3
  // Utils
4
4
  import { MESSAGES } from '../../../utils/message';
@@ -9,6 +9,10 @@ import DialogV2 from '../../GenericUIBlocks/Dialog/V2';
9
9
 
10
10
  // Icons
11
11
  import Warning from '../../../assets/images/modal-icons/warning';
12
+ // @ts-ignore
13
+ import CheckboxChecked from '../../../assets/images/modal-icons/checkbox-checked';
14
+ // @ts-ignore
15
+ import CheckboxUnchecked from '../../../assets/images/modal-icons/checkbox-unchecked';
12
16
 
13
17
  // Styles
14
18
  import './styles.scss';
@@ -19,7 +23,7 @@ interface FieldValidationModalProps {
19
23
  currentTheme?: string | null | undefined;
20
24
  loading?: boolean;
21
25
  handleClose: () => void;
22
- handleContinue: () => void;
26
+ handleContinue: (acknowledged: boolean) => void;
23
27
  }
24
28
 
25
29
  const modalStyles = {
@@ -41,8 +45,43 @@ const FieldValidationModal: React.FC<FieldValidationModalProps> = ({
41
45
  handleClose,
42
46
  handleContinue,
43
47
  }) => {
44
- const fieldNames = [...invalidFields].map(item => `"${item}"`).join(', ');
45
- const description = MESSAGES.TEMPLATE.FIELD_VALIDATION.DESCRIPTION(fieldNames);
48
+ const [acknowledged, setAcknowledged] = useState(false);
49
+
50
+ // Reset checkbox whenever the modal opens with a new set of fields
51
+ useEffect(() => {
52
+ if (open) {
53
+ setAcknowledged(false);
54
+ }
55
+ }, [open]);
56
+
57
+ const content = (
58
+ <div className="field-validation-content">
59
+ <p className="field-validation-description">
60
+ {MESSAGES.TEMPLATE.FIELD_VALIDATION.DESCRIPTION}
61
+ </p>
62
+ <div
63
+ className="field-validation-list-scroll"
64
+ role="region"
65
+ aria-label={MESSAGES.TEMPLATE.FIELD_VALIDATION.LIST_REGION_LABEL}
66
+ >
67
+ <ul className="field-validation-list">
68
+ {invalidFields.map((field, index) => (
69
+ <li key={`${field}-${index}`}>
70
+ <span className="field-validation-list-index">{index + 1}.</span>
71
+ <span className="field-validation-list-text">{field}</span>
72
+ </li>
73
+ ))}
74
+ </ul>
75
+ </div>
76
+ <label
77
+ className="field-validation-acknowledge"
78
+ onClick={() => setAcknowledged((prev) => !prev)}
79
+ >
80
+ {acknowledged ? <CheckboxChecked /> : <CheckboxUnchecked />}
81
+ {MESSAGES.TEMPLATE.FIELD_VALIDATION.ACKNOWLEDGE_LABEL}
82
+ </label>
83
+ </div>
84
+ );
46
85
 
47
86
  return currentTheme === 'v2' ? (
48
87
  <DialogV2
@@ -53,14 +92,16 @@ const FieldValidationModal: React.FC<FieldValidationModalProps> = ({
53
92
  handleClose={handleClose}
54
93
  title={MESSAGES.TEMPLATE.FIELD_VALIDATION.TITLE}
55
94
  subHeading=""
56
- description={description}
57
95
  currentTheme="v2"
58
96
  isGallery={false}
59
- onSubmit={handleContinue}
97
+ onSubmit={() => handleContinue(acknowledged)}
60
98
  submitText={MESSAGES.TEMPLATE.FIELD_VALIDATION.CONTINUE_BUTTON}
99
+ submitDisabled={!acknowledged}
61
100
  onCancel={handleClose}
62
101
  cancelText={MESSAGES.TEMPLATE.FIELD_VALIDATION.CANCEL_BUTTON}
63
- />
102
+ >
103
+ {content}
104
+ </DialogV2>
64
105
  ) : (
65
106
  <Dialog
66
107
  icon={<Warning fill="var(--primary-color)" />}
@@ -70,12 +111,14 @@ const FieldValidationModal: React.FC<FieldValidationModalProps> = ({
70
111
  handleClose={handleClose}
71
112
  title={MESSAGES.TEMPLATE.FIELD_VALIDATION.TITLE}
72
113
  subHeading=""
73
- description={description}
74
- onSubmit={handleContinue}
114
+ onSubmit={() => handleContinue(acknowledged)}
75
115
  submitText={MESSAGES.TEMPLATE.FIELD_VALIDATION.CONTINUE_BUTTON}
116
+ submitDisabled={!acknowledged}
76
117
  onCancel={handleClose}
77
118
  cancelText={MESSAGES.TEMPLATE.FIELD_VALIDATION.CANCEL_BUTTON}
78
- />
119
+ >
120
+ {content}
121
+ </Dialog>
79
122
  );
80
123
  };
81
124
 
@@ -1,39 +1,94 @@
1
1
  .field-validation-content {
2
- margin-top: 20px;
2
+ width: 100%;
3
+ margin-top: 12px;
4
+ text-align: left;
3
5
  }
4
6
 
5
- .field-validation-list {
6
- max-height: 300px;
7
- overflow-y: auto;
8
- padding: 10px;
9
- background-color: #f9f9f9;
10
- border-radius: 4px;
7
+ .field-validation-description {
8
+ font-size: 16px;
9
+ font-weight: 400;
10
+ color: var(--text-color);
11
+ line-height: 20px;
12
+ font-family: var(--font-family);
13
+ margin: 0 0 12px 0;
14
+ padding: 0;
11
15
  }
12
16
 
13
- .field-validation-item {
14
- margin-bottom: 15px;
15
- padding: 12px;
16
- background-color: #fff;
17
- border-left: 3px solid #ff9800;
18
- border-radius: 4px;
19
-
20
- .field-name {
21
- font-weight: 600;
22
- color: #333;
23
- margin-bottom: 5px;
24
- font-family: 'Courier New', monospace;
25
- font-size: 14px;
17
+ // Scroll only the list; keep markers visible for 10+ (outside markers need horizontal room —
18
+ // overflow-x: hidden was clipping two-digit list numbers to "0", "1", "2").
19
+ .field-validation-list-scroll {
20
+ max-height: min(40vh, 280px);
21
+ overflow-y: auto;
22
+ overscroll-behavior: contain;
23
+ margin: 0 0 16px 0;
24
+ padding-right: 6px;
25
+ padding-left: 4px;
26
+ box-sizing: border-box;
27
+
28
+ // Match the SDK-wide scrollbar (same variables used in .builder-wrapper and Polotno panels)
29
+ scrollbar-width: thin;
30
+ scrollbar-color: var(--scrollbar-thumb-color) var(--scrollbar-track-color);
31
+
32
+ &::-webkit-scrollbar {
33
+ width: 10px;
26
34
  }
27
-
28
- .field-error {
29
- color: #666;
30
- font-size: 13px;
31
- margin-bottom: 4px;
35
+
36
+ &::-webkit-scrollbar-track {
37
+ background: var(--scrollbar-track-color);
38
+ border-radius: 3px;
39
+ }
40
+
41
+ &::-webkit-scrollbar-thumb {
42
+ background: var(--scrollbar-thumb-color);
43
+ border-radius: 3px;
44
+ }
45
+ }
46
+
47
+ .field-validation-list {
48
+ margin: 0;
49
+ padding: 0;
50
+ list-style: none;
51
+
52
+ li {
53
+ display: flex;
54
+ gap: 6px;
55
+ align-items: flex-start;
56
+ font-size: 16px;
57
+ font-weight: 400;
58
+ color: var(--text-color);
59
+ line-height: 20px;
60
+ margin-bottom: 6px;
61
+ font-family: var(--font-family);
32
62
  }
33
-
34
- .field-location {
35
- color: #999;
36
- font-size: 12px;
37
- font-style: italic;
63
+ }
64
+
65
+ .field-validation-list-index {
66
+ flex-shrink: 0;
67
+ min-width: 1.75rem;
68
+ text-align: right;
69
+ font-variant-numeric: tabular-nums;
70
+ }
71
+
72
+ .field-validation-list-text {
73
+ flex: 1;
74
+ min-width: 0;
75
+ word-break: break-all;
76
+ }
77
+
78
+ .field-validation-acknowledge {
79
+ display: flex;
80
+ align-items: flex-start;
81
+ gap: 8px;
82
+ font-size: 16px;
83
+ font-weight: 400;
84
+ color: var(--text-color);
85
+ line-height: 20px;
86
+ cursor: pointer;
87
+ user-select: none;
88
+ font-family: var(--font-family);
89
+
90
+ svg {
91
+ flex-shrink: 0;
92
+ margin-top: 1px;
38
93
  }
39
94
  }
@@ -430,9 +430,14 @@ const TopNavigation: React.FC<TopNavigationProps> = ({
430
430
  }
431
431
  };
432
432
 
433
- const handleSave = async () => {
433
+ const handleSave = async (
434
+ hasFieldsWarnings: boolean = false,
435
+ fieldsWarningsAccepted: boolean = false
436
+ ) => {
434
437
  try {
435
438
  const formData = new FormData();
439
+ formData.append('has_fields_warnings', String(hasFieldsWarnings));
440
+ formData.append('fields_warnings_accepted', String(fieldsWarningsAccepted));
436
441
  const allFields = [
437
442
  ...defaultFields,
438
443
  ...customFields,
@@ -576,9 +581,9 @@ const TopNavigation: React.FC<TopNavigationProps> = ({
576
581
  }
577
582
  };
578
583
 
579
- const handleContinueAnyway = () => {
584
+ const handleContinueAnyway = (acknowledged: boolean) => {
580
585
  setIsShowModel((prev) => ({ ...prev, loading: true }));
581
- handleSave();
586
+ handleSave(true, acknowledged);
582
587
  };
583
588
 
584
589
  const handleChangeModel = (
@@ -146,7 +146,9 @@ export const MESSAGES = {
146
146
  FIELD_VALIDATION: {
147
147
  TITLE: "Invalid Fields",
148
148
  HEADING: "The following fields are not recognized",
149
- DESCRIPTION: (fieldNames: string) => `The following field(s) ${fieldNames} are not recognized.`,
149
+ DESCRIPTION: "The following field(s) used in this template are not recognized by the system. You can save the template as is, but these fields will not populate with data. To resolve this, remove or replace them with valid field names.",
150
+ LIST_REGION_LABEL: "Unrecognized template fields",
151
+ ACKNOWLEDGE_LABEL: "I understand that saving now will preserve these invalid fields, but they will not be populated with data.",
150
152
  CONTINUE_BUTTON: "Continue Saving",
151
153
  CANCEL_BUTTON: "Cancel",
152
154
  },
package/version.js CHANGED
@@ -1 +1 @@
1
- export const SDK_VERSION = '2.1.6-beta.3';
1
+ export const SDK_VERSION = '2.1.6-beta.5';