@bigbinary/neeto-rules-frontend 2.7.20 → 2.7.22

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 (87) hide show
  1. package/app/javascript/src/translations/ar.json +2 -1
  2. package/app/javascript/src/translations/bg.json +2 -1
  3. package/app/javascript/src/translations/ca.json +2 -1
  4. package/app/javascript/src/translations/cs.json +2 -1
  5. package/app/javascript/src/translations/da.json +2 -1
  6. package/app/javascript/src/translations/de.json +2 -1
  7. package/app/javascript/src/translations/es-MX.json +2 -1
  8. package/app/javascript/src/translations/es.json +2 -1
  9. package/app/javascript/src/translations/et.json +2 -1
  10. package/app/javascript/src/translations/fi.json +2 -1
  11. package/app/javascript/src/translations/fil.json +2 -1
  12. package/app/javascript/src/translations/fr.json +2 -1
  13. package/app/javascript/src/translations/he.json +2 -1
  14. package/app/javascript/src/translations/hi.json +2 -1
  15. package/app/javascript/src/translations/hr.json +2 -1
  16. package/app/javascript/src/translations/hu.json +2 -1
  17. package/app/javascript/src/translations/id.json +2 -1
  18. package/app/javascript/src/translations/it.json +2 -1
  19. package/app/javascript/src/translations/ja.json +2 -1
  20. package/app/javascript/src/translations/ko.json +2 -1
  21. package/app/javascript/src/translations/nl.json +2 -1
  22. package/app/javascript/src/translations/pl.json +2 -1
  23. package/app/javascript/src/translations/pt-BR.json +2 -1
  24. package/app/javascript/src/translations/pt.json +2 -1
  25. package/app/javascript/src/translations/ro.json +2 -1
  26. package/app/javascript/src/translations/ru.json +2 -1
  27. package/app/javascript/src/translations/sk.json +2 -1
  28. package/app/javascript/src/translations/sl.json +2 -1
  29. package/app/javascript/src/translations/sv.json +2 -1
  30. package/app/javascript/src/translations/th.json +2 -1
  31. package/app/javascript/src/translations/tr.json +2 -1
  32. package/app/javascript/src/translations/uk.json +2 -1
  33. package/app/javascript/src/translations/vi.json +2 -1
  34. package/app/javascript/src/translations/zh-CN.json +2 -1
  35. package/app/javascript/src/translations/zh-TW.json +2 -1
  36. package/dist/.ready +1 -1
  37. package/dist/NeetoRulesBuilder.js +30 -2
  38. package/dist/NeetoRulesBuilder.js.map +1 -1
  39. package/dist/NeetoRulesForm.js +2 -2
  40. package/dist/cjs/NeetoRulesBuilder.js +30 -2
  41. package/dist/cjs/NeetoRulesBuilder.js.map +1 -1
  42. package/dist/cjs/NeetoRulesForm.js +2 -2
  43. package/dist/cjs/index.js +2 -2
  44. package/dist/cjs/v2/NeetoRules.js +1 -1
  45. package/dist/cjs/v2/NeetoRulesBuilder.js +407 -207
  46. package/dist/cjs/v2/NeetoRulesBuilder.js.map +1 -1
  47. package/dist/cjs/v2/NeetoRulesForm.js +10 -8
  48. package/dist/cjs/v2/NeetoRulesForm.js.map +1 -1
  49. package/dist/cjs/v2/RulePreview.js +1 -1
  50. package/dist/cjs/v2/hooks.js +2 -2
  51. package/dist/cjs/v2/index.js +4 -4
  52. package/dist/{index-DMCgC01M.js → index-49edM85x.js} +2 -2
  53. package/dist/{index-DMCgC01M.js.map → index-49edM85x.js.map} +1 -1
  54. package/dist/{index-D_dEe2Gg.js → index-BZYwFjcS.js} +2 -2
  55. package/dist/{index-D_dEe2Gg.js.map → index-BZYwFjcS.js.map} +1 -1
  56. package/dist/{index-BXLCiV70.js → index-CcbW7H2S.js} +67 -21
  57. package/dist/index-CcbW7H2S.js.map +1 -0
  58. package/dist/{index-hvuc6OIP.js → index-Fukq1VSN.js} +69 -18
  59. package/dist/index-Fukq1VSN.js.map +1 -0
  60. package/dist/index.js +2 -2
  61. package/dist/keyboardShortcuts-DtnjcivY.js +96 -0
  62. package/dist/{keyboardShortcuts-lX0oq49M.js.map → keyboardShortcuts-DtnjcivY.js.map} +1 -1
  63. package/dist/keyboardShortcuts-_OrtgF0A.js +92 -0
  64. package/dist/{keyboardShortcuts-DXP5YgeG.js.map → keyboardShortcuts-_OrtgF0A.js.map} +1 -1
  65. package/dist/{useCustomDataStore-CU3KpyD4.js → useCustomDataStore-CEbhXugO.js} +2 -2
  66. package/dist/{useCustomDataStore-CU3KpyD4.js.map → useCustomDataStore-CEbhXugO.js.map} +1 -1
  67. package/dist/{useCustomDataStore-D9k8F5g-.js → useCustomDataStore-DPmWkEhs.js} +2 -2
  68. package/dist/{useCustomDataStore-D9k8F5g-.js.map → useCustomDataStore-DPmWkEhs.js.map} +1 -1
  69. package/dist/{useUtilityStore-BBb39TOj.js → useUtilityStore-BVCulMEC.js} +9 -2
  70. package/dist/useUtilityStore-BVCulMEC.js.map +1 -0
  71. package/dist/{useUtilityStore-DkxAexDw.js → useUtilityStore-gtPhFvpI.js} +9 -2
  72. package/dist/useUtilityStore-gtPhFvpI.js.map +1 -0
  73. package/dist/v2/NeetoRules.js +1 -1
  74. package/dist/v2/NeetoRulesBuilder.js +388 -207
  75. package/dist/v2/NeetoRulesBuilder.js.map +1 -1
  76. package/dist/v2/NeetoRulesForm.js +10 -8
  77. package/dist/v2/NeetoRulesForm.js.map +1 -1
  78. package/dist/v2/RulePreview.js +1 -1
  79. package/dist/v2/hooks.js +2 -2
  80. package/dist/v2/index.js +4 -4
  81. package/package.json +7 -7
  82. package/dist/index-BXLCiV70.js.map +0 -1
  83. package/dist/index-hvuc6OIP.js.map +0 -1
  84. package/dist/keyboardShortcuts-DXP5YgeG.js +0 -92
  85. package/dist/keyboardShortcuts-lX0oq49M.js +0 -96
  86. package/dist/useUtilityStore-BBb39TOj.js.map +0 -1
  87. package/dist/useUtilityStore-DkxAexDw.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  import _defineProperty from '@babel/runtime/helpers/defineProperty';
2
2
  import _objectDestructuringEmpty from '@babel/runtime/helpers/objectDestructuringEmpty';
3
- import { f as flatten, S as SHORTCUTS } from '../keyboardShortcuts-DXP5YgeG.js';
3
+ import { f as flatten, S as SHORTCUTS } from '../keyboardShortcuts-_OrtgF0A.js';
4
4
  import { useShallow } from 'zustand/shallow';
5
5
  import { useState, useRef, useEffect, createElement, Fragment as Fragment$1, useCallback, useMemo } from 'react';
6
6
  import { Button, Input, Checkbox, Typography, RadioGroup, Textarea, DatePicker, Select as Select$1, Tooltip, MultiEmailInput, Spinner } from '@bigbinary/neeto-atoms';
@@ -11,9 +11,9 @@ import { isNotEmpty, toLabelAndValue, removeBy, isNot, noop } from '@bigbinary/n
11
11
  import Container from '@bigbinary/neeto-molecules/v2/Container';
12
12
  import Header from '@bigbinary/neeto-molecules/v2/Header';
13
13
  import { useTranslation } from 'react-i18next';
14
- import { E as EditorAction, m as Panel, p as ErrorCallout, q as SmsFields, r as PhoneNumberField, j as formatData, u as usePollRuleName, T as TouchErrors, l as ScrollToErrorField, n as getValidationSchema, o as DEFAULT_INITIAL_VALUE, k as buildPayload } from '../index-BXLCiV70.js';
15
- import { u as useCustomDataStore } from '../useCustomDataStore-CU3KpyD4.js';
16
- import { u as useUtilityStore } from '../useUtilityStore-BBb39TOj.js';
14
+ import { E as EditorAction, L as ListField, o as Panel, r as ErrorCallout, s as SmsFields, M as MIN_DELAY_VALUE, t as MAX_DELAY_VALUE, v as PhoneNumberField, l as formatData, u as usePollRuleName, T as TouchErrors, n as ScrollToErrorField, p as getValidationSchema, q as DEFAULT_INITIAL_VALUE, m as buildPayload } from '../index-CcbW7H2S.js';
15
+ import { u as useCustomDataStore } from '../useCustomDataStore-CEbhXugO.js';
16
+ import { u as useUtilityStore } from '../useUtilityStore-BVCulMEC.js';
17
17
  import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray';
18
18
  import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
19
19
  import Plus from '@bigbinary/neeto-icons/Plus';
@@ -22,6 +22,7 @@ import Delete from '@bigbinary/neeto-icons/Delete';
22
22
  import _objectWithoutProperties from '@babel/runtime/helpers/objectWithoutProperties';
23
23
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
24
24
  import { t } from 'i18next';
25
+ import * as yup from 'yup';
25
26
  import _asyncToGenerator from '@babel/runtime/helpers/asyncToGenerator';
26
27
  import useHotkeys from '@bigbinary/neeto-hotkeys';
27
28
  import Search from '@bigbinary/neeto-icons/Search';
@@ -35,7 +36,6 @@ import '@tanstack/react-query';
35
36
  import '@bigbinary/neeto-commons-frontend/react-utils';
36
37
  import 'axios';
37
38
  import '../index-9h4B7JZZ.js';
38
- import 'yup';
39
39
  import 'lucide-react';
40
40
  import '@bigbinary/neeto-commons-frontend/v2/react-utils';
41
41
  import '@monaco-editor/react';
