@bigbinary/neeto-rules-frontend 2.7.19 → 2.7.21

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 (88) 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/en.json +2 -1
  8. package/app/javascript/src/translations/es-MX.json +2 -1
  9. package/app/javascript/src/translations/es.json +2 -1
  10. package/app/javascript/src/translations/et.json +2 -1
  11. package/app/javascript/src/translations/fi.json +2 -1
  12. package/app/javascript/src/translations/fil.json +2 -1
  13. package/app/javascript/src/translations/fr.json +2 -1
  14. package/app/javascript/src/translations/he.json +2 -1
  15. package/app/javascript/src/translations/hi.json +2 -1
  16. package/app/javascript/src/translations/hr.json +2 -1
  17. package/app/javascript/src/translations/hu.json +2 -1
  18. package/app/javascript/src/translations/id.json +2 -1
  19. package/app/javascript/src/translations/it.json +2 -1
  20. package/app/javascript/src/translations/ja.json +2 -1
  21. package/app/javascript/src/translations/ko.json +2 -1
  22. package/app/javascript/src/translations/nl.json +2 -1
  23. package/app/javascript/src/translations/pl.json +2 -1
  24. package/app/javascript/src/translations/pt-BR.json +2 -1
  25. package/app/javascript/src/translations/pt.json +2 -1
  26. package/app/javascript/src/translations/ro.json +2 -1
  27. package/app/javascript/src/translations/ru.json +2 -1
  28. package/app/javascript/src/translations/sk.json +2 -1
  29. package/app/javascript/src/translations/sl.json +2 -1
  30. package/app/javascript/src/translations/sv.json +2 -1
  31. package/app/javascript/src/translations/th.json +2 -1
  32. package/app/javascript/src/translations/tr.json +2 -1
  33. package/app/javascript/src/translations/uk.json +2 -1
  34. package/app/javascript/src/translations/vi.json +2 -1
  35. package/app/javascript/src/translations/zh-CN.json +2 -1
  36. package/app/javascript/src/translations/zh-TW.json +2 -1
  37. package/dist/.ready +1 -1
  38. package/dist/NeetoRulesBuilder.js +79 -17
  39. package/dist/NeetoRulesBuilder.js.map +1 -1
  40. package/dist/NeetoRulesForm.js +2 -2
  41. package/dist/cjs/NeetoRulesBuilder.js +78 -16
  42. package/dist/cjs/NeetoRulesBuilder.js.map +1 -1
  43. package/dist/cjs/NeetoRulesForm.js +2 -2
  44. package/dist/cjs/index.js +2 -2
  45. package/dist/cjs/v2/NeetoRules.js +1 -1
  46. package/dist/cjs/v2/NeetoRulesBuilder.js +370 -154
  47. package/dist/cjs/v2/NeetoRulesBuilder.js.map +1 -1
  48. package/dist/cjs/v2/NeetoRulesForm.js +10 -8
  49. package/dist/cjs/v2/NeetoRulesForm.js.map +1 -1
  50. package/dist/cjs/v2/RulePreview.js +1 -1
  51. package/dist/cjs/v2/hooks.js +2 -2
  52. package/dist/cjs/v2/index.js +4 -4
  53. package/dist/{index-DwGEK-_1.js → index-49edM85x.js} +2 -2
  54. package/dist/{index-DwGEK-_1.js.map → index-49edM85x.js.map} +1 -1
  55. package/dist/{index-ogJeZ752.js → index-BZYwFjcS.js} +2 -2
  56. package/dist/{index-ogJeZ752.js.map → index-BZYwFjcS.js.map} +1 -1
  57. package/dist/{index-k-eGkX-R.js → index-CcbW7H2S.js} +67 -21
  58. package/dist/index-CcbW7H2S.js.map +1 -0
  59. package/dist/{index-Vt6GY_o0.js → index-Fukq1VSN.js} +69 -18
  60. package/dist/index-Fukq1VSN.js.map +1 -0
  61. package/dist/index.js +2 -2
  62. package/dist/keyboardShortcuts-DtnjcivY.js +96 -0
  63. package/dist/{keyboardShortcuts-DNOhEY8h.js.map → keyboardShortcuts-DtnjcivY.js.map} +1 -1
  64. package/dist/keyboardShortcuts-_OrtgF0A.js +92 -0
  65. package/dist/{keyboardShortcuts-SAk712q8.js.map → keyboardShortcuts-_OrtgF0A.js.map} +1 -1
  66. package/dist/{useCustomDataStore-CU3KpyD4.js → useCustomDataStore-CEbhXugO.js} +2 -2
  67. package/dist/{useCustomDataStore-CU3KpyD4.js.map → useCustomDataStore-CEbhXugO.js.map} +1 -1
  68. package/dist/{useCustomDataStore-D9k8F5g-.js → useCustomDataStore-DPmWkEhs.js} +2 -2
  69. package/dist/{useCustomDataStore-D9k8F5g-.js.map → useCustomDataStore-DPmWkEhs.js.map} +1 -1
  70. package/dist/{useUtilityStore-BBb39TOj.js → useUtilityStore-BVCulMEC.js} +9 -2
  71. package/dist/useUtilityStore-BVCulMEC.js.map +1 -0
  72. package/dist/{useUtilityStore-DkxAexDw.js → useUtilityStore-gtPhFvpI.js} +9 -2
  73. package/dist/useUtilityStore-gtPhFvpI.js.map +1 -0
  74. package/dist/v2/NeetoRules.js +1 -1
  75. package/dist/v2/NeetoRulesBuilder.js +352 -155
  76. package/dist/v2/NeetoRulesBuilder.js.map +1 -1
  77. package/dist/v2/NeetoRulesForm.js +10 -8
  78. package/dist/v2/NeetoRulesForm.js.map +1 -1
  79. package/dist/v2/RulePreview.js +1 -1
  80. package/dist/v2/hooks.js +2 -2
  81. package/dist/v2/index.js +4 -4
  82. package/package.json +7 -7
  83. package/dist/index-Vt6GY_o0.js.map +0 -1
  84. package/dist/index-k-eGkX-R.js.map +0 -1
  85. package/dist/keyboardShortcuts-DNOhEY8h.js +0 -88
  86. package/dist/keyboardShortcuts-SAk712q8.js +0 -92
  87. package/dist/useUtilityStore-BBb39TOj.js.map +0 -1
  88. 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 './keyboardShortcuts-DNOhEY8h.js';
