@capillarytech/creatives-library 9.0.65 → 9.0.66

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": "9.0.65",
4
+ "version": "9.0.66",
5
5
  "description": "Capillary creatives ui",
6
6
  "main": "./index.js",
7
7
  "module": "./index.es.js",
@@ -52,6 +52,17 @@ const formatSafe = (intl, descriptor) => (intl?.formatMessage ? intl.formatMessa
52
52
  // Classic gates every field-error display on checkValidation (pre-save silence).
53
53
  const shouldShowError = (renderContext, error) => Boolean(renderContext?.checkValidation && error);
54
54
 
55
+ const isEmptyValue = (value) => !value || !/\S/.test(String(value));
56
+
57
+ // Classic (Classic.js:2881-2885) only defers the "empty/required" error until
58
+ // Save/Update/Done (checkValidation); brace/personalization/tag errors show live
59
+ // as soon as they're detected. Title/Message fields need that same two-tier gate.
60
+ const shouldShowFieldError = (renderContext, error, value) => {
61
+ if (!error) return false;
62
+ const isEmptyRequiredError = error === true && isEmptyValue(value);
63
+ return isEmptyRequiredError ? Boolean(renderContext?.checkValidation) : true;
64
+ };
65
+
55
66
  /** Classic input-case error message: personalization > brace > schema errorMessage. */
56
67
  const resolveInputMessage = (field, value, error, renderContext) => {
57
68
  const { intl, restrictPersonalization } = renderContext || {};
@@ -67,7 +78,7 @@ const resolveInputMessage = (field, value, error, renderContext) => {
67
78
  export const MpushInputField = ({
68
79
  field, value, error, onChange, onBlur, renderContext,
69
80
  }) => {
70
- const showError = shouldShowError(renderContext, error);
81
+ const showError = shouldShowFieldError(renderContext, error, value);
71
82
  const message = showError ? resolveInputMessage(field, value, error, renderContext) : '';
72
83
  return (
73
84
  <CapColumn key={field.id} span={field.width} offset={field.offset} style={field.style || {}}>
@@ -95,13 +106,9 @@ export const MpushTextAreaField = ({
95
106
  }) => {
96
107
  let aiDisabled = true;
97
108
  try { aiDisabled = isAiContentBotDisabled(); } catch (e) { console.error(e); aiDisabled = true; }
98
- // Classic-observable behavior: errorData is only ever computed under
99
- // startValidation (Classic.js:334-345), so NO editor error — empty or tag —
100
- // is visible before a save attempt. checkValidation is true exactly in the
101
- // states where Classic can hold a non-false errorType, so gating display on it
102
- // reproduces Classic's typing silence and also keeps the initial-hydrate
103
- // errorData (computed for the parent validity emission) from leaking into the UI.
104
- const showError = shouldShowError(renderContext, error);
109
+ // Classic shows brace/tag/personalization errors live while typing and only
110
+ // defers the empty/required error until Save/Update/Done (Classic.js:2881-2885).
111
+ const showError = shouldShowFieldError(renderContext, error, value);
105
112
  // MPUSH keeps the inline message even though the channel is liquid-supported
106
113
  // (Classic.js:2908-2915). Personalization gets its own message (2877-2879).
107
114
  const inlineMessage = showError ? resolveInputMessage(field, value, error, renderContext) : '';
@@ -26,7 +26,7 @@ const kids = (el) => {
26
26
  describe('MpushInputField', () => {
27
27
  const field = { id: 'secondary-cta-0-label', width: 18, errorMessage: 'Label required' };
28
28
 
29
- it('message resolution: personalization > brace > schema errorMessage; hidden without checkValidation', () => {
29
+ it('message resolution: personalization > brace > schema errorMessage; empty-required error hidden without checkValidation', () => {
30
30
  const base = { field, onChange: () => {}, renderContext: { checkValidation: true, intl } };
31
31
  expect(kids(MpushInputField({ ...base, value: '', error: true }))[0].props.errorMessage)
32
32
  .toBe('Label required');
@@ -42,12 +42,20 @@ describe('MpushInputField', () => {
42
42
  ...base, value: '', error: true, renderContext: { checkValidation: false, intl },
43
43
  }))[0].props.errorMessage).toBe('');
44
44
  });
45
+
46
+ it('shows brace/tag errors live, before checkValidation (Save/Update/Done) is set', () => {
47
+ const el = MpushInputField({
48
+ field, value: 'a {{b', error: ERROR_VALUE.BRACKET, onChange: () => {}, renderContext: { checkValidation: false, intl },
49
+ });
50
+ expect(kids(el)[0].props.errorMessage).toContain('curly braces');
51
+ expect(kids(el)[0].props.className).toContain('error');
52
+ });
45
53
  });
46
54
 
47
55
  describe('MpushTextAreaField', () => {
48
56
  const field = { id: 'message-editor', width: 18, errorMessage: 'Message required' };
49
57
 
50
- it('inline message shows only under checkValidation; AskAira renders when AI enabled', () => {
58
+ it('empty-required inline message shows only under checkValidation; AskAira renders when AI enabled', () => {
51
59
  const base = { field, onChange: jest.fn(), renderContext: { checkValidation: true, intl } };
52
60
  expect(kids(MpushTextAreaField({ ...base, value: '', error: true }))[0].props.errorMessage)
53
61
  .toBe('Message required');
@@ -66,6 +74,18 @@ describe('MpushTextAreaField', () => {
66
74
  });
67
75
  expect(kids(el).length).toBe(1); // textarea only, no bot
68
76
  });
77
+
78
+ it('shows brace/tag errors live, before checkValidation (Save/Update/Done) is set', () => {
79
+ const el = MpushTextAreaField({
80
+ field,
81
+ value: 'hi {{name',
82
+ error: ERROR_VALUE.BRACKET,
83
+ onChange: () => {},
84
+ renderContext: { checkValidation: false, intl },
85
+ });
86
+ expect(kids(el)[0].props.errorMessage).toContain('curly braces');
87
+ expect(kids(el)[0].props.className).toContain('error-form-builder');
88
+ });
69
89
  });
70
90
 
71
91
  describe('MpushCheckboxField', () => {