@capillarytech/creatives-library 8.0.235 → 8.0.236-alpha.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.
Files changed (86) hide show
  1. package/assets/Android.png +0 -0
  2. package/assets/iOS.png +0 -0
  3. package/config/app.js +0 -1
  4. package/constants/unified.js +1 -1
  5. package/initialReducer.js +2 -0
  6. package/package.json +1 -1
  7. package/services/api.js +5 -2
  8. package/services/tests/api.test.js +18 -0
  9. package/utils/common.js +1 -2
  10. package/utils/commonUtils.js +14 -1
  11. package/utils/transformTemplateConfig.js +0 -10
  12. package/v2Components/CapDeviceContent/index.js +61 -56
  13. package/v2Components/CapTagList/index.js +4 -0
  14. package/v2Components/CapWhatsappCTA/tests/index.test.js +5 -0
  15. package/v2Components/HtmlEditor/HTMLEditor.js +165 -80
  16. package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +532 -0
  17. package/v2Components/HtmlEditor/__tests__/index.lazy.test.js +17 -12
  18. package/v2Components/HtmlEditor/_htmlEditor.scss +0 -4
  19. package/v2Components/HtmlEditor/_index.lazy.scss +0 -1
  20. package/v2Components/HtmlEditor/components/CodeEditorPane/_codeEditorPane.scss +0 -98
  21. package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +125 -148
  22. package/v2Components/HtmlEditor/components/DeviceToggle/_deviceToggle.scss +1 -0
  23. package/v2Components/HtmlEditor/components/DeviceToggle/index.js +3 -3
  24. package/v2Components/HtmlEditor/components/InAppPreviewPane/DeviceFrame.js +4 -7
  25. package/v2Components/HtmlEditor/components/InAppPreviewPane/__tests__/DeviceFrame.test.js +35 -45
  26. package/v2Components/HtmlEditor/components/InAppPreviewPane/_inAppPreviewPane.scss +1 -3
  27. package/v2Components/HtmlEditor/components/InAppPreviewPane/constants.js +33 -33
  28. package/v2Components/HtmlEditor/components/InAppPreviewPane/index.js +7 -6
  29. package/v2Components/HtmlEditor/constants.js +29 -20
  30. package/v2Components/HtmlEditor/hooks/__tests__/useInAppContent.test.js +158 -17
  31. package/v2Components/HtmlEditor/hooks/useInAppContent.js +53 -143
  32. package/v2Components/HtmlEditor/index.js +1 -1
  33. package/v2Components/HtmlEditor/messages.js +85 -85
  34. package/v2Components/MobilePushPreviewV2/index.js +32 -7
  35. package/v2Components/TemplatePreview/_templatePreview.scss +31 -21
  36. package/v2Components/TemplatePreview/index.js +47 -32
  37. package/v2Components/TemplatePreview/messages.js +4 -0
  38. package/v2Containers/BeeEditor/index.js +82 -80
  39. package/v2Containers/BeePopupEditor/constants.js +10 -0
  40. package/v2Containers/BeePopupEditor/index.js +180 -0
  41. package/v2Containers/BeePopupEditor/tests/index.test.js +627 -0
  42. package/v2Containers/CreativesContainer/SlideBoxContent.js +69 -34
  43. package/v2Containers/CreativesContainer/SlideBoxHeader.js +2 -1
  44. package/v2Containers/CreativesContainer/constants.js +1 -0
  45. package/v2Containers/CreativesContainer/index.js +65 -13
  46. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +4 -12
  47. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +15 -0
  48. package/v2Containers/InApp/__tests__/InAppHTMLEditor.test.js +376 -0
  49. package/v2Containers/InApp/__tests__/sagas.test.js +363 -0
  50. package/v2Containers/InApp/actions.js +7 -0
  51. package/v2Containers/InApp/constants.js +18 -4
  52. package/v2Containers/InApp/index.js +642 -355
  53. package/v2Containers/InApp/index.scss +4 -3
  54. package/v2Containers/InApp/messages.js +7 -3
  55. package/v2Containers/InApp/reducer.js +21 -3
  56. package/v2Containers/InApp/sagas.js +29 -9
  57. package/v2Containers/InApp/selectors.js +25 -5
  58. package/v2Containers/InApp/tests/index.test.js +154 -50
  59. package/v2Containers/InApp/tests/reducer.test.js +34 -0
  60. package/v2Containers/InApp/tests/sagas.test.js +61 -9
  61. package/v2Containers/InApp/tests/selectors.test.js +612 -0
  62. package/v2Containers/InAppWrapper/components/InAppWrapperView.js +162 -0
  63. package/v2Containers/InAppWrapper/components/__tests__/InAppWrapperView.test.js +267 -0
  64. package/v2Containers/InAppWrapper/components/inAppWrapperView.scss +9 -0
  65. package/v2Containers/InAppWrapper/constants.js +16 -0
  66. package/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +473 -0
  67. package/v2Containers/InAppWrapper/hooks/useInAppWrapper.js +198 -0
  68. package/v2Containers/InAppWrapper/index.js +148 -0
  69. package/v2Containers/InAppWrapper/messages.js +49 -0
  70. package/v2Containers/InappAdvance/index.js +1006 -0
  71. package/v2Containers/InappAdvance/index.scss +10 -0
  72. package/v2Containers/InappAdvance/tests/index.test.js +448 -0
  73. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +3 -0
  74. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/index.test.js.snap +2 -0
  75. package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +2 -0
  76. package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +9 -0
  77. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +12 -0
  78. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4 -0
  79. package/v2Containers/TagList/index.js +65 -1
  80. package/v2Containers/Templates/_templates.scss +49 -1
  81. package/v2Containers/Templates/index.js +93 -5
  82. package/v2Containers/Templates/messages.js +4 -0
  83. package/v2Containers/Templates/reducer.js +20 -7
  84. package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +8 -88
  85. package/v2Containers/Templates/tests/reducer.test.js +125 -0
  86. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +35 -0