3
+ import './keyboardShortcuts-_OrtgF0A.js';
4
4
  import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray';
5
5
  import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
6
6
  import { useShallow } from 'zustand/shallow';
@@ -15,7 +15,7 @@ import { u as useUtilityStore } from './useUtilityStore-CCUYS1mS.js';
15
15
  import classNames from 'classnames';
16
16
  import Typography from '@bigbinary/neetoui/Typography';
17
17
  import { isNotNil, isEmpty, pluck } from 'ramda';
18
- import { g as getActionOptions, a as getFieldDetails, b as getSlackChannelErrors, c as getOptionsKey, d as getActionLabel, A as ActionSubItem, F as FIELDS_WITH_OPTIONS, P as PANEL_TYPES, D as DEFAULT_RULE_ACTION, e as getLogicalOperatorOptions, f as getFieldDetails$1, h as getVerbOptions, R as RadioField$1, S as SelectField$1, V as ValueField, i as DEFAULT_DELAY, j as getAllEvents, O as OPERATORS$1, k as STATUS_KEYS, l as formatData, u as usePollRuleName, T as TouchErrors, m as buildPayload, n as ScrollToErrorField, o as Panel, p as getValidationSchema, q as DEFAULT_INITIAL_VALUE } from './index-ogJeZ752.js';
18
+ import { g as getActionOptions, a as getFieldDetails, b as getSlackChannelErrors, c as getOptionsKey, d as getActionLabel, A as ActionSubItem, F as FIELDS_WITH_OPTIONS, P as PANEL_TYPES, D as DEFAULT_RULE_ACTION, e as getLogicalOperatorOptions, f as getFieldDetails$1, h as getVerbOptions, R as RadioField$1, S as SelectField$1, V as ValueField, i as DEFAULT_DELAY, j as getAllEvents, O as OPERATORS$1, k as STATUS_KEYS, l as formatData, u as usePollRuleName, T as TouchErrors, m as buildPayload, n as ScrollToErrorField, o as Panel, p as getValidationSchema, q as DEFAULT_INITIAL_VALUE } from './index-BZYwFjcS.js';
19
19
  import { a as useActiveField, u as useCustomDataStore } from './useCustomDataStore-BtKYtLVc.js';
