@capillarytech/creatives-library 8.0.292-alpha.14 → 8.0.292-alpha.15

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@capillarytech/creatives-library",
3
3
  "author": "meharaj",
4
- "version": "8.0.292-alpha.14",
4
+ "version": "8.0.292-alpha.15",
5
5
  "description": "Capillary creatives ui",
6
6
  "main": "./index.js",
7
7
  "module": "./index.es.js",
@@ -191,7 +191,7 @@ const HTMLEditor = forwardRef(({
191
191
  inAppContent.updateContent(newContent, true);
192
192
  inAppLastAppliedInitialRef.current = { android: newAndroid, ios: newIos };
193
193
  }
194
- }, [initialContent, isEmailVariant, isInAppVariant, emailContent, inAppContent]);
194
+ }, [initialContent, isEmailVariant, isInAppVariant]);
195
195
  // Handle context change for tag API calls
196
196
  // If variant is INAPP, use SMS layout; otherwise use the channel (EMAIL)
197
197
  const handleContextChange = useCallback((contextData) => {
@@ -324,7 +324,7 @@ const HTMLEditor = forwardRef(({
324
324
  : countIssuesBySeverity(validation.getAllIssues()),
325
325
  })
326
326
  ,
327
- }), [validation, currentContent, apiValidationErrors]);
327
+ }), [validation, currentContent, apiValidationErrors]); // Include apiValidationErrors so ref methods return updated counts
328
328
 
329
329
  // Use ref to store callback to avoid infinite loops (callback in deps would cause re-runs)
330
330
  const onValidationChangeRef = useRef(onValidationChange);
@@ -832,5 +832,5 @@ HTMLEditor.defaultProps = {
832
832
  apiValidationErrors: null, // API validation errors from validateLiquidTemplateContent
833
833
  };
834
834
 
835
- // Export with injectIntl - HTMLEditor uses forwardRef internally
835
+ // Export with injectIntl - HTMLEditor now uses forwardRef internally
836
836
  export default injectIntl(HTMLEditor);
@@ -142,13 +142,9 @@ export const InApp = (props) => {
142
142
  const [isHTMLTemplate, setIsHTMLTemplate] = useState(false);
143
143
  // Version to force HTMLEditor remount on layout changes
144
144
  const [htmlEditorContentVersion, setHtmlEditorContentVersion] = useState(0);
145
- // Refs to store latest content (kept in sync in handleHtmlContentChange so Test and Preview reads fresh content in library mode)
145
+ // Refs to store latest content before layout changes
146
146
  const htmlContentAndroidRef = useRef(htmlContentAndroid);
147
147
  const htmlContentIosRef = useRef(htmlContentIos);
148
- useEffect(() => {
149
- htmlContentAndroidRef.current = htmlContentAndroid;
150
- htmlContentIosRef.current = htmlContentIos;
151
- }, [htmlContentAndroid, htmlContentIos]);
152
148
  const [accountId, setAccountId] = useState("");
153
149
  const [accessToken, setAccessToken] = useState("");
154
150
  const [accountName, setAccountName] = useState("");
@@ -176,15 +172,14 @@ export const InApp = (props) => {
176
172
  // TestAndPreviewSlidebox state
177
173
  const [showTestAndPreviewSlidebox, setShowTestAndPreviewSlidebox] = useState(false);
178
174
 
179
- // Get template content for TestAndPreviewSlidebox (same pattern as Mobile Push: read current content for preview)
180
- // State is updated on every keystroke via onContentChange; refs are synced so we read fresh content in library mode too.
175
+ // Get template content for TestAndPreviewSlidebox
176
+ // Returns simple structure with preview fields only
177
+ // Transformation to payload structure happens in prepareTestMessagePayload
178
+ // Reference: Based on getPreviewSection() function (lines 490-530) which prepares content for TemplatePreview
181
179
  const getTemplateContent = useCallback(() => {
182
- const androidMsg = isHTMLTemplate
183
- ? (htmlContentAndroidRef.current ?? htmlContentAndroid ?? '')
184
- : templateMessageAndroid;
185
- const iosMsg = isHTMLTemplate
186
- ? (htmlContentIosRef.current ?? htmlContentIos ?? '')
187
- : templateMessageIos;
180
+ // For HTML template, use HTML editor content so preview stays in sync with typing
181
+ const androidMsg = isHTMLTemplate ? (htmlContentAndroid ?? '') : templateMessageAndroid;
182
+ const iosMsg = isHTMLTemplate ? (htmlContentIos ?? '') : templateMessageIos;
188
183
 
189
184
  // Prepare Android content
190
185
  const androidMediaPreview = {};
@@ -512,11 +507,40 @@ export const InApp = (props) => {
512
507
  }
513
508
  }, [editData.templateDetails || templateData]);
514
509
 
515
- // Extract editor type from defaultData for stable reference
510
+ // Extract editor type: from defaultData (create flow) or derive from template content (edit flow)
516
511
  const editorType = useMemo(() => {
517
- const type = defaultData?.['editor-type'];
518
- return type;
519
- }, [defaultData]);
512
+ const fromDefault = defaultData?.['editor-type'];
513
+ if (fromDefault) return fromDefault;
514
+
515
+ // Edit flow: derive from template content when editor-type wasn't passed from wrapper
516
+ const source = isFullMode ? editData?.templateDetails : templateData;
517
+ const versions = source?.versions;
518
+ const content = get(versions, 'base.content', {});
519
+ if (!content || isEmpty(content)) return undefined;
520
+
521
+ const androidContent = content?.ANDROID;
522
+ const iosContent = content?.IOS;
523
+ const androidTitle = (androidContent?.title ?? '').toString();
524
+ const iosTitle = (iosContent?.title ?? '').toString();
525
+ const androidType = androidContent?.type ?? '';
526
+ const iosType = iosContent?.type ?? '';
527
+ const androidStyle = get(androidContent, 'expandableDetails.style');
528
+ const iosStyle = get(iosContent, 'expandableDetails.style');
529
+ const isBEEeditorAndroid = get(androidContent, 'isBEEeditor');
530
+ const isBEEeditorIos = get(iosContent, 'isBEEeditor');
531
+ const isBeeFreeAndroid = !isEmpty(androidTitle) && androidTitle.toLowerCase() === 'bee free template';
532
+ const isBeeFreeIos = !isEmpty(iosTitle) && iosTitle.toLowerCase() === 'bee free template';
533
+ const isHTMLEditorAndroid = !isEmpty(androidTitle) && androidTitle.toLowerCase() === 'html editor template';
534
+ const isHTMLEditorIos = !isEmpty(iosTitle) && iosTitle.toLowerCase() === 'html editor template';
535
+
536
+ const androidIsHTML = isHTMLEditorAndroid
537
+ || ((androidType === INAPP_MEDIA_TYPES.HTML || androidStyle === BIG_HTML) && !isBEEeditorAndroid && !isBeeFreeAndroid);
538
+ const iosIsHTML = isHTMLEditorIos
539
+ || ((iosType === INAPP_MEDIA_TYPES.HTML || iosStyle === BIG_HTML) && !isBEEeditorIos && !isBeeFreeIos);
540
+
541
+ if (androidIsHTML || iosIsHTML) return INAPP_EDITOR_TYPES.HTML_EDITOR;
542
+ return INAPP_EDITOR_TYPES.DRAG_DROP_EDITOR;
543
+ }, [defaultData, isFullMode, editData?.templateDetails, templateData]);
520
544
 