@@ -12,14 +12,14 @@
12
12
  * Note: Uses injectIntl with forwardRef to provide direct access to CodeEditorPane via ref
13
13
  */
14
14
 
15
- import React, { useRef, useCallback, useMemo, useState } from 'react';
15
+ import React, {
16
+ useRef, useCallback, useMemo, useState,
17
+ } from 'react';
16
18
  import PropTypes from 'prop-types';
17
- import { Layout } from 'antd'; // Fallback - no Cap UI equivalent
18
19
  import { injectIntl, intlShape } from 'react-intl';
19
20
 
20
21
  // Cap UI Components (First Preference)
21
22
  import CapRow from '@capillarytech/cap-ui-library/CapRow';
22
- import CapColumn from '@capillarytech/cap-ui-library/CapColumn';
23
23
  import CapSpin from '@capillarytech/cap-ui-library/CapSpin';
24
24
  import CapNotification from '@capillarytech/cap-ui-library/CapNotification';
25
25
  import CapModal from '@capillarytech/cap-ui-library/CapModal';
@@ -40,7 +40,9 @@ import { useLayoutState } from './hooks/useLayoutState';
40
40
  import { useValidation } from './hooks/useValidation';
41
41
 
42
42
  // Constants
43
- import { HTML_EDITOR_VARIANTS, DEVICE_TYPES, DEFAULT_HTML_CONTENT } from './constants';
43
+ import {
44
+ HTML_EDITOR_VARIANTS, DEVICE_TYPES, DEFAULT_HTML_CONTENT, TAG, EMBEDDED, DEFAULT, FULL, ALL, SMS, EMAIL,
45
+ } from './constants';
44
46
 
45
47
  // Styles
46
48
  import './_htmlEditor.scss';