20
20
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
21
21
  import { joinHyphenCase } from '@bigbinary/neeto-commons-frontend/utils';
@@ -2,7 +2,7 @@
2
2
 
3
3
  var _defineProperty = require('@babel/runtime/helpers/defineProperty');
4
4
  var _objectDestructuringEmpty = require('@babel/runtime/helpers/objectDestructuringEmpty');
5
- var keyboardShortcuts = require('../keyboardShortcuts-SAk712q8.js');
5
+ var keyboardShortcuts = require('../keyboardShortcuts-DtnjcivY.js');
6
6
  var shallow = require('zustand/shallow');
7
7
  var react = require('react');
8
8
  var classNames = require('classnames');
@@ -13,7 +13,7 @@ var Header = require('@bigbinary/neeto-molecules/Header');
13
13
  var Spinner = require('@bigbinary/neetoui/Spinner');
14
14
  var ActionBlock = require('@bigbinary/neetoui/formik/ActionBlock');
15
15
  var reactI18next = require('react-i18next');
16
- var index = require('../index-DwGEK-_1.js');
16
+ var index = require('../index-49edM85x.js');
17
17
  var useCustomDataStore = require('../useCustomDataStore-DxFx8aCf.js');
18
18
  var useUtilityStore = require('../useUtilityStore-C_U20IMX.js');
19
19
  var _toConsumableArray = require('@babel/runtime/helpers/toConsumableArray');
@@ -26,8 +26,8 @@ var _objectWithoutProperties = require('@babel/runtime/helpers/objectWithoutProp
26
26
  var jsxRuntime = require('react/jsx-runtime');
27
27
  var i18next = require('i18next');
28
28
  var yup = require('yup');
29
- var reactUtils = require('@bigbinary/neeto-commons-frontend/react-utils');
30
29
  var _asyncToGenerator = require('@babel/runtime/helpers/asyncToGenerator');
30
+ var useHotkeys = require('@bigbinary/neeto-hotkeys');
31
31
  var Search = require('@bigbinary/neeto-icons/Search');
32
32
  var Input = require('@bigbinary/neetoui/Input');
33
33
  var Typography = require('@bigbinary/neetoui/Typography');
@@ -47,6 +47,7 @@ var MultiEmailInput = require('@bigbinary/neetoui/MultiEmailInput');
47
47
  require('@babel/runtime/helpers/typeof');
48
48
  require('../useAutomationRulesApi-C1T2E1AN.js');
49
49
  require('@tanstack/react-query');
50
+ require('@bigbinary/neeto-commons-frontend/react-utils');
50
51
  require('axios');
51
52
  require('../index-DFwPrb81.js');
52
53
  require('@bigbinary/neetoui/formik/Radio');
@@ -64,7 +65,6 @@ require('@bigbinary/neetoui/Label');
64
65
  require('@bigbinary/neetoui/formik/MultiEmailInput');
65
66
  require('@bigbinary/neeto-editor/FormikEditor');
66
67
  require('@bigbinary/neeto-icons/Refresh');
67
- require('@bigbinary/neeto-hotkeys');
68
68
  require('@bigbinary/neeto-icons/Check');
69
69
  require('react-select/creatable');
70
70
  require('@babel/runtime/helpers/toArray');
@@ -277,6 +277,21 @@ var TOKEN_STATE = {
277
277
  };
278
278
  var STATE_CLASS = _defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty({}, TOKEN_STATE.PLACEHOLDER, "mb-placeholder"), TOKEN_STATE.PLACEHOLDER_NEXT, "mb-placeholder mb-placeholder-next"), TOKEN_STATE.DISABLED, "mb-placeholder mb-placeholder-disabled"), TOKEN_STATE.FILLED, "mb-tok"), TOKEN_STATE.MUTED, "mb-tok mb-tok-muted");
279
279
 
280
+ // The flash is a run-once CSS animation, so a repeat submit while it is still
281
+ // applied would not replay it on its own.
282
+ var useReplayFlash = function useReplayFlash(flashSeq) {
283
+ var ref = react.useRef(null);
284
+ react.useEffect(function () {
285
+ var _ref$current, _ref$current$getAnima;
286
+ if (!flashSeq) return;
287
+ (_ref$current = ref.current) === null || _ref$current === void 0 || (_ref$current$getAnima = _ref$current.getAnimations) === null || _ref$current$getAnima === void 0 || _ref$current$getAnima.call(_ref$current).forEach(function (animation) {
288
+ animation.cancel();
289
+ animation.play();
290
+ });
291
+ }, [flashSeq]);
292
+ return ref;
293
+ };
294
+
280
295
  var _excluded = ["children", "state", "active", "invalid", "onClick", "className", "dataTestid"];