521
545
  // Separate effect for handling editor type from wrapper in create mode
522
546
  useEffect(() => {
@@ -1013,12 +1037,11 @@ export const InApp = (props) => {
1013
1037
  );
1014
1038
  };
1015
1039
 
1016
- // Handle HTML content changes from HTMLEditor - update state and refs so Test and Preview has fresh content (full + library mode)
1040
+ // Handle HTML content changes from HTMLEditor
1017
1041
  const handleHtmlContentChange = useCallback((deviceContent, changedDevice) => {
1018
1042
  // When "keep content same" is on, useInAppContent passes full deviceContent with both
1019
1043
  // android and ios set to the same value. We must update both states so preview shows
1020
1044
  // the synced content for each device. Otherwise only update the device that changed.
1021
- // Refs are updated synchronously so getTemplateContent() reads latest when opening the slidebox.
1022
1045
 
1023
1046
  // Clear validation errors when content changes (similar to Bee Editor)
1024
1047
  if (changedDevice) {
@@ -1041,36 +1064,33 @@ export const InApp = (props) => {
1041
1064
  const isSyncUpdate = hasAndroid && hasIos;
1042
1065
 
1043
1066
  if (isSyncUpdate) {
1067
+ // Sync mode: update both so preview shows same content for Android and iOS
1044
1068
  if (hasAndroid) {
1045
- const v = deviceContent.android || '';
1046
- htmlContentAndroidRef.current = v;
1047
- setHtmlContentAndroid(v);
1069
+ setHtmlContentAndroid(deviceContent.android || '');
1048
1070
  }
1049
1071
  if (hasIos) {
1050
- const v = deviceContent.ios || '';
1051
- htmlContentIosRef.current = v;
1052
- setHtmlContentIos(v);
1072
+ setHtmlContentIos(deviceContent.ios || '');
1053
1073
  }
1054
1074
  } else if (changedDevice) {
1075
+ // Only one device changed
1055
1076
  if (changedDevice.toUpperCase() === ANDROID && hasAndroid) {
1056
- const v = deviceContent.android || '';
1057
- htmlContentAndroidRef.current = v;
1058
- setHtmlContentAndroid(v);
1077
+ setHtmlContentAndroid(deviceContent.android || '');
1059
1078
  } else if (changedDevice.toUpperCase() === IOS_CAPITAL && hasIos) {
1060
- const v = deviceContent.ios || '';
1061
- htmlContentIosRef.current = v;
1062
- setHtmlContentIos(v);
1079
+ setHtmlContentIos(deviceContent.ios || '');
1063
1080
  }
1064
1081
  } else {
1082
+ // Fallback: update both if changedDevice not provided
1065
1083
  if (hasAndroid) {
1066
- const newValue = deviceContent.android || '';
1067
- htmlContentAndroidRef.current = newValue;
1068
- setHtmlContentAndroid((prev) => (prev !== newValue ? newValue : prev));
1084
+ setHtmlContentAndroid((prev) => {
1085
+ const newValue = deviceContent.android || '';
1086
+ return prev !== newValue ? newValue : prev;
1087
+ });
1069
1088
  }
1070
1089
  if (hasIos) {
1071
- const newValue = deviceContent.ios || '';
1072
- htmlContentIosRef.current = newValue;
1073
- setHtmlContentIos((prev) => (prev !== newValue ? newValue : prev));
1090
+ setHtmlContentIos((prev) => {
1091
+ const newValue = deviceContent.ios || '';
1092
+ return prev !== newValue ? newValue : prev;
1093
+ });
1074
1094
  }
1075
1095
  }
1076
1096
  }, [ANDROID, IOS_CAPITAL, setErrorMessage]);