@@ -79,6 +79,22 @@ var TIME_UNITS = [{
79
79
  /* eslint-enable @bigbinary/neeto/neetocommons-tips */
80
80
 
81
81
  var LEAD_TIME_UNITS = TIME_UNITS;
82
+
83
+ // Mirrors the classic form's three-digit input cap; 999 days equals the
84
+ // backend's maximum lead time.
85
+ var MAX_LEAD_TIME_VALUE = 999;
86
+ var STEPPER_DELTA = {
87
+ INCREMENT: 1,
88
+ DECREMENT: -1
89
+ };
90
+ var STEPPER_MIN_VALUE = 1;
91
+ var DEFAULT_DELAY_VALUE = 10;
92
+
93
+ // Matches the token flash animation duration in sentence-builder.css.
94
+ var FLASH_DURATION_MS = 2200;
95
+
96
+ // Keeps an element out of the keyboard tab order (HTML tabindex sentinel).
97
+ var SKIP_TAB_INDEX = -1;
82
98
  var CONDITION_VERBS = {
83
99
  IS: "is",
84
100
  IS_NOT: "is_not",
@@ -176,7 +192,11 @@ var CONFIG_FOCUSABLE_SELECTOR = 'input:not([type="radio"]):not([type="checkbox"]
176
192
  var SMS_TYPES = ["sms", "smsToNumbers"];
177
193
  var RECIPIENT_FOCUSABLE_SELECTOR = 'input, textarea, [contenteditable="true"]';
178
194
  var SMS_TO_NUMBERS = "smsToNumbers";
179
- var SWAP_CHANNEL_ORDER = ["email", "sms", "slack", "webhook", "calendar_invite"];
195
+ var RECIPIENT_STORAGE_FIELDS = {
196
+ emails: "emails",
197
+ value: "value",
198
+ phoneNumbers: "phoneNumbers"
199
+ };
180
200
  var DEFAULT_DELAY_UNITS = TIME_UNITS;
181
201
 
182
202
  var useClearingHover = function useClearingHover() {
@@ -443,6 +463,18 @@ var actionParts = function actionParts(_ref11) {
443
463
  recipientSubtitle: channelMeta.recipientSubtitle || (option === null || option === void 0 ? void 0 : option.recipientSubtitle)
444
464
  };
445
465
  };
466
+
467
+ // Which condition fields a host offers can depend on the rule — a trigger may
468
+ // only support a subset. Lookups deliberately keep using the full list so a
469
+ // field already on the rule still resolves after the offer narrows.
470
+ var offeredConditionFields = function offeredConditionFields(_ref12) {
471
+ var _ref13, _schema$conditions$fi, _schema$conditions3, _schema$conditions3$f, _schema$conditions4;
472
+ var schema = _ref12.schema,
473
+ rule = _ref12.rule;
474
+ return (_ref13 = (_schema$conditions$fi = schema === null || schema === void 0 || (_schema$conditions3 = schema.conditions) === null || _schema$conditions3 === void 0 || (_schema$conditions3$f = _schema$conditions3.fieldsFor) === null || _schema$conditions3$f === void 0 ? void 0 : _schema$conditions3$f.call(_schema$conditions3, {
475
+ rule: rule
476
+ })) !== null && _schema$conditions$fi !== void 0 ? _schema$conditions$fi : schema === null || schema === void 0 || (_schema$conditions4 = schema.conditions) === null || _schema$conditions4 === void 0 ? void 0 : _schema$conditions4.fields) !== null && _ref13 !== void 0 ? _ref13 : [];
477
+ };
446
478
  var hasTrigger = function hasTrigger(rule) {
447
479
  return !isEmpty((rule === null || rule === void 0 ? void 0 : rule.triggers) || []);
448
480
  };
@@ -454,28 +486,28 @@ var hasAction = function hasAction(rule) {
454
486
  var isRuleComplete = function isRuleComplete(rule) {
455
487
  return hasTrigger(rule) && hasAction(rule);
456
488
  };
457
- var scopeOptionFor = function scopeOptionFor(_ref12) {
489
+ var scopeOptionFor = function scopeOptionFor(_ref14) {
458
490
  var _item$value, _schema$scope;
459
- var schema = _ref12.schema,
460
- item = _ref12.item;
491
+ var schema = _ref14.schema,
492
+ item = _ref14.item;
461
493
  var value = (_item$value = item === null || item === void 0 ? void 0 : item.value) !== null && _item$value !== void 0 ? _item$value : item;
462
494
  return ((schema === null || schema === void 0 || (_schema$scope = schema.scope) === null || _schema$scope === void 0 ? void 0 : _schema$scope.options) || []).find(function (candidate) {
463
495
  var _candidate$value2;
464
496
  return ((_candidate$value2 = candidate.value) !== null && _candidate$value2 !== void 0 ? _candidate$value2 : candidate.id) === value;
465
497
  });
466
498
  };
467
- var scopePhoneFields = function scopePhoneFields(_ref13) {
468
- var _ref14, _item$phoneFields, _scopeOptionFor;
469
- var schema = _ref13.schema,
470
- item = _ref13.item;
471
- return (_ref14 = (_item$phoneFields = item === null || item === void 0 ? void 0 : item.phoneFields) !== null && _item$phoneFields !== void 0 ? _item$phoneFields : (_scopeOptionFor = scopeOptionFor({
499
+ var scopePhoneFields = function scopePhoneFields(_ref15) {
500
+ var _ref16, _item$phoneFields, _scopeOptionFor;
501
+ var schema = _ref15.schema,
502
+ item = _ref15.item;
503
+ return (_ref16 = (_item$phoneFields = item === null || item === void 0 ? void 0 : item.phoneFields) !== null && _item$phoneFields !== void 0 ? _item$phoneFields : (_scopeOptionFor = scopeOptionFor({
472
504
  schema: schema,
473
505
  item: item
474
- })) === null || _scopeOptionFor === void 0 ? void 0 : _scopeOptionFor.phoneFields) !== null && _ref14 !== void 0 ? _ref14 : null;
506
+ })) === null || _scopeOptionFor === void 0 ? void 0 : _scopeOptionFor.phoneFields) !== null && _ref16 !== void 0 ? _ref16 : null;
475
507
  };
476
- var effectiveScopePhoneField = function effectiveScopePhoneField(_ref15) {
477
- var schema = _ref15.schema,
478
- item = _ref15.item;
508
+ var effectiveScopePhoneField = function effectiveScopePhoneField(_ref17) {
509
+ var schema = _ref17.schema,
510
+ item = _ref17.item;
479
511
  if (item !== null && item !== void 0 && item.phoneField) return item.phoneField;
480
512
  var phoneFields = scopePhoneFields({
481
513
  schema: schema,
@@ -483,14 +515,14 @@ var effectiveScopePhoneField = function effectiveScopePhoneField(_ref15) {
483
515
  });
484
516
  return (phoneFields === null || phoneFields === void 0 ? void 0 : phoneFields.length) === 1 ? phoneFields[0].value : undefined;
485
517
  };
486
- var invalidScopeIndexes = function invalidScopeIndexes(_ref16) {
518
+ var invalidScopeIndexes = function invalidScopeIndexes(_ref18) {
487
519
  var _scope$requiresPhone;
488
- var rule = _ref16.rule,
489
- schema = _ref16.schema;
520
+ var rule = _ref18.rule,
521
+ schema = _ref18.schema;
490
522
  var scope = schema === null || schema === void 0 ? void 0 : schema.scope;
491
523
  if (!(scope !== null && scope !== void 0 && scope.enabled) || !((_scope$requiresPhone = scope.requiresPhone) !== null && _scope$requiresPhone !== void 0 && _scope$requiresPhone.call(scope, (rule === null || rule === void 0 ? void 0 : rule.actions) || []))) return [];
492
524
  return ((rule === null || rule === void 0 ? void 0 : rule.scope) || []).reduce(function (indexes, item, index) {
493
- var _ref17, _item$hasPhoneField;
525
+ var _ref19, _item$hasPhoneField;
494
526
  var option = scopeOptionFor({
495
527
  schema: schema,
496
528
  item: item
@@ -499,15 +531,15 @@ var invalidScopeIndexes = function invalidScopeIndexes(_ref16) {
499
531
  schema: schema,
500
532
  item: item
501
533
  });
502
- var hasPhoneField = (_ref17 = (_item$hasPhoneField = item === null || item === void 0 ? void 0 : item.hasPhoneField) !== null && _item$hasPhoneField !== void 0 ? _item$hasPhoneField : option === null || option === void 0 ? void 0 : option.hasPhoneField) !== null && _ref17 !== void 0 ? _ref17 : phoneFields ? phoneFields.length > 0 : undefined;
534
+ var hasPhoneField = (_ref19 = (_item$hasPhoneField = item === null || item === void 0 ? void 0 : item.hasPhoneField) !== null && _item$hasPhoneField !== void 0 ? _item$hasPhoneField : option === null || option === void 0 ? void 0 : option.hasPhoneField) !== null && _ref19 !== void 0 ? _ref19 : phoneFields ? phoneFields.length > 0 : undefined;
503
535
  if (hasPhoneField === false) indexes.push(index);
504
536
  return indexes;
505
537
  }, []);
506
538
  };
507
- var invalidScopePhoneFieldIndexes = function invalidScopePhoneFieldIndexes(_ref18) {
539
+ var invalidScopePhoneFieldIndexes = function invalidScopePhoneFieldIndexes(_ref20) {
508
540
  var _scope$requiresPhone2;
509
- var rule = _ref18.rule,
510
- schema = _ref18.schema;
541
+ var rule = _ref20.rule,
542
+ schema = _ref20.schema;
511
543
  var scope = schema === null || schema === void 0 ? void 0 : schema.scope;
512
544
  if (!(scope !== null && scope !== void 0 && scope.enabled) || !((_scope$requiresPhone2 = scope.requiresPhone) !== null && _scope$requiresPhone2 !== void 0 && _scope$requiresPhone2.call(scope, (rule === null || rule === void 0 ? void 0 : rule.actions) || []))) return [];
513
545
  return ((rule === null || rule === void 0 ? void 0 : rule.scope) || []).reduce(function (indexes, item, index) {
@@ -544,14 +576,33 @@ var minutesToParts = function minutesToParts(minutes) {
544
576
  unit: "minutes"
545
577
  };
546
578
  };
547
- var partsToMinutes = function partsToMinutes(_ref19) {
548
- var value = _ref19.value,
549
- unit = _ref19.unit;
579
+ var partsToMinutes = function partsToMinutes(_ref21) {
580
+ var value = _ref21.value,
581
+ unit = _ref21.unit;
550
582
  return (
551
583
  // eslint-disable-next-line security/detect-object-injection
552
584
  (Number(value) || 0) * (UNIT_MINUTES[unit] || 1)
553
585
  );
554
586
  };
587
+ var leadTimeExceedsMax = function leadTimeExceedsMax(minutes) {
588
+ return minutesToParts(minutes).value > MAX_LEAD_TIME_VALUE;
589
+ };
590
+ var leadTimeValidationSchema = function leadTimeValidationSchema(schema) {
591
+ var _schema$triggers2;
592
+ var fieldKey = schema === null || schema === void 0 || (_schema$triggers2 = schema.triggers) === null || _schema$triggers2 === void 0 || (_schema$triggers2 = _schema$triggers2.leadTime) === null || _schema$triggers2 === void 0 ? void 0 : _schema$triggers2.fieldKey;
593
+ if (!fieldKey) return yup.object();
594
+ return yup.object().shape(_defineProperty({}, fieldKey, yup.object().shape({
595
+ // yup 0.32 can only concat schemas of the same type, and the host's
596
+ // generic field schema for the lead time key is a string schema.
597
+ value: yup.string().test("max-lead-time", function () {
598
+ return t("neetoRules.validations.maxLeadTime", {
599
+ max: MAX_LEAD_TIME_VALUE
600
+ });
601
+ }, function (minutes) {
602
+ return !leadTimeExceedsMax(minutes);
603
+ })
604
+ })));
605
+ };
555
606
  var leadTimeLabel = function leadTimeLabel(minutes) {
556
607
  var _minutesToParts = minutesToParts(minutes),
557
608
  value = _minutesToParts.value,
@@ -574,30 +625,33 @@ var normalizeSchema = function normalizeSchema() {
574
625
  var joinTypeFor = function joinTypeFor(mode) {
575
626
  return mode === CONDITION_MODE.OR ? JOIN_TYPE.or : JOIN_TYPE.and;
576
627
  };
628
+ var recipientStorageField = function recipientStorageField(field) {
629
+ return field === RECIPIENT_STORAGE_FIELDS.emails ? RECIPIENT_STORAGE_FIELDS.emails : RECIPIENT_STORAGE_FIELDS.value;
630
+ };
577
631
  var modeFromJoinType = function modeFromJoinType(joinType) {
578
632
  return joinType === JOIN_TYPE.or ? CONDITION_MODE.OR : CONDITION_MODE.AND;
579
633
  };
580
634
 
581
635
  // eslint-disable-next-line security/detect-object-injection
582
- var valueAt = function valueAt(_ref20) {
636
+ var valueAt = function valueAt(_ref22) {
583
637
  var _values$key;
584
- var values = _ref20.values,
585
- key = _ref20.key;
638
+ var values = _ref22.values,
639
+ key = _ref22.key;
586
640
  return values === null || values === void 0 || (_values$key = values[key]) === null || _values$key === void 0 ? void 0 : _values$key.value;
587
641
  };
588
642
  var asArray = function asArray(maybeArray) {
589
643
  return Array.isArray(maybeArray) ? maybeArray : [];
590
644
  };
591
645
  var fieldKeysFromSchema = function fieldKeysFromSchema() {
592
- var _schema$triggers2, _schema$actor2, _schema$conditions3, _schema$actions3, _schema$delay, _schema$triggers3, _schema$scope2;
646
+ var _schema$triggers3, _schema$actor2, _schema$conditions5, _schema$actions3, _schema$delay, _schema$triggers4, _schema$scope2;
593
647
  var schema = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
594
648
  return {
595
- triggers: ((_schema$triggers2 = schema.triggers) === null || _schema$triggers2 === void 0 ? void 0 : _schema$triggers2.fieldKey) || "events",
649
+ triggers: ((_schema$triggers3 = schema.triggers) === null || _schema$triggers3 === void 0 ? void 0 : _schema$triggers3.fieldKey) || "events",
596
650
  performer: ((_schema$actor2 = schema.actor) === null || _schema$actor2 === void 0 ? void 0 : _schema$actor2.fieldKey) || "performer",
597
- conditions: ((_schema$conditions3 = schema.conditions) === null || _schema$conditions3 === void 0 ? void 0 : _schema$conditions3.fieldKey) || "conditions",
651
+ conditions: ((_schema$conditions5 = schema.conditions) === null || _schema$conditions5 === void 0 ? void 0 : _schema$conditions5.fieldKey) || "conditions",
598
652
  actions: ((_schema$actions3 = schema.actions) === null || _schema$actions3 === void 0 ? void 0 : _schema$actions3.fieldKey) || "actions",
599
653
  delay: ((_schema$delay = schema.delay) === null || _schema$delay === void 0 ? void 0 : _schema$delay.fieldKey) || "execution_delay",
600
- leadTime: (_schema$triggers3 = schema.triggers) === null || _schema$triggers3 === void 0 || (_schema$triggers3 = _schema$triggers3.leadTime) === null || _schema$triggers3 === void 0 ? void 0 : _schema$triggers3.fieldKey,
654
+ leadTime: (_schema$triggers4 = schema.triggers) === null || _schema$triggers4 === void 0 || (_schema$triggers4 = _schema$triggers4.leadTime) === null || _schema$triggers4 === void 0 ? void 0 : _schema$triggers4.fieldKey,
601
655
  scope: ((_schema$scope2 = schema.scope) === null || _schema$scope2 === void 0 ? void 0 : _schema$scope2.fieldKey) || "meetingIds",
602
656
  status: "status",
603
657
  name: "name"
@@ -605,11 +659,11 @@ var fieldKeysFromSchema = function fieldKeysFromSchema() {
605
659
  };
606
660
  var valuesToRuleModel = function valuesToRuleModel() {
607
661
  var _valueAt, _conditions$;
608
- var _ref21 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
609
- _ref21$values = _ref21.values,
610
- values = _ref21$values === void 0 ? {} : _ref21$values,
611
- _ref21$schema = _ref21.schema,
612
- schema = _ref21$schema === void 0 ? {} : _ref21$schema;
662
+ var _ref23 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
663
+ _ref23$values = _ref23.values,
664
+ values = _ref23$values === void 0 ? {} : _ref23$values,
665
+ _ref23$schema = _ref23.schema,
666
+ schema = _ref23$schema === void 0 ? {} : _ref23$schema;
613
667
  var keys = fieldKeysFromSchema(schema);
614
668
  var conditions = asArray(valueAt({
615
669
  values: values,
@@ -653,42 +707,42 @@ var valuesToRuleModel = function valuesToRuleModel() {
653
707
  }))
654
708
  };
655
709
  };
656
- var setTriggers = function setTriggers(_ref22) {
657
- var schema = _ref22.schema,
658
- triggers = _ref22.triggers;
710
+ var setTriggers = function setTriggers(_ref24) {
711
+ var schema = _ref24.schema,
712
+ triggers = _ref24.triggers;
659
713
  return {
660
714
  path: "".concat(fieldKeysFromSchema(schema).triggers, ".value"),
661
715
  value: triggers
662
716
  };
663
717
  };
664
- var setPerformer = function setPerformer(_ref23) {
665
- var schema = _ref23.schema,
666
- performer = _ref23.performer;
718
+ var setPerformer = function setPerformer(_ref25) {
719
+ var schema = _ref25.schema,
720
+ performer = _ref25.performer;
667
721
  return {
668
722
  path: "".concat(fieldKeysFromSchema(schema).performer, ".value"),
669
723
  value: performer
670
724
  };
671
725
  };
672
- var setActions = function setActions(_ref24) {
673
- var schema = _ref24.schema,
674
- actions = _ref24.actions;
726
+ var setActions = function setActions(_ref26) {
727
+ var schema = _ref26.schema,
728
+ actions = _ref26.actions;
675
729
  return {
676
730
  path: "".concat(fieldKeysFromSchema(schema).actions, ".value"),
677
731
  value: actions
678
732
  };
679
733
  };
680
- var setConditions = function setConditions(_ref25) {
681
- var schema = _ref25.schema,
682
- conditions = _ref25.conditions;
734
+ var setConditions = function setConditions(_ref27) {
735
+ var schema = _ref27.schema,
736
+ conditions = _ref27.conditions;
683
737
  return {
684
738
  path: "".concat(fieldKeysFromSchema(schema).conditions, ".value"),
685
739
  value: conditions
686
740
  };
687
741
  };
688
- var setConditionMode = function setConditionMode(_ref26) {
689
- var schema = _ref26.schema,
690
- conditions = _ref26.conditions,
691
- joinType = _ref26.joinType;
742
+ var setConditionMode = function setConditionMode(_ref28) {
743
+ var schema = _ref28.schema,
744
+ conditions = _ref28.conditions,
745
+ joinType = _ref28.joinType;
692
746
  return setConditions({
693
747
  schema: schema,
694
748
  conditions: conditions.map(function (condition) {
@@ -696,34 +750,34 @@ var setConditionMode = function setConditionMode(_ref26) {
696
750
  })
697
751
  });
698
752
  };
699
- var setDelay = function setDelay(_ref27) {
700
- var schema = _ref27.schema,
701
- delay = _ref27.delay;
753
+ var setDelay = function setDelay(_ref29) {
754
+ var schema = _ref29.schema,
755
+ delay = _ref29.delay;
702
756
  return {
703
757
  path: "".concat(fieldKeysFromSchema(schema).delay, ".value"),
704
758
  value: delay !== null && delay !== void 0 ? delay : {}
705
759
  };
706
760
  };
707
- var setActive = function setActive(_ref28) {
708
- var schema = _ref28.schema,
709
- active = _ref28.active;
761
+ var setActive = function setActive(_ref30) {
762
+ var schema = _ref30.schema,
763
+ active = _ref30.active;
710
764
  return {
711
765
  path: "".concat(fieldKeysFromSchema(schema).status, ".value"),
712
766
  value: active ? STATUS_KEYS.ENABLED : STATUS_KEYS.DISABLED
713
767
  };
714
768
  };
715
- var setScope = function setScope(_ref29) {
716
- var schema = _ref29.schema,
717
- scope = _ref29.scope;
769
+ var setScope = function setScope(_ref31) {
770
+ var schema = _ref31.schema,
771
+ scope = _ref31.scope;
718
772
  return {
719
773
  path: "".concat(fieldKeysFromSchema(schema).scope, ".value"),
720
774
  value: scope
721
775
  };
722
776
  };
723
- var removeArrayItem = function removeArrayItem(_ref30) {
724
- var values = _ref30.values,
725
- fieldKey = _ref30.fieldKey,
726
- index = _ref30.index;
777
+ var removeArrayItem = function removeArrayItem(_ref32) {
778
+ var values = _ref32.values,
779
+ fieldKey = _ref32.fieldKey,
780
+ index = _ref32.index;
727
781
  var list = asArray(valueAt({
728
782
  values: values,
729
783
  key: fieldKey
@@ -750,6 +804,35 @@ var removeArrayItem = function removeArrayItem(_ref30) {
750
804
  }
751
805
  return result;
752
806
  };
807
+ var clearArrayItems = function clearArrayItems(_ref33) {
808
+ var values = _ref33.values,
809
+ fieldKey = _ref33.fieldKey;
810
+ var list = asArray(valueAt({
811
+ values: values,
812
+ key: fieldKey
813
+ }));
814
+ var removed = list.filter(function (item) {
815
+ return item === null || item === void 0 ? void 0 : item.id;
816
+ }).map(function (item) {
817
+ return _objectSpread$b(_objectSpread$b({}, item), {}, {
818
+ _destroy: true
819
+ });
820
+ });
821
+ var result = [{
822
+ path: "".concat(fieldKey, ".value"),
823
+ value: []
824
+ }];
825
+ if (removed.length) {
826
+ var _values$fieldKey2;
827
+ // eslint-disable-next-line security/detect-object-injection
828
+ var deleted = asArray(values === null || values === void 0 || (_values$fieldKey2 = values[fieldKey]) === null || _values$fieldKey2 === void 0 ? void 0 : _values$fieldKey2.deleted);
829
+ result.push({
830
+ path: "".concat(fieldKey, ".deleted"),
831
+ value: [].concat(_toConsumableArray(deleted), _toConsumableArray(removed))
832
+ });
833
+ }
834
+ return result;
835
+ };
753
836
 
754
837
  function ownKeys$a(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
755
838
  function _objectSpread$a(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$a(Object(t), true).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$a(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
@@ -1029,6 +1112,7 @@ var MetaBlock = function MetaBlock(_ref) {
1029
1112
  children: t("neetoRules.builder.automationName")
1030
1113
  }), /*#__PURE__*/jsxs("div", {
1031
1114
  ref: nameRef,
1115
+ "data-testid": "rule-name-edit",
1032
1116
  role: handleEditName ? "button" : undefined,
1033
1117
  tabIndex: handleEditName ? 0 : undefined,
1034
1118
  className: classNames("mb-meta-input-wrap", {
@@ -1037,6 +1121,7 @@ var MetaBlock = function MetaBlock(_ref) {
1037
1121
  onClick: handleEditName,
1038
1122
  children: [/*#__PURE__*/jsx("span", {
1039
1123
  className: "mb-meta-name-display",
1124
+ "data-testid": "rule-name",
1040
1125
  children: rule.name
1041
1126
  }), /*#__PURE__*/jsx("span", {
1042
1127
  "aria-hidden": true,
@@ -1058,8 +1143,10 @@ var MetaBlock = function MetaBlock(_ref) {
1058
1143
  })]
1059
1144
  }), /*#__PURE__*/jsxs("label", {
1060
1145
  className: "mb-meta-active",
1146
+ "data-testid": "rule-active-label",
1061
1147
  children: [/*#__PURE__*/jsx("input", {
1062
1148
  checked: rule.active,
1149
+ "data-testid": "rule-active-checkbox",
1063
1150
  readOnly: !handleToggleActive,
1064
1151
  type: "checkbox",
1065
1152
  onChange: handleToggleActive || undefined
@@ -1317,6 +1404,8 @@ var ActionRow = function ActionRow(_ref) {
1317
1404
  });
1318
1405
  var configLabel = mediumLabel || sentencify(option === null || option === void 0 ? void 0 : option.placeholder);
1319
1406
  var isConfigured = isNotEmpty(action === null || action === void 0 ? void 0 : action.metadata);
1407
+ // A host that shows no value label still needs the token to read as filled.
1408
+ var configState = configValue || isConfigured ? TOKEN_STATE.FILLED : TOKEN_STATE.MUTED;
1320
1409
  var _useClearingHover = useClearingHover(),
1321
1410
  clearing = _useClearingHover.clearing,
1322
1411
  clearingHoverProps = _useClearingHover.clearingHoverProps;
@@ -1355,7 +1444,7 @@ var ActionRow = function ActionRow(_ref) {
1355
1444
  children: verbLabel
1356
1445
  }), hasParamTail ? /*#__PURE__*/jsx(Token, {
1357
1446
  dataTestid: "action-config-value-".concat(index),
1358
- state: configValue ? TOKEN_STATE.FILLED : TOKEN_STATE.MUTED,
1447
+ state: configState,
1359
1448
  active: isActive({
1360
1449
  type: BUILDER_ANCHORS.ACTION_CONFIG,
1361
1450
  index: index
@@ -1403,7 +1492,7 @@ var ActionRow = function ActionRow(_ref) {
1403
1492
  index: index
1404
1493
  }),
1405
1494
  dataTestid: "action-config-value-".concat(index),
1406
- state: configValue ? TOKEN_STATE.FILLED : TOKEN_STATE.MUTED,
1495
+ state: configState,
1407
1496
  invalid: isInvalid({
1408
1497
  type: BUILDER_ANCHORS.ACTION_CONFIG,
1409
1498
  index: index
@@ -1626,6 +1715,10 @@ var WhenBlock = function WhenBlock(_ref) {
1626
1715
  type: BUILDER_ANCHORS.TRIGGER_LEAD_TIME,
1627
1716
  index: index
1628
1717
  }),
1718
+ invalid: isInvalid({
1719
+ type: BUILDER_ANCHORS.TRIGGER_LEAD_TIME,
1720
+ index: index
1721
+ }),
1629
1722
  onClick: handleToken && function () {
1630
1723
  return handleToken({
1631
1724
  type: BUILDER_ANCHORS.TRIGGER_LEAD_TIME,
@@ -1836,6 +1929,24 @@ var useRuleModel = function useRuleModel(schema) {
1836
1929
  fieldKey: fieldKeysFromSchema(schema).actions,
1837
1930
  index: index
1838
1931
  }));
1932
+ },
1933
+ clearTriggers: function clearTriggers() {
1934
+ return applyAll(clearArrayItems({
1935
+ values: values,
1936
+ fieldKey: fieldKeysFromSchema(schema).triggers
1937
+ }));
1938
+ },
1939
+ clearConditions: function clearConditions() {
1940
+ return applyAll(clearArrayItems({
1941
+ values: values,
1942
+ fieldKey: fieldKeysFromSchema(schema).conditions
1943
+ }));
1944
+ },
1945
+ clearActions: function clearActions() {
1946
+ return applyAll(clearArrayItems({
1947
+ values: values,
1948
+ fieldKey: fieldKeysFromSchema(schema).actions
1949
+ }));
1839
1950
  }
1840
1951
  };
1841
1952
  };
@@ -1982,9 +2093,9 @@ var nextTriggers = function nextTriggers(_ref10) {
1982
2093
  name: value
1983
2094
  }]);
1984
2095
  }
1985
- return [{
2096
+ return [_objectSpread$4(_objectSpread$4({}, rule.triggers[0]), {}, {
1986
2097
  name: value
1987
- }];
2098
+ })];
1988
2099
  };
1989
2100
  var nextConditionAt = function nextConditionAt(_ref11) {
1990
2101
  var _field$allowMatching;
@@ -2117,7 +2228,7 @@ var nextActionRecipientAt = function nextActionRecipientAt(_ref14) {
2117
2228
  });
2118
2229
  };
2119
2230
  var descriptorFor = function descriptorFor(_ref15) {
2120
- var _schema$actor2, _schema$conditions2;
2231
+ var _schema$actor2;
2121
2232
  var anchor = _ref15.anchor,
2122
2233
  schema = _ref15.schema,
2123
2234
  rule = _ref15.rule,
@@ -2163,7 +2274,10 @@ var descriptorFor = function descriptorFor(_ref15) {
2163
2274
  title: t("neetoRules.builder.panes.addCondition"),
2164
2275
  subtitle: t("neetoRules.builder.panes.condFieldSubtitle"),
2165
2276
  cascade: true,
2166
- options: (((_schema$conditions2 = schema.conditions) === null || _schema$conditions2 === void 0 ? void 0 : _schema$conditions2.fields) || []).map(function (field) {
2277
+ options: offeredConditionFields({
2278
+ schema: schema,
2279
+ rule: rule
2280
+ }).map(function (field) {
2167
2281
  return {
2168
2282
  label: field.paneLabel || field.label,
2169
2283
  value: optionValue(field),
@@ -2177,7 +2291,7 @@ var descriptorFor = function descriptorFor(_ref15) {
2177
2291
  };
2178
2292
  case BUILDER_ANCHORS.COND_OP_TOGGLE:
2179
2293
  {
2180
- var _schema$conditions3;
2294
+ var _schema$conditions2;
2181
2295
  var field = findField({
2182
2296
  schema: schema,
2183
2297
  value: conditionAt({
@@ -2185,7 +2299,7 @@ var descriptorFor = function descriptorFor(_ref15) {
2185
2299
  index: index
2186
2300
  }).field
2187
2301
  });
2188
- var labels = ((_schema$conditions3 = schema.conditions) === null || _schema$conditions3 === void 0 ? void 0 : _schema$conditions3.operatorLabels) || {};
2302
+ var labels = ((_schema$conditions2 = schema.conditions) === null || _schema$conditions2 === void 0 ? void 0 : _schema$conditions2.operatorLabels) || {};
2189
2303
  var verbs = (field === null || field === void 0 ? void 0 : field.allowMatching) || [];
2190
2304
  var fieldLabel = (field === null || field === void 0 ? void 0 : field.paneLabel) || (field === null || field === void 0 ? void 0 : field.label) || "";
2191
2305
  var isContains = isNotEmpty(verbs) && verbs.every(isContainsVerb);
@@ -2231,7 +2345,7 @@ var descriptorFor = function descriptorFor(_ref15) {
2231
2345
  case BUILDER_ANCHORS.ACTION_ADD:
2232
2346
  case BUILDER_ANCHORS.ACTION_CHANNEL:
2233
2347
  {
2234
- var _schema$actions11, _schema$actions12, _channelOf;
2348
+ var _schema$actions11, _channelOf;
2235
2349
  var isSwap = anchor === BUILDER_ANCHORS.ACTION_CHANNEL;
2236
2350
  var channelMetaFor = function channelMetaFor(value) {
2237
2351
  var _schema$actions10;
@@ -2240,13 +2354,10 @@ var descriptorFor = function descriptorFor(_ref15) {
2240
2354
  ((_schema$actions10 = schema.actions) === null || _schema$actions10 === void 0 || (_schema$actions10 = _schema$actions10.channelMeta) === null || _schema$actions10 === void 0 ? void 0 : _schema$actions10[value]) || {}
2241
2355
  );
2242
2356
  };
2243
- var rank = function rank(value) {
2244
- var idx = SWAP_CHANNEL_ORDER.indexOf(value);
2245
- return idx === -1 ? SWAP_CHANNEL_ORDER.length : idx;
2246
- };
2247
- var sourceOptions = isSwap ? _toConsumableArray(((_schema$actions11 = schema.actions) === null || _schema$actions11 === void 0 ? void 0 : _schema$actions11.options) || []).sort(function (optionA, optionB) {
2248
- return rank(optionValue(optionA)) - rank(optionValue(optionB));
2249
- }) : ((_schema$actions12 = schema.actions) === null || _schema$actions12 === void 0 ? void 0 : _schema$actions12.options) || [];
2357
+
2358
+ // Both panes list the host's actions in the order it declared them;
2359
+ // re-ranking only the swap pane made the two disagree.
2360
+ var sourceOptions = ((_schema$actions11 = schema.actions) === null || _schema$actions11 === void 0 ? void 0 : _schema$actions11.options) || [];
2250
2361
  return {
2251
2362
  title: isSwap ? t("neetoRules.builder.panes.actionSwapTitle") : t("neetoRules.builder.panes.actionAddTitle"),
2252
2363
  subtitle: isSwap ? t("neetoRules.builder.panes.actionSwapSubtitle") : t("neetoRules.builder.panes.actionAddSubtitle"),
@@ -2276,7 +2387,7 @@ var descriptorFor = function descriptorFor(_ref15) {
2276
2387
  }
2277
2388
  case BUILDER_ANCHORS.ACTION_RECIPIENT:
2278
2389
  {
2279
- var _schema$actions13;
2390
+ var _schema$actions12;
2280
2391
  var action = actionAt({
2281
2392
  rule: rule,
2282
2393
  index: index
@@ -2286,7 +2397,7 @@ var descriptorFor = function descriptorFor(_ref15) {
2286
2397
  action: action
2287
2398
  });
2288
2399
  // eslint-disable-next-line security/detect-object-injection
2289
- var meta = ((_schema$actions13 = schema.actions) === null || _schema$actions13 === void 0 || (_schema$actions13 = _schema$actions13.channelMeta) === null || _schema$actions13 === void 0 ? void 0 : _schema$actions13[channel]) || {};
2400
+ var meta = ((_schema$actions12 = schema.actions) === null || _schema$actions12 === void 0 || (_schema$actions12 = _schema$actions12.channelMeta) === null || _schema$actions12 === void 0 ? void 0 : _schema$actions12[channel]) || {};
2290
2401
  var option = findActionOption({
2291
2402
  schema: schema,
2292
2403
  name: channel
@@ -2402,9 +2513,9 @@ var commitFor = function commitFor(_ref16) {
2402
2513
  }]));
2403
2514
  return "stay";
2404
2515
  }
2405
- setTriggers([{
2516
+ setTriggers([_objectSpread$4(_objectSpread$4({}, rule.triggers[0]), {}, {
2406
2517
  name: value
2407
- }]);
2518
+ })]);
2408
2519
  var leadTime = (_schema$triggers5 = schema.triggers) === null || _schema$triggers5 === void 0 ? void 0 : _schema$triggers5.leadTime;
2409
2520
  if (leadTime !== null && leadTime !== void 0 && leadTime.fieldKey && (leadTime.appliesTo || []).includes(value) && !rule.leadTime) {
2410
2521
  var _leadTime$default;
@@ -2671,7 +2782,7 @@ var applyPreview = function applyPreview(_ref19) {
2671
2782
  function ownKeys$3(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
2672
2783
  function _objectSpread$3(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$3(Object(t), true).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$3(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
2673
2784
  var Canvas = function Canvas(_ref) {
2674
- var _schema$scope, _schema$scope2, _schema$conditions, _schema$triggers, _schema$delay, _schema$meta$showName, _schema$meta;
2785
+ var _schema$scope, _schema$triggers, _schema$delay, _schema$meta$showName, _schema$meta;
2675
2786
  var schema = _ref.schema;
2676
2787
  var _useTranslation = useTranslation(),
2677
2788
  t = _useTranslation.t;
@@ -2684,15 +2795,16 @@ var Canvas = function Canvas(_ref) {
2684
2795
  var _useRuleModel = useRuleModel(schema),
2685
2796
  rule = _useRuleModel.rule,
2686
2797
  fieldKeys = _useRuleModel.fieldKeys,
2687
- setTriggers = _useRuleModel.setTriggers,
2688
2798
  setPerformer = _useRuleModel.setPerformer,
2689
2799
  setConditions = _useRuleModel.setConditions,
2690
- setActions = _useRuleModel.setActions,
2691
2800
  setDelay = _useRuleModel.setDelay,
2692
2801
  removeCondition = _useRuleModel.removeCondition,
2693
2802
  removeAction = _useRuleModel.removeAction,
2694
2803
  setActive = _useRuleModel.setActive,
2695
- setScope = _useRuleModel.setScope;
2804
+ setScope = _useRuleModel.setScope,
2805
+ clearTriggers = _useRuleModel.clearTriggers,
2806
+ clearConditions = _useRuleModel.clearConditions,
2807
+ clearActions = _useRuleModel.clearActions;
2696
2808
  var _useUtilityStore = useUtilityStore(useShallow(function (store) {
2697
2809
  return {
2698
2810
  builderPreview: store["builderPreview"],
@@ -2737,7 +2849,7 @@ var Canvas = function Canvas(_ref) {
2737
2849
  setFlashSeq(submitCount);
2738
2850
  var timer = setTimeout(function () {
2739
2851
  return setFlashSeq(0);
2740
- }, 2200);
2852
+ }, FLASH_DURATION_MS);
2741
2853
  return function () {
2742
2854
  return clearTimeout(timer);
2743
2855
  };
@@ -2754,7 +2866,7 @@ var Canvas = function Canvas(_ref) {
2754
2866
  });
2755
2867
  };
2756
2868
  var matchesInvalid = function matchesInvalid(_ref4) {
2757
- var _schema$actions, _schema$actions$actio, _schema$actions2, _schema$actions2$rend, _schema$actions3, _schema$actions3$rend, _schema$actions4, _schema$actions4$opti, _schema$actions5, _schema$actions5$opti;
2869
+ var _schema$actions, _schema$actions$actio, _schema$actions2, _schema$actions2$rend, _schema$actions3, _schema$actions3$rend, _schema$actions4, _schema$actions4$opti, _schema$actions5, _schema$actions5$opti, _schema$actions6, _schema$actions7;
2758
2870
  var type = _ref4.type,
2759
2871
  index = _ref4.index;
2760
2872
  var conditionMeta = "".concat(fieldKeys.conditions, ".value.").concat(index, ".metadata");
@@ -2774,7 +2886,13 @@ var Canvas = function Canvas(_ref) {
2774
2886
  action: actionItem
2775
2887
  }));
2776
2888
  var flatOption = ((_schema$actions4 = schema.actions) === null || _schema$actions4 === void 0 || (_schema$actions4$opti = _schema$actions4.optionForName) === null || _schema$actions4$opti === void 0 ? void 0 : _schema$actions4$opti.call(_schema$actions4, actionItem.name)) || ((_schema$actions5 = schema.actions) === null || _schema$actions5 === void 0 || (_schema$actions5$opti = _schema$actions5.optionForChannel) === null || _schema$actions5$opti === void 0 ? void 0 : _schema$actions5$opti.call(_schema$actions5, channel));
2777
- var recipientFields = [].concat(_toConsumableArray(hasRecipientEditor || hasRecipientField ? ["emails"] : []), _toConsumableArray((flatOption === null || flatOption === void 0 ? void 0 : flatOption.type) === "smsToNumbers" ? ["phoneNumbers"] : []));
2889
+ var recipientConfig = [].concat(_toConsumableArray((((_schema$actions6 = schema.actions) === null || _schema$actions6 === void 0 ? void 0 : _schema$actions6.options) || []).flatMap(function (option) {
2890
+ return option.recipients || [];
2891
+ })), _toConsumableArray(((_schema$actions7 = schema.actions) === null || _schema$actions7 === void 0 ? void 0 : _schema$actions7.recipients) || [])).find(function (item) {
2892
+ var _item$value;
2893
+ return ((_item$value = item.value) !== null && _item$value !== void 0 ? _item$value : item.id) === actionItem.recipient;
2894
+ });
2895
+ var recipientFields = [].concat(_toConsumableArray(hasRecipientEditor || hasRecipientField ? [RECIPIENT_STORAGE_FIELDS.emails] : []), _toConsumableArray(recipientConfig !== null && recipientConfig !== void 0 && recipientConfig.field ? [recipientStorageField(recipientConfig.field)] : []), _toConsumableArray((flatOption === null || flatOption === void 0 ? void 0 : flatOption.type) === SMS_TO_NUMBERS ? [RECIPIENT_STORAGE_FIELDS.phoneNumbers] : []));
2778
2896
  switch (type) {
2779
2897
  case BUILDER_ANCHORS.TRIGGER_ACTOR:
2780
2898
  {
@@ -2784,6 +2902,10 @@ var Canvas = function Canvas(_ref) {
2784
2902
  prefix: "".concat(actorKey, ".value")
2785
2903
  });
2786
2904
  }
2905
+ case BUILDER_ANCHORS.TRIGGER_LEAD_TIME:
2906
+ return hasErrorAt({
2907
+ prefix: "".concat(fieldKeys.leadTime, ".value")
2908
+ });
2787
2909
  case BUILDER_ANCHORS.COND_FIELD:
2788
2910
  return hasErrorAt({
2789
2911
  prefix: "".concat(fieldKeys.conditions, ".value.").concat(index, ".field")
@@ -2804,7 +2926,9 @@ var Canvas = function Canvas(_ref) {
2804
2926
  exclude: recipientFields
2805
2927
  });
2806
2928
  case BUILDER_ANCHORS.ACTION_RECIPIENT:
2807
- return recipientFields.some(function (field) {
2929
+ return hasErrorAt({
2930
+ prefix: "".concat(fieldKeys.actions, ".value.").concat(index, ".name")
2931
+ }) || recipientFields.some(function (field) {
2808
2932
  return hasErrorAt({
2809
2933
  prefix: "".concat(actionMeta, ".").concat(field)
2810
2934
  });
@@ -2882,8 +3006,6 @@ var Canvas = function Canvas(_ref) {
2882
3006
  return (action === null || action === void 0 ? void 0 : action.channel) || (action === null || action === void 0 ? void 0 : action.name);
2883
3007
  });
2884
3008
  var isScopeEnabled = (schema === null || schema === void 0 || (_schema$scope = schema.scope) === null || _schema$scope === void 0 ? void 0 : _schema$scope.enabled) && isTriggerSet && hasAction;
2885
- var isScopeComplete = !(schema !== null && schema !== void 0 && (_schema$scope2 = schema.scope) !== null && _schema$scope2 !== void 0 && _schema$scope2.enabled) || isNotEmpty(rule.scope || []);
2886
- var isComplete = isRuleComplete(rule) && isScopeComplete;
2887
3009
  var handleRemoveScope = function handleRemoveScope(index) {
2888
3010
  closePaneIfTargeting({
2889
3011
  anchors: [BUILDER_ANCHORS.SCOPE_PHONE_FIELD],
@@ -2893,7 +3015,10 @@ var Canvas = function Canvas(_ref) {
2893
3015
  return i !== index;
2894
3016
  }));
2895
3017
  };
2896
- var conditionFields = (schema === null || schema === void 0 || (_schema$conditions = schema.conditions) === null || _schema$conditions === void 0 ? void 0 : _schema$conditions.fields) || [];
3018
+ var conditionFields = offeredConditionFields({
3019
+ schema: schema,
3020
+ rule: rule
3021
+ });
2897
3022
  var canAddCondition = isNotEmpty(conditionFields);
2898
3023
  var leadTimeAppliesTo = (schema === null || schema === void 0 || (_schema$triggers = schema.triggers) === null || _schema$triggers === void 0 || (_schema$triggers = _schema$triggers.leadTime) === null || _schema$triggers === void 0 ? void 0 : _schema$triggers.appliesTo) || [];
2899
3024
  var hasLeadTimeTrigger = rule.triggers.some(function (trigger) {
@@ -2917,12 +3042,12 @@ var Canvas = function Canvas(_ref) {
2917
3042
  };
2918
3043
  var handleClearTrigger = function handleClearTrigger() {
2919
3044
  var _schema$actor2;
2920
- setTriggers([]);
3045
+ clearTriggers();
2921
3046
  // Hosts without an actor pane can never re-set it, and null fails its validation.
2922
3047
  if ((_schema$actor2 = schema.actor) !== null && _schema$actor2 !== void 0 && _schema$actor2.enabled) setPerformer(null);
2923
- setConditions([]);
3048
+ clearConditions();
2924
3049
  setDelay(null);
2925
- setActions([]);
3050
+ clearActions();
2926
3051
  setScope([]);
2927
3052
  closePane();
2928
3053
  };
@@ -2944,7 +3069,7 @@ var Canvas = function Canvas(_ref) {
2944
3069
  );
2945
3070
  };
2946
3071
  return /*#__PURE__*/jsx("div", {
2947
- className: "neeto-rules-builder",
3072
+ className: "neeto-rules-builder nrb-atoms",
2948
3073
  children: /*#__PURE__*/jsxs("div", {
2949
3074
  className: "mb-canvas neeto-rules-main-card",
2950
3075
  children: [/*#__PURE__*/jsx(WhenBlock, {
@@ -2986,6 +3111,7 @@ var Canvas = function Canvas(_ref) {
2986
3111
  }) : /*#__PURE__*/jsx("div", {
2987
3112
  className: "mb-add-row",
2988
3113
  children: /*#__PURE__*/jsx(Button, {
3114
+ "data-testid": "rule-delay-add",
2989
3115
  icon: Plus,
2990
3116
  iconPosition: "left",
2991
3117
  label: t("neetoRules.common.addDelay"),
@@ -3017,24 +3143,22 @@ var Canvas = function Canvas(_ref) {
3017
3143
  onRemoveScope: handleRemoveScope,
3018
3144
  onToken: openPane
3019
3145
  })]
3020
- }), isComplete && /*#__PURE__*/jsxs(Fragment$1, {
3021
- children: [/*#__PURE__*/jsx(Connector, {
3022
- active: true
3023
- }), /*#__PURE__*/jsx(MetaBlock, {
3024
- rule: rule,
3025
- isInvalid: isInvalid({
3146
+ }), /*#__PURE__*/jsx(Connector, {
3147
+ active: true
3148
+ }), /*#__PURE__*/jsx(MetaBlock, {
3149
+ rule: rule,
3150
+ isInvalid: isInvalid({
3151
+ type: BUILDER_ANCHORS.META_NAME
3152
+ }),
3153
+ showName: (_schema$meta$showName = schema === null || schema === void 0 || (_schema$meta = schema.meta) === null || _schema$meta === void 0 ? void 0 : _schema$meta.showName) !== null && _schema$meta$showName !== void 0 ? _schema$meta$showName : true,
3154
+ onEditName: function onEditName() {
3155
+ return openPane({
3026
3156
  type: BUILDER_ANCHORS.META_NAME
3027
- }),
3028
- showName: (_schema$meta$showName = schema === null || schema === void 0 || (_schema$meta = schema.meta) === null || _schema$meta === void 0 ? void 0 : _schema$meta.showName) !== null && _schema$meta$showName !== void 0 ? _schema$meta$showName : true,
3029
- onEditName: function onEditName() {
3030
- return openPane({
3031
- type: BUILDER_ANCHORS.META_NAME
3032
- });
3033
- },
3034
- onToggleActive: function onToggleActive(event) {
3035
- return setActive(event.target.checked);
3036
- }
3037
- })]
3157
+ });
3158
+ },
3159
+ onToggleActive: function onToggleActive(event) {
3160
+ return setActive(event.target.checked);
3161
+ }
3038
3162
  })]
3039
3163
  })
3040
3164
  });
@@ -3045,6 +3169,7 @@ var ACTION_CONFIG_TYPES = {
3045
3169
  multiSelect: "multiSelect",
3046
3170
  dropdown: "dropdown",
3047
3171
  note: "note",
3172
+ list: "list",
3048
3173
  textarea: "textarea",
3049
3174
  number: "number",
3050
3175
  text: "text",
@@ -3106,6 +3231,7 @@ var ActionConfigFields = function ActionConfigFields(_ref) {
3106
3231
  };
3107
3232
  var noMatches = /*#__PURE__*/jsx("div", {
3108
3233
  className: "mb-pane-empty",
3234
+ "data-testid": "pane-no-matches",
3109
3235
  children: t("neetoRules.builder.noMatches")
3110
3236
  });
3111
3237
  if (type === ACTION_CONFIG_TYPES.emailChannel) {
@@ -3114,7 +3240,7 @@ var ActionConfigFields = function ActionConfigFields(_ref) {
3114
3240
  var bodyPath = "".concat(name, ".body");
3115
3241
  return /*#__PURE__*/jsxs("div", {
3116
3242
  className: "flex flex-col gap-4",
3117
- children: [/*#__PURE__*/jsx(Input, {
3243
+ children: [!(option !== null && option !== void 0 && option.hideSubject) && /*#__PURE__*/jsx(Input, {
3118
3244
  required: true,
3119
3245
  error: fieldError(subjectPath),
3120
3246
  label: t("neetoRules.builder.config.subject"),
@@ -3147,7 +3273,7 @@ var ActionConfigFields = function ActionConfigFields(_ref) {
3147
3273
  setFieldValue(valuePath, current.includes(value) ? current.filter(isNot(value)) : [].concat(_toConsumableArray(current), [value]));
3148
3274
  };
3149
3275
  return /*#__PURE__*/jsxs("div", {
3150
- className: "flex flex-col gap-y-1",
3276
+ className: "mb-pane-list flex flex-col",
3151
3277
  children: [filtered.map(function (item) {
3152
3278
  return /*#__PURE__*/jsx(Checkbox, {
3153
3279
  checked: current.includes(item.value),
@@ -3189,6 +3315,14 @@ var ActionConfigFields = function ActionConfigFields(_ref) {
3189
3315
  })
3190
3316
  });
3191
3317
  }
3318
+ if (type === ACTION_CONFIG_TYPES.list) {
3319
+ return /*#__PURE__*/jsxs("div", {
3320
+ className: "flex flex-col gap-2",
3321
+ children: [/*#__PURE__*/jsx(ListField, {
3322
+ name: valuePath
3323
+ }), hintBlock]
3324
+ });
3325
+ }
3192
3326
  if (type === ACTION_CONFIG_TYPES.note) {
3193
3327
  var _action$metadata2;
3194
3328
  return /*#__PURE__*/jsxs("div", {
@@ -3434,7 +3568,7 @@ var ConfigPane = function ConfigPane(_ref) {
3434
3568
  while (1) switch (_context.n) {
3435
3569
  case 0:
3436
3570
  _context.n = 1;
3437
- return validate(["emails"]);
3571
+ return validate([RECIPIENT_STORAGE_FIELDS.emails]);
3438
3572
  case 1:
3439
3573
  if (_context.v) {
3440
3574
  _context.n = 2;
@@ -3463,7 +3597,6 @@ var ConfigPane = function ConfigPane(_ref) {
3463
3597
  };
3464
3598
  }();
3465
3599
  useHotkeys(SHORTCUTS["continue"].sequence, handleContinue, {
3466
- enabled: shouldAdvanceToRecipient,
3467
3600
  mode: "global"
3468
3601
  });
3469
3602
  return /*#__PURE__*/jsxs(Fragment, {
@@ -3471,6 +3604,7 @@ var ConfigPane = function ConfigPane(_ref) {
3471
3604
  children: /*#__PURE__*/jsxs("div", {
3472
3605
  className: "flex w-full flex-col gap-y-2",
3473
3606
  children: [/*#__PURE__*/jsx(Typography, {
3607
+ "data-testid": "pane-title",
3474
3608
  variant: "h5",
3475
3609
  children: title
3476
3610
  }), configSubtitle && /*#__PURE__*/jsx(Typography, {
@@ -3480,6 +3614,7 @@ var ConfigPane = function ConfigPane(_ref) {
3480
3614
  }), showSearch && /*#__PURE__*/jsx("div", {
3481
3615
  className: "mb-pane-search",
3482
3616
  children: /*#__PURE__*/jsx(Input, {
3617
+ dataTestid: "pane-search",
3483
3618
  placeholder: t("neetoRules.builder.searchPlaceholder"),
3484
3619
  prefix: /*#__PURE__*/jsx(Search, {}),
3485
3620
  size: "large",
@@ -3499,20 +3634,14 @@ var ConfigPane = function ConfigPane(_ref) {
3499
3634
  message: disabledReason,
3500
3635
  selectedField: flatOption
3501
3636
  })
3502
- }), isSms ? /*#__PURE__*/jsxs(Fragment, {
3503
- children: [/*#__PURE__*/jsx(SmsFields, {
3504
- action: action,
3505
- index: index,
3506
- name: name,
3507
- shouldAutoFocus: true,
3508
- selectedField: flatOption,
3509
- showPhoneNumberInput: false
3510
- }), /*#__PURE__*/jsx(Typography, {
3511
- className: "mt-2",
3512
- color: "muted",
3513
- variant: "body3",
3514
- children: t("neetoRules.builder.config.smsSegmentHint")
3515
- })]
3637
+ }), isSms ? /*#__PURE__*/jsx(SmsFields, {
3638
+ action: action,
3639
+ index: index,
3640
+ name: name,
3641
+ shouldAutoFocus: true,
3642
+ hint: t("neetoRules.builder.config.smsSegmentHint"),
3643
+ selectedField: flatOption,
3644
+ showPhoneNumberInput: false
3516
3645
  }) : (_hostRenderConfig = hostRenderConfig === null || hostRenderConfig === void 0 ? void 0 : hostRenderConfig({
3517
3646
  name: name,
3518
3647
  action: action,
@@ -3525,8 +3654,9 @@ var ConfigPane = function ConfigPane(_ref) {
3525
3654
  option: flatOption
3526
3655
  })]
3527
3656
  })
3528
- }), shouldAdvanceToRecipient && /*#__PURE__*/jsx(Panel.Footer, {
3657
+ }), /*#__PURE__*/jsx(Panel.Footer, {
3529
3658
  children: /*#__PURE__*/jsx(Button, {
3659
+ "data-testid": "continue-button",
3530
3660
  label: t("neetoRules.buttons.continue"),
3531
3661
  size: "lg",
3532
3662
  onClick: handleContinue
@@ -3543,7 +3673,9 @@ var DelayPane = function DelayPane(_ref) {
3543
3673
  var _useRuleModel = useRuleModel(schema),
3544
3674
  fieldKeys = _useRuleModel.fieldKeys;
3545
3675
  var _useFormikContext = useFormikContext(),
3546
- setFieldValue = _useFormikContext.setFieldValue;
3676
+ setFieldValue = _useFormikContext.setFieldValue,
3677
+ setFieldTouched = _useFormikContext.setFieldTouched,
3678
+ getFieldMeta = _useFormikContext.getFieldMeta;
3547
3679
  var bodyRef = useRef(null);
3548
3680
  var name = fieldKeys.delay;
3549
3681
  var _useField = useField("".concat(name, ".value")),
@@ -3552,12 +3684,18 @@ var DelayPane = function DelayPane(_ref) {
3552
3684
  var units = normalizeOptions((_schema$delay = schema.delay) === null || _schema$delay === void 0 ? void 0 : _schema$delay.units);
3553
3685
  var unitOptions = isNotEmpty(units) ? units : DEFAULT_DELAY_UNITS;
3554
3686
  usePaneValidation("".concat(name, ".value"));
3687
+ useEffect(function () {
3688
+ if ((value === null || value === void 0 ? void 0 : value.value) === undefined) return;
3689
+ if (getFieldMeta("".concat(name, ".value.value")).touched) return;
3690
+ setFieldTouched("".concat(name, ".value.value"), true, false);
3691
+ // eslint-disable-next-line react-hooks/exhaustive-deps
3692
+ }, [value === null || value === void 0 ? void 0 : value.value]);
3555
3693
  useEffect(function () {
3556
3694
  if (isEmpty(value || {})) {
3557
3695
  var _unitOptions$0$value, _unitOptions$;
3558
3696
  setFieldValue("".concat(name, ".value"), {
3559
- value: 10,
3560
- unit: (_unitOptions$0$value = (_unitOptions$ = unitOptions[0]) === null || _unitOptions$ === void 0 ? void 0 : _unitOptions$.value) !== null && _unitOptions$0$value !== void 0 ? _unitOptions$0$value : "minutes"
3697
+ value: DEFAULT_DELAY_VALUE,
3698
+ unit: (_unitOptions$0$value = (_unitOptions$ = unitOptions[0]) === null || _unitOptions$ === void 0 ? void 0 : _unitOptions$.value) !== null && _unitOptions$0$value !== void 0 ? _unitOptions$0$value : DEFAULT_DELAY_UNITS[0].value
3561
3699
  });
3562
3700
  }
3563
3701
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -3575,6 +3713,7 @@ var DelayPane = function DelayPane(_ref) {
3575
3713
  children: /*#__PURE__*/jsxs("div", {
3576
3714
  className: "flex flex-col gap-y-1",
3577
3715
  children: [/*#__PURE__*/jsx(Typography, {
3716
+ "data-testid": "pane-title",
3578
3717
  variant: "h5",
3579
3718
  children: t("neetoRules.common.addDelay")
3580
3719
  }), /*#__PURE__*/jsx(Typography, {
@@ -3595,13 +3734,15 @@ var DelayPane = function DelayPane(_ref) {
3595
3734
  className: "flex items-start gap-x-2",
3596
3735
  children: [/*#__PURE__*/jsx(Input$1, {
3597
3736
  className: "w-44",
3598
- max: 999,
3599
- min: 1,
3737
+ dataTestid: "delay-value",
3738
+ max: MAX_DELAY_VALUE,
3739
+ min: MIN_DELAY_VALUE,
3600
3740
  name: "".concat(name, ".value.value"),
3601
3741
  placeholder: t("neetoRules.placeholders.enterDelay"),
3602
3742
  size: "large",
3603
3743
  type: "number"
3604
3744
  }), /*#__PURE__*/jsx(Select, {
3745
+ dataTestid: "delay-unit",
3605
3746
  defaultValue: value === null || value === void 0 ? void 0 : value.unit,
3606
3747
  name: "".concat(name, ".value.unit"),
3607
3748
  options: unitOptions,
@@ -3635,11 +3776,13 @@ var asText = function asText(value) {
3635
3776
  var NumberStepper = function NumberStepper(_ref) {
3636
3777
  var value = _ref.value,
3637
3778
  onChange = _ref.onChange,
3779
+ dataTestid = _ref.dataTestid,
3638
3780
  label = _ref.label,
3639
3781
  _ref$min = _ref.min,
3640
- min = _ref$min === void 0 ? 1 : _ref$min,
3782
+ min = _ref$min === void 0 ? STEPPER_MIN_VALUE : _ref$min,
3641
3783
  max = _ref.max,
3642
- required = _ref.required;
3784
+ required = _ref.required,
3785
+ error = _ref.error;
3643
3786
  var _useTranslation = useTranslation(),
3644
3787
  t = _useTranslation.t;
3645
3788
  var _useState = useState(null),
@@ -3664,15 +3807,41 @@ var NumberStepper = function NumberStepper(_ref) {
3664
3807
  max: max
3665
3808
  }));
3666
3809
  };
3667
- return /*#__PURE__*/jsxs("div", {
3810
+ return /*#__PURE__*/jsx("div", {
3668
3811
  className: "mb-stepper",
3669
- children: [/*#__PURE__*/jsx(Input, {
3812
+ children: /*#__PURE__*/jsx(Input, {
3813
+ dataTestid: dataTestid,
3814
+ error: error,
3670
3815
  label: label,
3671
3816
  min: min,
3672
3817
  required: required,
3673
3818
  autoFocus: true,
3674
3819
  type: "number",
3675
3820
  value: display,
3821
+ suffix: /*#__PURE__*/jsxs("div", {
3822
+ className: "mb-stepper-controls",
3823
+ children: [/*#__PURE__*/jsx("button", {
3824
+ "aria-label": t("neetoRules.builder.aria.increase"),
3825
+ className: "mb-stepper-btn",
3826
+ "data-testid": "stepper-increase",
3827
+ tabIndex: SKIP_TAB_INDEX,
3828
+ type: "button",
3829
+ onClick: function onClick() {
3830
+ return step(STEPPER_DELTA.INCREMENT);
3831
+ },
3832
+ children: /*#__PURE__*/jsx(Up, {})
3833
+ }), /*#__PURE__*/jsx("button", {
3834
+ "aria-label": t("neetoRules.builder.aria.decrease"),
3835
+ className: "mb-stepper-btn",
3836
+ "data-testid": "stepper-decrease",
3837
+ tabIndex: SKIP_TAB_INDEX,
3838
+ type: "button",
3839
+ onClick: function onClick() {
3840
+ return step(STEPPER_DELTA.DECREMENT);
3841
+ },
3842
+ children: /*#__PURE__*/jsx(Down, {})
3843
+ })]
3844
+ }),
3676
3845
  onBlur: function onBlur() {
3677
3846
  return setDraft(null);
3678
3847
  },
@@ -3682,28 +3851,7 @@ var NumberStepper = function NumberStepper(_ref) {
3682
3851
  onFocus: function onFocus(event) {
3683
3852
  return event.target.select();
3684
3853
  }
3685
- }), /*#__PURE__*/jsxs("div", {
3686
- className: "mb-stepper-controls",
3687
- children: [/*#__PURE__*/jsx("button", {
3688
- "aria-label": t("neetoRules.builder.aria.increase"),
3689
- className: "mb-stepper-btn",
3690
- tabIndex: -1,
3691
- type: "button",
3692
- onClick: function onClick() {
3693
- return step(1);
3694
- },
3695
- children: /*#__PURE__*/jsx(Up, {})
3696
- }), /*#__PURE__*/jsx("button", {
3697
- "aria-label": t("neetoRules.builder.aria.decrease"),
3698
- className: "mb-stepper-btn",
3699
- tabIndex: -1,
3700
- type: "button",
3701
- onClick: function onClick() {
3702
- return step(-1);
3703
- },
3704
- children: /*#__PURE__*/jsx(Down, {})
3705
- })]
3706
- })]
3854
+ })
3707
3855
  });
3708
3856
  };
3709
3857
 
@@ -3712,7 +3860,9 @@ var LeadTimePane = function LeadTimePane(_ref) {
3712
3860
  var _useTranslation = useTranslation(),
3713
3861
  t = _useTranslation.t;
3714
3862
  var _useFormikContext = useFormikContext(),
3715
- setFieldValue = _useFormikContext.setFieldValue;
3863
+ setFieldValue = _useFormikContext.setFieldValue,
3864
+ setFieldTouched = _useFormikContext.setFieldTouched,
3865
+ getFieldMeta = _useFormikContext.getFieldMeta;
3716
3866
  var _useRuleModel = useRuleModel(schema),
3717
3867
  rule = _useRuleModel.rule,
3718
3868
  fieldKeys = _useRuleModel.fieldKeys;
@@ -3720,6 +3870,11 @@ var LeadTimePane = function LeadTimePane(_ref) {
3720
3870
  amount = _minutesToParts.value,
3721
3871
  unit = _minutesToParts.unit;
3722
3872
  var path = "".concat(fieldKeys.leadTime, ".value");
3873
+ var _useField = useField(path),
3874
+ _useField2 = _slicedToArray(_useField, 2),
3875
+ _useField2$ = _useField2[1],
3876
+ error = _useField2$.error,
3877
+ touched = _useField2$.touched;
3723
3878
  var update = function update(_ref2) {
3724
3879
  var value = _ref2.value,
3725
3880
  nextUnit = _ref2.unit;
@@ -3728,11 +3883,19 @@ var LeadTimePane = function LeadTimePane(_ref) {
3728
3883
  unit: nextUnit
3729
3884
  }));
3730
3885
  };
3886
+ usePaneValidation(path);
3887
+ useEffect(function () {
3888
+ if (rule.leadTime === undefined) return;
3889
+ if (getFieldMeta(path).touched) return;
3890
+ setFieldTouched(path, true, false);
3891
+ // eslint-disable-next-line react-hooks/exhaustive-deps
3892
+ }, [rule.leadTime]);
3731
3893
  return /*#__PURE__*/jsxs(Fragment, {
3732
3894
  children: [/*#__PURE__*/jsx(Panel.Header, {
3733
3895
  children: /*#__PURE__*/jsxs("div", {
3734
3896
  className: "flex flex-col gap-y-1",
3735
3897
  children: [/*#__PURE__*/jsx(Typography, {
3898
+ "data-testid": "pane-title",
3736
3899
  variant: "h5",
3737
3900
  children: t("neetoRules.builder.leadTimeTitle")
3738
3901
  }), /*#__PURE__*/jsx(Typography, {
@@ -3743,32 +3906,41 @@ var LeadTimePane = function LeadTimePane(_ref) {
3743
3906
  })
3744
3907
  }), /*#__PURE__*/jsx(Panel.Body, {
3745
3908
  children: /*#__PURE__*/jsxs("div", {
3746
- className: "flex items-end gap-x-3",
3747
- children: [/*#__PURE__*/jsx("div", {
3748
- className: "flex-1",
3749
- children: /*#__PURE__*/jsx(NumberStepper, {
3750
- label: t("neetoRules.builder.before"),
3751
- value: amount,
3752
- onChange: function onChange(value) {
3753
- return update({
3754
- value: value === "" ? 0 : value,
3755
- unit: unit
3756
- });
3757
- }
3758
- })
3759
- }), /*#__PURE__*/jsx("div", {
3760
- className: "w-32 shrink-0",
3761
- children: /*#__PURE__*/jsx(Select$1, {
3762
- isSearchable: false,
3763
- options: LEAD_TIME_UNITS,
3764
- value: unit,
3765
- onChange: function onChange(nextUnit) {
3766
- return update({
3767
- value: amount,
3768
- unit: nextUnit
3769
- });
3770
- }
3771
- })
3909
+ className: "flex flex-col gap-y-1.5",
3910
+ children: [/*#__PURE__*/jsx(Typography, {
3911
+ variant: "body2",
3912
+ weight: "medium",
3913
+ children: t("neetoRules.builder.before")
3914
+ }), /*#__PURE__*/jsxs("div", {
3915
+ className: "flex items-start gap-x-3",
3916
+ children: [/*#__PURE__*/jsx("div", {
3917
+ className: "flex-1",
3918
+ children: /*#__PURE__*/jsx(NumberStepper, {
3919
+ dataTestid: "lead-time",
3920
+ error: touched ? error : "",
3921
+ value: amount,
3922
+ onChange: function onChange(value) {
3923
+ return update({
3924
+ value: value === "" ? 0 : value,
3925
+ unit: unit
3926
+ });
3927
+ }
3928
+ })
3929
+ }), /*#__PURE__*/jsx("div", {
3930
+ className: "w-32 shrink-0",
3931
+ children: /*#__PURE__*/jsx(Select$1, {
3932
+ dataTestid: "lead-time-unit",
3933
+ isSearchable: false,
3934
+ options: LEAD_TIME_UNITS,
3935
+ value: unit,
3936
+ onChange: function onChange(nextUnit) {
3937
+ return update({
3938
+ value: amount,
3939
+ unit: nextUnit
3940
+ });
3941
+ }
3942
+ })
3943
+ })]
3772
3944
  })]
3773
3945
  })
3774
3946
  })]
@@ -3786,6 +3958,7 @@ var NamePane = function NamePane(_ref) {
3786
3958
  children: /*#__PURE__*/jsxs("div", {
3787
3959
  className: "flex flex-col gap-y-1",
3788
3960
  children: [/*#__PURE__*/jsx(Typography, {
3961
+ "data-testid": "pane-title",
3789
3962
  variant: "h5",
3790
3963
  children: t("neetoRules.builder.automationName")
3791
3964
  }), /*#__PURE__*/jsx(Typography, {
@@ -3963,12 +4136,13 @@ var OptionsPane = function OptionsPane(_ref) {
3963
4136
  if (isEmpty(filtered)) {
3964
4137
  return /*#__PURE__*/jsx("div", {
3965
4138
  className: "mb-pane-empty",
4139
+ "data-testid": "pane-no-matches",
3966
4140
  children: t("neetoRules.builder.noMatches")
3967
4141
  });
3968
4142
  }
3969
4143
  if (multi) {
3970
4144
  return /*#__PURE__*/jsx("div", {
3971
- className: "flex flex-col",
4145
+ className: "mb-pane-list flex flex-col",
3972
4146
  children: groups.map(function (_ref2) {
3973
4147
  var _ref3 = _slicedToArray(_ref2, 2),
3974
4148
  category = _ref3[0],
@@ -4020,6 +4194,7 @@ var OptionsPane = function OptionsPane(_ref) {
4020
4194
  children: /*#__PURE__*/jsxs("div", {
4021
4195
  className: "flex w-full flex-col gap-y-2",
4022
4196
  children: [/*#__PURE__*/jsx(Typography, {
4197
+ "data-testid": "pane-title",
4023
4198
  variant: "h5",
4024
4199
  children: title
4025
4200
  }), /*#__PURE__*/jsx(Typography, {
@@ -4030,6 +4205,7 @@ var OptionsPane = function OptionsPane(_ref) {
4030
4205
  className: "mb-pane-search",
4031
4206
  ref: searchRef,
4032
4207
  children: /*#__PURE__*/jsx(Input, {
4208
+ dataTestid: "pane-search",
4033
4209
  placeholder: t("neetoRules.builder.searchPlaceholder"),
4034
4210
  prefix: /*#__PURE__*/jsx(Search, {}),
4035
4211
  size: "large",
@@ -4044,6 +4220,7 @@ var OptionsPane = function OptionsPane(_ref) {
4044
4220
  children: [renderBody(), belowContent]
4045
4221
  }), cascade && /*#__PURE__*/jsx(Panel.Footer, {
4046
4222
  children: /*#__PURE__*/jsx(Button, {
4223
+ "data-testid": "continue-button",
4047
4224
  disabled: !canContinue,
4048
4225
  label: t("neetoRules.buttons.continue"),
4049
4226
  size: "lg",
@@ -4069,8 +4246,8 @@ var RecipientField = function RecipientField(_ref) {
4069
4246
  var fieldError = function fieldError(path) {
4070
4247
  return getIn(touched, path) && getIn(errors, path);
4071
4248
  };
4072
- if (field === "emails") {
4073
- var _path = "".concat(name, ".emails");
4249
+ if (field === RECIPIENT_STORAGE_FIELDS.emails) {
4250
+ var _path = "".concat(name, ".").concat(RECIPIENT_STORAGE_FIELDS.emails);
4074
4251
  var _current = getIn(values, _path) || [];
4075
4252
  return /*#__PURE__*/jsx(MultiEmailInput, {
4076
4253
  required: true,
@@ -4092,7 +4269,7 @@ var RecipientField = function RecipientField(_ref) {
4092
4269
  }
4093
4270
  });
4094
4271
  }
4095
- var path = "".concat(name, ".value");
4272
+ var path = "".concat(name, ".").concat(RECIPIENT_STORAGE_FIELDS.value);
4096
4273
  var current = getIn(values, path);
4097
4274
  var options = normalizeOptions(dropdownOptions);
4098
4275
  return /*#__PURE__*/jsx(Select$1, {
@@ -4136,7 +4313,7 @@ var RecipientPane = function RecipientPane(_ref) {
4136
4313
  });
4137
4314
  var flatOption = ((_schema$actions4 = schema.actions) === null || _schema$actions4 === void 0 || (_schema$actions4$opti = _schema$actions4.optionForName) === null || _schema$actions4$opti === void 0 ? void 0 : _schema$actions4$opti.call(_schema$actions4, action.name)) || ((_schema$actions5 = schema.actions) === null || _schema$actions5 === void 0 || (_schema$actions5$opti = _schema$actions5.optionForChannel) === null || _schema$actions5$opti === void 0 ? void 0 : _schema$actions5$opti.call(_schema$actions5, channel));
4138
4315
  var isSmsToNumbers = (flatOption === null || flatOption === void 0 ? void 0 : flatOption.type) === SMS_TO_NUMBERS;
4139
- var recipientFieldPath = isSmsToNumbers ? "".concat(name, ".phoneNumbers") : "".concat(name, ".emails");
4316
+ var recipientFieldPath = isSmsToNumbers ? "".concat(name, ".").concat(RECIPIENT_STORAGE_FIELDS.phoneNumbers) : "".concat(name, ".").concat(RECIPIENT_STORAGE_FIELDS.emails);
4140
4317
  usePaneValidation(recipientFieldPath);
4141
4318
  useEffect(function () {
4142
4319
  var _bodyRef$current;
@@ -4167,7 +4344,7 @@ var RecipientPane = function RecipientPane(_ref) {
4167
4344
  action: action
4168
4345
  })) !== null && _schema$actions$rende !== void 0 ? _schema$actions$rende : builtInRecipientField;
4169
4346
  var phoneField = isSmsToNumbers ? /*#__PURE__*/jsx(PhoneNumberField, {
4170
- name: "".concat(name, ".phoneNumbers"),
4347
+ name: "".concat(name, ".").concat(RECIPIENT_STORAGE_FIELDS.phoneNumbers),
4171
4348
  phoneNumbers: (_action$metadata = action.metadata) === null || _action$metadata === void 0 ? void 0 : _action$metadata.phoneNumbers
4172
4349
  }) : null;
4173
4350
  var belowField = phoneField || recipientField;
@@ -4203,6 +4380,7 @@ var RecipientPane = function RecipientPane(_ref) {
4203
4380
  children: /*#__PURE__*/jsxs("div", {
4204
4381
  className: "flex w-full flex-col gap-y-2",
4205
4382
  children: [/*#__PURE__*/jsx(Typography, {
4383
+ "data-testid": "pane-title",
4206
4384
  variant: "h5",
4207
4385
  children: meta.recipientTitle || t("neetoRules.builder.panes.recipientTitle")
4208
4386
  }), /*#__PURE__*/jsx(Typography, {
@@ -4249,6 +4427,7 @@ var ConditionValueFields = function ConditionValueFields(_ref) {
4249
4427
  };
4250
4428
  var noMatches = /*#__PURE__*/jsx("div", {
4251
4429
  className: "mb-pane-empty",
4430
+ "data-testid": "pane-no-matches",
4252
4431
  children: t("neetoRules.builder.noMatches")
4253
4432
  });
4254
4433
  if (type === CONDITION_VALUE_TYPES.multiSelect && isNotEmpty(enumOptions)) {
@@ -4260,7 +4439,7 @@ var ConditionValueFields = function ConditionValueFields(_ref) {
4260
4439
  setFieldValue(valuesPath, current.includes(value) ? current.filter(isNot(value)) : [].concat(_toConsumableArray(current), [value]));
4261
4440
  };
4262
4441
  return /*#__PURE__*/jsxs("div", {
4263
- className: "flex flex-col gap-y-1",
4442
+ className: "mb-pane-list flex flex-col",
4264
4443
  children: [filtered.map(function (option) {
4265
4444
  return /*#__PURE__*/jsx(Checkbox, {
4266
4445
  checked: current.includes(option.value),
@@ -4404,6 +4583,7 @@ var ValuePane = function ValuePane(_ref) {
4404
4583
  children: /*#__PURE__*/jsxs("div", {
4405
4584
  className: "flex w-full flex-col gap-y-2",
4406
4585
  children: [/*#__PURE__*/jsx(Typography, {
4586
+ "data-testid": "pane-title",
4407
4587
  variant: "h5",
4408
4588
  children: t("neetoRules.builder.pickValue", {
4409
4589
  field: (field === null || field === void 0 ? void 0 : field.label) || t("neetoRules.builder.valueWord")
@@ -4418,6 +4598,7 @@ var ValuePane = function ValuePane(_ref) {
4418
4598
  className: "mb-pane-search",
4419
4599
  ref: searchRef,
4420
4600
  children: /*#__PURE__*/jsx(Input, {
4601
+ dataTestid: "pane-search",
4421
4602
  placeholder: t("neetoRules.builder.searchPlaceholder"),
4422
4603
  prefix: /*#__PURE__*/jsx(Search, {}),
4423
4604
  size: "large",
@@ -4564,7 +4745,7 @@ var Form = function Form(_ref) {
4564
4745
  data: data,
4565
4746
  customData: customData,
4566
4747
  isNameGenerationDisabled: isNameRequired
4567
- }),
4748
+ }).concat(leadTimeValidationSchema(schema)),
4568
4749
  onSubmit: submitForm,
4569
4750
  children: function children() {
4570
4751
  return /*#__PURE__*/jsxs("div", {