281
296
  function ownKeys$c(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; }
282
297
  function _objectSpread$c(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$c(Object(t), true).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$c(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
@@ -293,8 +308,10 @@ var Token = function Token(_ref) {
293
308
  dataTestid = _ref.dataTestid,
294
309
  rest = _objectWithoutProperties(_ref, _excluded);
295
310
  var isInteractive = typeof onClick === "function" && state !== TOKEN_STATE.DISABLED;
311
+ var tokenRef = useReplayFlash(invalid);
296
312
  return /*#__PURE__*/jsxRuntime.jsx("span", _objectSpread$c(_objectSpread$c({
297
313
  "data-testid": dataTestid,
314
+ ref: tokenRef,
298
315
  role: isInteractive ? "button" : undefined,
299
316
  tabIndex: isInteractive ? 0 : undefined,
300
317
  className: classNames(
@@ -1108,15 +1125,17 @@ var DelayRow = function DelayRow(_ref) {
1108
1125
  });
1109
1126
  };
1110
1127
 
1111
- var MetaBlock = reactUtils.withT(function (_ref) {
1112
- var t = _ref.t,
1113
- rule = _ref.rule,
1128
+ var MetaBlock = function MetaBlock(_ref) {
1129
+ var rule = _ref.rule,
1114
1130
  _ref$showName = _ref.showName,
1115
1131
  showName = _ref$showName === void 0 ? true : _ref$showName,
1116
1132
  _ref$isInvalid = _ref.isInvalid,
1117
1133
  isInvalid = _ref$isInvalid === void 0 ? false : _ref$isInvalid,
1118
1134
  handleEditName = _ref.onEditName,
1119
1135
  handleToggleActive = _ref.onToggleActive;
1136
+ var _useTranslation = reactI18next.useTranslation(),
1137
+ t = _useTranslation.t;
1138
+ var nameRef = useReplayFlash(isInvalid);
1120
1139
  return /*#__PURE__*/jsxRuntime.jsxs("div", {
1121
1140
  className: "mb-meta",
1122
1141
  children: [showName && /*#__PURE__*/jsxRuntime.jsxs("div", {
@@ -1125,6 +1144,8 @@ var MetaBlock = reactUtils.withT(function (_ref) {
1125
1144
  className: "mb-meta-label",
1126
1145
  children: t("neetoRules.builder.automationName")
1127
1146
  }), /*#__PURE__*/jsxRuntime.jsxs("div", {
1147
+ ref: nameRef,
1148
+ "data-testid": "rule-name-edit",
1128
1149
  role: handleEditName ? "button" : undefined,
1129
1150
  tabIndex: handleEditName ? 0 : undefined,
1130
1151
  className: classNames("mb-meta-input-wrap", {
@@ -1133,6 +1154,7 @@ var MetaBlock = reactUtils.withT(function (_ref) {
1133
1154
  onClick: handleEditName,
1134
1155
  children: [/*#__PURE__*/jsxRuntime.jsx("span", {
1135
1156
  className: "mb-meta-name-display",
1157
+ "data-testid": "rule-name",
1136
1158
  children: rule.name
1137
1159
  }), /*#__PURE__*/jsxRuntime.jsx("span", {
1138
1160
  "aria-hidden": true,
@@ -1154,8 +1176,10 @@ var MetaBlock = reactUtils.withT(function (_ref) {
1154
1176
  })]
1155
1177
  }), /*#__PURE__*/jsxRuntime.jsxs("label", {
1156
1178
  className: "mb-meta-active",
1179
+ "data-testid": "rule-active-label",
1157
1180
  children: [/*#__PURE__*/jsxRuntime.jsx("input", {
1158
1181
  checked: rule.active,
1182
+ "data-testid": "rule-active-checkbox",
1159
1183
  readOnly: !handleToggleActive,
1160
1184
  type: "checkbox",
1161
1185
  onChange: handleToggleActive || undefined
@@ -1174,7 +1198,7 @@ var MetaBlock = reactUtils.withT(function (_ref) {
1174
1198
  }), t("neetoRules.builder.activateThisAutomation")]
1175
1199
  })]
1176
1200
  });
1177
- });
1201
+ };
1178
1202
 
1179
1203
  function ownKeys$8(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; }
1180
1204
  function _objectSpread$8(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$8(Object(t), true).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$8(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
@@ -2836,10 +2860,10 @@ var Canvas = function Canvas(_ref) {
2836
2860
  var flatErrors = react.useMemo(function () {
2837
2861
  return keyboardShortcuts.flatten(errors || {});
2838
2862
  }, [errors]);
2839
- var _useState = react.useState(false),
2863
+ var _useState = react.useState(0),
2840
2864
  _useState2 = _slicedToArray(_useState, 2),
2841
- flashing = _useState2[0],
2842
- setFlashing = _useState2[1];
2865
+ flashSeq = _useState2[0],
2866
+ setFlashSeq = _useState2[1];
2843
2867
  var lastSubmitCount = react.useRef(submitCount);
2844
2868
  react.useEffect(function () {
2845
2869
  if (submitCount <= lastSubmitCount.current) return undefined;
@@ -2853,9 +2877,9 @@ var Canvas = function Canvas(_ref) {
2853
2877
  }))) {
2854
2878
  return undefined;
2855
2879
  }
2856
- setFlashing(true);
2880
+ setFlashSeq(submitCount);
2857
2881
  var timer = setTimeout(function () {
2858
- return setFlashing(false);
2882
+ return setFlashSeq(0);
2859
2883
  }, FLASH_DURATION_MS);
2860
2884
  return function () {
2861
2885
  return clearTimeout(timer);
@@ -2872,11 +2896,10 @@ var Canvas = function Canvas(_ref) {
2872
2896
  });
2873
2897
  });
2874
2898
  };
2875
- var isInvalid = function isInvalid(_ref4) {
2899
+ var matchesInvalid = function matchesInvalid(_ref4) {
2876
2900
  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;
2877
2901
  var type = _ref4.type,
2878
2902
  index = _ref4.index;
2879
- if (!flashing) return false;
2880
2903
  var conditionMeta = "".concat(fieldKeys.conditions, ".value.").concat(index, ".metadata");
2881
2904
  var actionMeta = "".concat(fieldKeys.actions, ".value.").concat(index, ".metadata");
2882
2905
  // eslint-disable-next-line security/detect-object-injection
@@ -2967,6 +2990,12 @@ var Canvas = function Canvas(_ref) {
2967
2990
  return false;
2968
2991
  }
2969
2992
  };
2993
+
2994
+ // Returns the submit generation, not a boolean, so consumers can replay the
2995
+ // flash animation when the same token is still invalid on a repeat submit.
2996
+ var isInvalid = function isInvalid(args) {
2997
+ return flashSeq && matchesInvalid(args) ? flashSeq : 0;
2998
+ };
2970
2999
  var closePaneIfTargeting = function closePaneIfTargeting(_ref5) {
2971
3000
  var anchors = _ref5.anchors,
2972
3001
  index = _ref5.index;
@@ -3110,6 +3139,7 @@ var Canvas = function Canvas(_ref) {
3110
3139
  }) : /*#__PURE__*/jsxRuntime.jsx("div", {
3111
3140
  className: "mb-add-row",
3112
3141
  children: /*#__PURE__*/jsxRuntime.jsx(Button, {
3142
+ "data-testid": "rule-delay-add",
3113
3143
  icon: Plus,
3114
3144
  iconPosition: "left",
3115
3145
  label: t("neetoRules.common.addDelay"),
@@ -3228,6 +3258,7 @@ var ActionConfigFields = function ActionConfigFields(_ref) {
3228
3258
  };
3229
3259
  var noMatches = /*#__PURE__*/jsxRuntime.jsx("div", {
3230
3260
  className: "mb-pane-empty",
3261
+ "data-testid": "pane-no-matches",
3231
3262
  children: t("neetoRules.builder.noMatches")
3232
3263
  });
3233
3264
  if (type === ACTION_CONFIG_TYPES.emailChannel) {
@@ -3583,11 +3614,16 @@ var ConfigPane = function ConfigPane(_ref) {
3583
3614
  return _ref2.apply(this, arguments);
3584
3615
  };
3585
3616
  }();
3617
+ useHotkeys(keyboardShortcuts.SHORTCUTS["continue"].sequence, handleContinue, {
3618
+ enabled: shouldAdvanceToRecipient,
3619
+ mode: "global"
3620
+ });
3586
3621
  return /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
3587
3622
  children: [/*#__PURE__*/jsxRuntime.jsx(index.Panel.Header, {
3588
3623
  children: /*#__PURE__*/jsxRuntime.jsxs("div", {
3589
3624
  className: "flex w-full flex-col gap-y-2",
3590
3625
  children: [/*#__PURE__*/jsxRuntime.jsx(Typography, {
3626
+ "data-testid": "pane-title",
3591
3627
  style: "h3",
3592
3628
  children: title
3593
3629
  }), configSubtitle && /*#__PURE__*/jsxRuntime.jsx(Typography, {
@@ -3597,6 +3633,7 @@ var ConfigPane = function ConfigPane(_ref) {
3597
3633
  }), showSearch && /*#__PURE__*/jsxRuntime.jsx("div", {
3598
3634
  className: "mb-pane-search",
3599
3635
  children: /*#__PURE__*/jsxRuntime.jsx(Input, {
3636
+ dataTestid: "pane-search",
3600
3637
  placeholder: t("neetoRules.builder.searchPlaceholder"),
3601
3638
  prefix: /*#__PURE__*/jsxRuntime.jsx(Search, {}),
3602
3639
  size: "large",
@@ -3638,6 +3675,7 @@ var ConfigPane = function ConfigPane(_ref) {
3638
3675
  })
3639
3676
  }), shouldAdvanceToRecipient && /*#__PURE__*/jsxRuntime.jsx(index.Panel.Footer, {
3640
3677
  children: /*#__PURE__*/jsxRuntime.jsx(Button, {
3678
+ "data-testid": "continue-button",
3641
3679
  label: t("neetoRules.buttons.continue"),
3642
3680
  size: "large",
3643
3681
  onClick: handleContinue
@@ -3694,6 +3732,7 @@ var DelayPane = function DelayPane(_ref) {
3694
3732
  children: /*#__PURE__*/jsxRuntime.jsxs("div", {
3695
3733
  className: "flex flex-col gap-y-1",
3696
3734
  children: [/*#__PURE__*/jsxRuntime.jsx(Typography, {
3735
+ "data-testid": "pane-title",
3697
3736
  style: "h3",
3698
3737
  children: t("neetoRules.common.addDelay")
3699
3738
  }), /*#__PURE__*/jsxRuntime.jsx(Typography, {
@@ -3715,6 +3754,7 @@ var DelayPane = function DelayPane(_ref) {
3715
3754
  className: "flex items-start gap-x-2",
3716
3755
  children: [/*#__PURE__*/jsxRuntime.jsx(Input$1, {
3717
3756
  className: "w-44",
3757
+ dataTestid: "delay-value",
3718
3758
  max: index.MAX_DELAY_VALUE,
3719
3759
  min: index.MIN_DELAY_VALUE,
3720
3760
  name: "".concat(name, ".value.value"),
@@ -3722,6 +3762,7 @@ var DelayPane = function DelayPane(_ref) {
3722
3762
  size: "large",
3723
3763
  type: "number"
3724
3764
  }), /*#__PURE__*/jsxRuntime.jsx(Select, {
3765
+ dataTestid: "delay-unit",
3725
3766
  defaultValue: neetoCist.findBy({
3726
3767
  value: value === null || value === void 0 ? void 0 : value.unit
3727
3768
  }, unitOptions),
@@ -3758,6 +3799,7 @@ var asText = function asText(value) {
3758
3799
  var NumberStepper = function NumberStepper(_ref) {
3759
3800
  var value = _ref.value,
3760
3801
  onChange = _ref.onChange,
3802
+ dataTestid = _ref.dataTestid,
3761
3803
  label = _ref.label,
3762
3804
  _ref$min = _ref.min,
3763
3805
  min = _ref$min === void 0 ? STEPPER_MIN_VALUE : _ref$min,
@@ -3791,6 +3833,7 @@ var NumberStepper = function NumberStepper(_ref) {
3791
3833
  return /*#__PURE__*/jsxRuntime.jsx("div", {
3792
3834
  className: "mb-stepper",
3793
3835
  children: /*#__PURE__*/jsxRuntime.jsx(Input, {
3836
+ dataTestid: dataTestid,
3794
3837
  error: error,
3795
3838
  label: label,
3796
3839
  min: min,
@@ -3803,6 +3846,7 @@ var NumberStepper = function NumberStepper(_ref) {
3803
3846
  children: [/*#__PURE__*/jsxRuntime.jsx("button", {
3804
3847
  "aria-label": t("neetoRules.builder.aria.increase"),
3805
3848
  className: "mb-stepper-btn",
3849
+ "data-testid": "stepper-increase",
3806
3850
  tabIndex: SKIP_TAB_INDEX,
3807
3851
  type: "button",
3808
3852
  onClick: function onClick() {
@@ -3812,6 +3856,7 @@ var NumberStepper = function NumberStepper(_ref) {
3812
3856
  }), /*#__PURE__*/jsxRuntime.jsx("button", {
3813
3857
  "aria-label": t("neetoRules.builder.aria.decrease"),
3814
3858
  className: "mb-stepper-btn",
3859
+ "data-testid": "stepper-decrease",
3815
3860
  tabIndex: SKIP_TAB_INDEX,
3816
3861
  type: "button",
3817
3862
  onClick: function onClick() {
@@ -3873,6 +3918,7 @@ var LeadTimePane = function LeadTimePane(_ref) {
3873
3918
  children: /*#__PURE__*/jsxRuntime.jsxs("div", {
3874
3919
  className: "flex flex-col gap-y-1",
3875
3920
  children: [/*#__PURE__*/jsxRuntime.jsx(Typography, {
3921
+ "data-testid": "pane-title",
3876
3922
  style: "h3",
3877
3923
  children: t("neetoRules.builder.leadTimeTitle")
3878
3924
  }), /*#__PURE__*/jsxRuntime.jsx(Typography, {
@@ -3894,6 +3940,7 @@ var LeadTimePane = function LeadTimePane(_ref) {
3894
3940
  children: [/*#__PURE__*/jsxRuntime.jsx("div", {
3895
3941
  className: "flex-1",
3896
3942
  children: /*#__PURE__*/jsxRuntime.jsx(NumberStepper, {
3943
+ dataTestid: "lead-time",
3897
3944
  error: touched ? error : "",
3898
3945
  value: amount,
3899
3946
  onChange: function onChange(value) {
@@ -3906,6 +3953,7 @@ var LeadTimePane = function LeadTimePane(_ref) {
3906
3953
  }), /*#__PURE__*/jsxRuntime.jsx("div", {
3907
3954
  className: "w-32 shrink-0",
3908
3955
  children: /*#__PURE__*/jsxRuntime.jsx(Select$1, {
3956
+ dataTestid: "lead-time-unit",
3909
3957
  isSearchable: false,
3910
3958
  options: LEAD_TIME_UNITS,
3911
3959
  value: neetoCist.findBy({
@@ -3939,6 +3987,7 @@ var NamePane = function NamePane(_ref) {
3939
3987
  children: /*#__PURE__*/jsxRuntime.jsxs("div", {
3940
3988
  className: "flex flex-col gap-y-1",
3941
3989
  children: [/*#__PURE__*/jsxRuntime.jsx(Typography, {
3990
+ "data-testid": "pane-title",
3942
3991
  style: "h3",
3943
3992
  children: t("neetoRules.builder.automationName")
3944
3993
  }), /*#__PURE__*/jsxRuntime.jsx(Typography, {
@@ -4080,6 +4129,11 @@ var OptionsPane = function OptionsPane(_ref) {
4080
4129
  data: target.data
4081
4130
  });else closePane();
4082
4131
  };
4132
+ var canContinue = cascade && selectedValues.some(Boolean);
4133
+ useHotkeys(keyboardShortcuts.SHORTCUTS["continue"].sequence, handleContinue, {
4134
+ enabled: canContinue,
4135
+ mode: "global"
4136
+ });
4083
4137
  var optionLabel = function optionLabel(option) {
4084
4138
  var Icon = option.icon;
4085
4139
  if (!Icon && !option.disabledReason) return option.label;
@@ -4111,6 +4165,7 @@ var OptionsPane = function OptionsPane(_ref) {
4111
4165
  if (ramda.isEmpty(filtered)) {
4112
4166
  return /*#__PURE__*/jsxRuntime.jsx("div", {
4113
4167
  className: "mb-pane-empty",
4168
+ "data-testid": "pane-no-matches",
4114
4169
  children: t("neetoRules.builder.noMatches")
4115
4170
  });
4116
4171
  }
@@ -4170,6 +4225,7 @@ var OptionsPane = function OptionsPane(_ref) {
4170
4225
  children: /*#__PURE__*/jsxRuntime.jsxs("div", {
4171
4226
  className: "flex w-full flex-col gap-y-2",
4172
4227
  children: [/*#__PURE__*/jsxRuntime.jsx(Typography, {
4228
+ "data-testid": "pane-title",
4173
4229
  style: "h3",
4174
4230
  children: title
4175
4231
  }), /*#__PURE__*/jsxRuntime.jsx(Typography, {
@@ -4180,6 +4236,7 @@ var OptionsPane = function OptionsPane(_ref) {
4180
4236
  className: "mb-pane-search",
4181
4237
  ref: searchRef,
4182
4238
  children: /*#__PURE__*/jsxRuntime.jsx(Input, {
4239
+ dataTestid: "pane-search",
4183
4240
  placeholder: t("neetoRules.builder.searchPlaceholder"),
4184
4241
  prefix: /*#__PURE__*/jsxRuntime.jsx(Search, {}),
4185
4242
  size: "large",
@@ -4194,7 +4251,8 @@ var OptionsPane = function OptionsPane(_ref) {
4194
4251
  children: [renderBody(), belowContent]
4195
4252
  }), cascade && /*#__PURE__*/jsxRuntime.jsx(index.Panel.Footer, {
4196
4253
  children: /*#__PURE__*/jsxRuntime.jsx(Button, {
4197
- disabled: !selectedValues.some(Boolean),
4254
+ "data-testid": "continue-button",
4255
+ disabled: !canContinue,
4198
4256
  label: t("neetoRules.buttons.continue"),
4199
4257
  size: "large",
4200
4258
  onClick: handleContinue
@@ -4356,6 +4414,7 @@ var RecipientPane = function RecipientPane(_ref) {
4356
4414
  children: /*#__PURE__*/jsxRuntime.jsxs("div", {
4357
4415
  className: "flex w-full flex-col gap-y-2",
4358
4416
  children: [/*#__PURE__*/jsxRuntime.jsx(Typography, {
4417
+ "data-testid": "pane-title",
4359
4418
  style: "h3",
4360
4419
  children: meta.recipientTitle || t("neetoRules.builder.panes.recipientTitle")
4361
4420
  }), /*#__PURE__*/jsxRuntime.jsx(Typography, {
@@ -4402,6 +4461,7 @@ var ConditionValueFields = function ConditionValueFields(_ref) {
4402
4461
  };
4403
4462
  var noMatches = /*#__PURE__*/jsxRuntime.jsx("div", {
4404
4463
  className: "mb-pane-empty",
4464
+ "data-testid": "pane-no-matches",
4405
4465
  children: t("neetoRules.builder.noMatches")
4406
4466
  });
4407
4467
  if (type === CONDITION_VALUE_TYPES.multiSelect && neetoCist.isNotEmpty(enumOptions)) {
@@ -4556,6 +4616,7 @@ var ValuePane = function ValuePane(_ref) {
4556
4616
  children: /*#__PURE__*/jsxRuntime.jsxs("div", {
4557
4617
  className: "flex w-full flex-col gap-y-2",
4558
4618
  children: [/*#__PURE__*/jsxRuntime.jsx(Typography, {
4619
+ "data-testid": "pane-title",
4559
4620
  style: "h3",
4560
4621
  children: t("neetoRules.builder.pickValue", {
4561
4622
  field: (field === null || field === void 0 ? void 0 : field.label) || t("neetoRules.builder.valueWord")
@@ -4570,6 +4631,7 @@ var ValuePane = function ValuePane(_ref) {
4570
4631
  className: "mb-pane-search",
4571
4632
  ref: searchRef,
4572
4633
  children: /*#__PURE__*/jsxRuntime.jsx(Input, {
4634
+ dataTestid: "pane-search",
4573
4635
  placeholder: t("neetoRules.builder.searchPlaceholder"),
4574
4636
  prefix: /*#__PURE__*/jsxRuntime.jsx(Search, {}),
4575
4637
  size: "large",