@@ -61,6 +63,14 @@ const HTMLEditor = ({
61
63
  showFullscreenButton = true,
62
64
  autoSave = true,
63
65
  autoSaveInterval = 30000, // 30 seconds
66
+ // Tags-related props for Add Label functionality
67
+ tags = [],
68
+ injectedTags = {},
69
+ location = {},
70
+ selectedOfferDetails = null,
71
+ onTagSelect = null,
72
+ onContextChange = null,
73
+ globalActions = null, // Redux actions for API calls
64
74
  ...props
65
75
  }) => {
66
76
  // Separate refs for main and modal editors to avoid conflicts
@@ -69,9 +79,7 @@ const HTMLEditor = ({
69
79
  const [isFullscreenModalOpen, setIsFullscreenModalOpen] = useState(false);
70
80
 
71
81
  // Get the currently active editor ref based on fullscreen state
72
- const getActiveEditorRef = useCallback(() => {
73
- return isFullscreenModalOpen ? modalEditorRef : mainEditorRef;
74
- }, [isFullscreenModalOpen]);
82
+ const getActiveEditorRef = useCallback(() => isFullscreenModalOpen ? modalEditorRef : mainEditorRef, [isFullscreenModalOpen]);
75
83
 
76
84
  // Initialize custom hooks for state management - always call both hooks to follow Rules of Hooks
77
85
  const isEmailVariant = variant === HTML_EDITOR_VARIANTS.EMAIL;
@@ -80,7 +88,7 @@ const HTMLEditor = ({
80
88
  autoSave: isEmailVariant ? autoSave : false,
81
89
  autoSaveInterval,
82
90
  onSave: isEmailVariant ? onSave : null,
83
- onChange: isEmailVariant ? onContentChange : null
91
+ onChange: isEmailVariant ? onContentChange : null,
84
92
  };
85
93
 
86
94
  const emailContent = useEditorContent(
@@ -97,7 +105,7 @@ const HTMLEditor = ({
97
105
  // Convert string content to device-specific format
98
106
  inAppInitialContent = {
99
107
  [DEVICE_TYPES.ANDROID]: initialContent,
100
- [DEVICE_TYPES.IOS]: initialContent
108
+ [DEVICE_TYPES.IOS]: initialContent,
101
109
  };
102
110
  } else {
103
111
  // Use provided device-specific content
@@ -109,7 +117,7 @@ const HTMLEditor = ({
109
117
  autoSave: isInAppVariant ? autoSave : false,
110
118
  autoSaveInterval,
111
119
  onSave: isInAppVariant ? onSave : null,
112
- onChange: isInAppVariant ? onContentChange : null
120
+ onChange: isInAppVariant ? onContentChange : null,
113
121
  };
114
122
 
115
123
  const inAppContent = useInAppContent(inAppInitialContent, inAppOptions);
@@ -117,6 +125,42 @@ const HTMLEditor = ({
117
125
  // Use appropriate content hook based on variant
118
126
  const content = variant === HTML_EDITOR_VARIANTS.EMAIL ? emailContent : inAppContent;
119
127
 
128
+ // Handle context change for tag API calls
129
+ // If variant is INAPP, use SMS layout; otherwise use the channel (EMAIL)
130
+ const handleContextChange = useCallback((contextData) => {
131
+ // If onContextChange is provided, use it instead of making our own API call
132
+ // This prevents duplicate API calls when parent component handles tag fetching
133
+ if (onContextChange) {
134
+ onContextChange(contextData);
135
+ return;
136
+ }
137
+
138
+ // Only make API call if onContextChange is not provided and globalActions is available
139
+ if (!globalActions || !location) {
140
+ return;
141
+ }
142
+
143
+ const { type } = location.query || {};
144
+ const tempData = (contextData || '').toLowerCase();
145
+ const isEmbedded = type === EMBEDDED;
146
+ const embedded = isEmbedded ? type : FULL;
147
+ const context = tempData === ALL ? DEFAULT : tempData;
148
+
149
+ // Determine layout: INAPP variant uses SMS, EMAIL variant uses EMAIL
150
+ const layout = variant === HTML_EDITOR_VARIANTS.INAPP ? SMS : EMAIL;
151
+
152
+ const query = {
153
+ layout,
154
+ type: TAG,
155
+ context,
156
+ embedded,
157
+ };
158
+
159
+ // Call the API via Redux action - this will trigger the saga which calls Api.fetchSchemaForEntity
160
+ // The API endpoint will be: /meta/TAG?query={...}
161
+ globalActions.fetchSchemaForEntity(query);
162
+ }, [variant, globalActions, location, onContextChange]);
163
+
120
164
  // Destructure content properties for cleaner access throughout component
121
165
  const {
122
166
  activeDevice,
@@ -124,14 +168,14 @@ const HTMLEditor = ({
124
168
  switchDevice,
125
169
  toggleContentSync,
126
170
  getDeviceContent,
127
- markAsSaved
171
+ markAsSaved,
128
172
  } = content || {};
129
173
 
130
174
  const layout = useLayoutState({
131
175
  splitSizes: [50, 50],
132
176
  viewMode: 'desktop',
133
177
  mobileWidth: 375,
134
- isFullscreen: false
178
+ isFullscreen: false,
135
179
  });
136
180
 
137
181
  // Get current content for validation based on variant
@@ -158,7 +202,7 @@ const HTMLEditor = ({
158
202
  'sanitizer.productionValidHtml': messages.sanitizer.productionValidHtml,
159
203
  'sanitizer.productionSanitized': messages.sanitizer.productionSanitized,
160
204
  'sanitizer.productionInlineCss': messages.sanitizer.productionInlineCss,
161
- 'sanitizer.productionLargeContent': messages.sanitizer.productionLargeContent
205
+ 'sanitizer.productionLargeContent': messages.sanitizer.productionLargeContent,
162
206
  };
163
207
 
164
208
  const messageObj = messageMap[messageKey];
@@ -179,7 +223,7 @@ const HTMLEditor = ({
179
223
  'validator.largeImageDetected': messages.validator.largeImageDetected,
180
224
  'validator.unclosedCssRule': messages.validator.unclosedCssRule,
181
225
  'validator.emptyCssRule': messages.validator.emptyCssRule,
182
- 'validator.cssValidationFailed': messages.validator.cssValidationFailed
226
+ 'validator.cssValidationFailed': messages.validator.cssValidationFailed,
183
227
  };
184
228
 
185
229
  const messageObj = messageMap[messageKey];
@@ -190,57 +234,69 @@ const HTMLEditor = ({
190
234
  enableRealTime: true,
191
235
  debounceMs: 500,
192
236
  enableSanitization: true,
193
- securityLevel: 'standard'
237
+ securityLevel: 'standard',
194
238
  }, formatSanitizerMessage, formatValidatorMessage);
195
239
 
196
240
  // Handle label insertion at cursor position
241
+ // Note: This is called for notification purposes only when tag is inserted via CodeEditorPane
242
+ // The actual insertion happens in CodeEditorPane.handleTagSelect
197
243
  const handleLabelInsert = useCallback((label, position) => {
198
- // With injectIntl({ forwardRef: true }), ref points directly to CodeEditorPane
199
- const activeEditorRef = getActiveEditorRef();
200
- const editor = activeEditorRef.current;
201
-
202
- if (!editor) {
203
- CapNotification.warning({
204
- message: intl.formatMessage(messages.labelInsertError),
205
- description: intl.formatMessage(messages.editorNotReady),
206
- duration: 3
207
- });
208
- return;
209
- }
210
-
211
- // Check if the required methods exist
212
- if (typeof editor?.insertText !== 'function') {
213
- CapNotification.error({
214
- message: intl.formatMessage(messages.labelInsertError),
215
- description: intl.formatMessage(messages.editorMethodNotAvailable),
216
- duration: 4
217
- });
218
- return;
219
- }
220
-
221
- try {
222
- // Get current cursor position or use provided position
223
- const cursor = position !== undefined
224
- ? position
225
- : (typeof editor?.getCursor === 'function' ? editor.getCursor() : 0);
226
-
227
- // Insert label at cursor position
228
- editor.insertText(label, cursor);
244
+ // If position is explicitly null, it means the editor wasn't ready when tag was selected
245
+ // In this case, CodeEditorPane couldn't insert the tag, so we should try here
246
+ if (position === null) {
247
+ // With injectIntl({ forwardRef: true }), ref points directly to CodeEditorPane
248
+ const activeEditorRef = getActiveEditorRef();
249
+ const editor = activeEditorRef.current;
250
+
251
+ if (!editor) {
252
+ CapNotification.warning({
253
+ message: intl.formatMessage(messages.labelInsertError),
254
+ description: intl.formatMessage(messages.editorNotReady),
255
+ duration: 3,
256
+ });
257
+ return;
258
+ }
229
259
 
230
- // Focus the editor if focus method is available
231
- editor?.focus?.();
260
+ // Check if the required methods exist
261
+ if (typeof editor?.insertText !== 'function') {
262
+ CapNotification.error({
263
+ message: intl.formatMessage(messages.labelInsertError),
264
+ description: intl.formatMessage(messages.editorMethodNotAvailable),
265
+ duration: 4,
266
+ });
267
+ return;
268
+ }
232
269
 
233
- // Show success notification
270
+ try {
271
+ // Get current cursor position
272
+ const cursor = typeof editor?.getCursor === 'function' ? editor.getCursor() : 0;
273
+
274
+ // Insert label at cursor position
275
+ editor.insertText(label, cursor);
276
+
277
+ // Focus the editor if focus method is available
278
+ editor?.focus?.();
279
+
280
+ // Show success notification
281
+ CapNotification.success({
282
+ message: intl.formatMessage(messages.labelInserted),
283
+ description: intl.formatMessage(messages.labelInsertedDescription, { label }),
284
+ duration: 2,
285
+ });
286
+ } catch (error) {
287
+ CapNotification.error({
288
+ message: intl.formatMessage(messages.labelInsertError),
289
+ description: error.message,
290
+ duration: 4,
291
+ });
292
+ }
293
+ } else {
294
+ // Tag was already inserted by CodeEditorPane (position is a valid number)
295
+ // Just show success notification - no need to access editor
234
296
  CapNotification.success({
235
297
  message: intl.formatMessage(messages.labelInserted),
236
298
  description: intl.formatMessage(messages.labelInsertedDescription, { label }),
237
- duration: 2
238
- });
239
- } catch (error) {
240
- CapNotification.error({
241
- message: intl.formatMessage(messages.labelInsertError),
242
- description: error.message,
243
- duration: 4
299
+ duration: 2,
244
300
  });
245
301
  }
246
302
  }, [intl, getActiveEditorRef]);
@@ -259,13 +315,13 @@ const HTMLEditor = ({
259
315
 
260
316
  CapNotification.success({
261
317
  message: intl.formatMessage(messages.contentSaved),
262
- duration: 2
318
+ duration: 2,
263
319
  });
264
320
  } catch (error) {
265
321
  CapNotification.error({
266
322
  message: intl.formatMessage(messages.saveError),
267
323
  description: error.message,
268
- duration: 4
324
+ duration: 4,
269
325
  });
270
326
  }
271
327
  }, [content, onSave, intl, markAsSaved]);
@@ -319,8 +375,8 @@ const HTMLEditor = ({
319
375
  switchDevice,
320
376
  toggleContentSync,
321
377
  getDeviceContent,
322
- layoutType
323
- })
378
+ layoutType,
379
+ }),
324
380
  }), [
325
381
  variant,
326
382
  content,
@@ -336,7 +392,7 @@ const HTMLEditor = ({
336
392
  switchDevice,
337
393
  toggleContentSync,
338
394
  getDeviceContent,
339
- layoutType
395
+ layoutType,
340
396
  ]);
341
397
 
342
398
  // Loading state
@@ -387,6 +443,12 @@ const HTMLEditor = ({
387
443
  ref={mainEditorRef}
388
444
  readOnly={readOnly}
389
445
  onLabelInsert={handleLabelInsert}
446
+ tags={tags}
447
+ injectedTags={injectedTags}
448
+ location={location}
449
+ selectedOfferDetails={selectedOfferDetails}
450
+ onTagSelect={onTagSelect}
451
+ onContextChange={handleContextChange}
390
452
  />
391
453
 
392
454
  {/* Preview Pane */}
@@ -411,17 +473,17 @@ const HTMLEditor = ({
411
473
  maskClosable={false}
412
474
  centered
413
475
  closable={false}
414
- width={"90vw"}
476
+ width="90vw"
415
477
  className="html-editor-fullscreen-modal"
416
478
  >
417
479
  <CapRow className="html-editor-fullscreen">
418
480
  {/* Editor Toolbar - Conditional based on variant */}
419
481
  {variant === HTML_EDITOR_VARIANTS.EMAIL ? (
420
482
  <EditorToolbar
421
- showFullscreenButton={true} // Show fullscreen button in modal to allow closing
483
+ showFullscreenButton // Show fullscreen button in modal to allow closing
422
484
  onLabelInsert={handleLabelInsert}
423
485
  onSave={handleSave}
424
- isFullscreenMode={true}
486
+ isFullscreenMode
425
487
  onToggleFullscreen={handleCloseFullscreen} // Close modal when clicked in fullscreen mode
426
488
  />
427
489
  ) : (
@@ -434,10 +496,10 @@ const HTMLEditor = ({
434
496
  onKeepContentSameChange={toggleContentSync}
435
497
  />
436
498
  <EditorToolbar
437
- showFullscreenButton={true} // Show fullscreen button in modal to allow closing
499
+ showFullscreenButton // Show fullscreen button in modal to allow closing
438
500
  onLabelInsert={handleLabelInsert}
439
501
  onSave={handleSave}
440
- isFullscreenMode={true}
502
+ isFullscreenMode
441
503
  onToggleFullscreen={handleCloseFullscreen} // Close modal when clicked in fullscreen mode
442
504
  variant={variant}
443
505
  showTitle={false} // Hide title in InApp variant
@@ -452,21 +514,27 @@ const HTMLEditor = ({
452
514
  <CodeEditorPane
453
515
  ref={modalEditorRef}
454
516
  readOnly={readOnly}
455
- isFullscreenMode={true}
517
+ isFullscreenMode
456
518
  onLabelInsert={handleLabelInsert}
519
+ tags={tags}
520
+ injectedTags={injectedTags}
521
+ location={location}
522
+ selectedOfferDetails={selectedOfferDetails}
523
+ onTagSelect={onTagSelect}
524
+ onContextChange={handleContextChange}
457
525
  />
458
526
 
459
- {/* Preview Pane */}
460
- <PreviewPane isFullscreenMode={true} isModalContext={true} />
461
- </SplitContainer>
527
+ {/* Preview Pane */}
528
+ <PreviewPane isFullscreenMode isModalContext />
529
+ </SplitContainer>
462
530
 
463
- {/* Validation Display in Modal */}
464
- <ValidationErrorDisplay
465
- validation={validation}
466
- onErrorClick={handleValidationErrorClick}
467
- variant={variant}
468
- className="html-editor-validation"
469
- />
531
+ {/* Validation Display in Modal */}
532
+ <ValidationErrorDisplay
533
+ validation={validation}
534
+ onErrorClick={handleValidationErrorClick}
535
+ variant={variant}
536
+ className="html-editor-validation"
537
+ />
470
538
  </CapRow>
471
539
  </CapRow>
472
540
  </CapModal>
@@ -481,7 +549,7 @@ HTMLEditor.propTypes = {
481
549
  layoutType: PropTypes.string, // Layout type for InApp variant
482
550
  initialContent: PropTypes.oneOfType([
483
551
  PropTypes.string,
484
- PropTypes.objectOf(PropTypes.string) // Per-device content for INAPP variant
552
+ PropTypes.objectOf(PropTypes.string), // Per-device content for INAPP variant
485
553
  ]),
486
554
  onSave: PropTypes.func,
487
555
  onContentChange: PropTypes.func,
@@ -489,11 +557,20 @@ HTMLEditor.propTypes = {
489
557
  readOnly: PropTypes.bool,
490
558
  showFullscreenButton: PropTypes.bool,
491
559
  autoSave: PropTypes.bool,
492
- autoSaveInterval: PropTypes.number
560
+ autoSaveInterval: PropTypes.number,
561
+ // Tags-related props
562
+ tags: PropTypes.array,
563
+ injectedTags: PropTypes.object,
564
+ location: PropTypes.object,
565
+ selectedOfferDetails: PropTypes.any,
566
+ onTagSelect: PropTypes.func,
567
+ onContextChange: PropTypes.func, // Deprecated: use globalActions instead
568
+ globalActions: PropTypes.object, // Redux actions for API calls
493
569
  };
494
570
 
495
571
  HTMLEditor.defaultProps = {
496
572
  variant: HTML_EDITOR_VARIANTS.EMAIL, // Default to email variant
573
+ layoutType: null, // Layout type for InApp variant
497
574
  initialContent: null, // Will use default from useEditorContent hook
498
575
  onSave: null,
499
576
  onContentChange: null,
@@ -501,7 +578,15 @@ HTMLEditor.defaultProps = {
501
578
  readOnly: false,
502
579
  showFullscreenButton: true,
503
580
  autoSave: true,
504
- autoSaveInterval: 30000
581
+ autoSaveInterval: 30000,
582
+ // Tags-related props defaults
583
+ tags: [],
584
+ injectedTags: {},
585
+ location: {},
586
+ selectedOfferDetails: null,
587
+ onTagSelect: null,
588
+ onContextChange: null,
589
+ globalActions: null,
505
590
  };
506
591
 
507
592
  // Export with forwardRef to allow direct access to CodeEditorPane via ref