@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,8 +1,8 @@
1
1
  import _defineProperty from '@babel/runtime/helpers/defineProperty';
2
2
  import _objectDestructuringEmpty from '@babel/runtime/helpers/objectDestructuringEmpty';
3
- import { f as flatten } from './keyboardShortcuts-DNOhEY8h.js';
3
+ import { f as flatten, S as SHORTCUTS } from './keyboardShortcuts-_OrtgF0A.js';
4
4
  import { useShallow } from 'zustand/shallow';
5
- import { useState, createElement, Fragment as Fragment$1, useCallback, useMemo, useRef, useEffect } from 'react';
5
+ import { useState, useRef, useEffect, createElement, Fragment as Fragment$1, useCallback, useMemo } from 'react';
6
6
  import classNames from 'classnames';
7
7
  import { useFormikContext, getIn, useField, Formik, Form as Form$1 } from 'formik';
8
8
  import { isNotEmpty, toLabelAndValue, removeBy, isNot, findBy, noop } from '@bigbinary/neeto-cist';
@@ -11,7 +11,7 @@ import Header from '@bigbinary/neeto-molecules/Header';
11
11
  import Spinner from '@bigbinary/neetoui/Spinner';
12
12
  import ActionBlock from '@bigbinary/neetoui/formik/ActionBlock';
13
13
  import { useTranslation } from 'react-i18next';
14
- import { E as EditorAction, 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-ogJeZ752.js';
14
+ import { E as EditorAction, 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-BZYwFjcS.js';
15
15
  import { u as useCustomDataStore } from './useCustomDataStore-BtKYtLVc.js';
16
16
  import { u as useUtilityStore } from './useUtilityStore-CCUYS1mS.js';
17
17
  import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray';
@@ -24,8 +24,8 @@ import _objectWithoutProperties from '@babel/runtime/helpers/objectWithoutProper
24
24
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
25
25
  import { t } from 'i18next';
26
26
  import * as yup from 'yup';
27
- import { withT } from '@bigbinary/neeto-commons-frontend/react-utils';
28
27
  import _asyncToGenerator from '@babel/runtime/helpers/asyncToGenerator';
28
+ import useHotkeys from '@bigbinary/neeto-hotkeys';
29
29
  import Search from '@bigbinary/neeto-icons/Search';
30
30
  import Input from '@bigbinary/neetoui/Input';
31
31
  import Typography from '@bigbinary/neetoui/Typography';
@@ -45,6 +45,7 @@ import MultiEmailInput from '@bigbinary/neetoui/MultiEmailInput';
45
45
  import '@babel/runtime/helpers/typeof';
46
46
  import './useAutomationRulesApi-C9I3wUZ8.js';
47
47
  import '@tanstack/react-query';
48
+ import '@bigbinary/neeto-commons-frontend/react-utils';
48
49
  import 'axios';
49
50
  import './index-9h4B7JZZ.js';
50
51
  import '@bigbinary/neetoui/formik/Radio';
@@ -62,7 +63,6 @@ import '@bigbinary/neetoui/Label';
62
63
  import '@bigbinary/neetoui/formik/MultiEmailInput';
63
64
  import '@bigbinary/neeto-editor/FormikEditor';
64
65
  import '@bigbinary/neeto-icons/Refresh';
65
- import '@bigbinary/neeto-hotkeys';
66
66
  import '@bigbinary/neeto-icons/Check';
67
67
  import 'react-select/creatable';
68
68
  import '@babel/runtime/helpers/toArray';
@@ -256,6 +256,21 @@ var TOKEN_STATE = {
256
256
  };
257
257
  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");
258
258
 
259
+ // The flash is a run-once CSS animation, so a repeat submit while it is still
260
+ // applied would not replay it on its own.
261
+ var useReplayFlash = function useReplayFlash(flashSeq) {
262
+ var ref = useRef(null);
263
+ useEffect(function () {
264
+ var _ref$current, _ref$current$getAnima;
265
+ if (!flashSeq) return;
266
+ (_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) {
267
+ animation.cancel();
268
+ animation.play();
269
+ });
270
+ }, [flashSeq]);
271
+ return ref;
272
+ };
273
+
259
274
  var _excluded = ["children", "state", "active", "invalid", "onClick", "className", "dataTestid"];
260
275
  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; }
261
276
  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; }
@@ -272,8 +287,10 @@ var Token = function Token(_ref) {
272
287
  dataTestid = _ref.dataTestid,
273
288
  rest = _objectWithoutProperties(_ref, _excluded);
274
289
  var isInteractive = typeof onClick === "function" && state !== TOKEN_STATE.DISABLED;
290
+ var tokenRef = useReplayFlash(invalid);
275
291
  return /*#__PURE__*/jsx("span", _objectSpread$c(_objectSpread$c({
276
292
  "data-testid": dataTestid,
293
+ ref: tokenRef,
277
294
  role: isInteractive ? "button" : undefined,
278
295
  tabIndex: isInteractive ? 0 : undefined,
279
296
  className: classNames(
@@ -1087,15 +1104,17 @@ var DelayRow = function DelayRow(_ref) {
1087
1104
  });
1088
1105
  };
1089
1106
 
1090
- var MetaBlock = withT(function (_ref) {
1091
- var t = _ref.t,
1092
- rule = _ref.rule,
1107
+ var MetaBlock = function MetaBlock(_ref) {
1108
+ var rule = _ref.rule,
1093
1109
  _ref$showName = _ref.showName,
1094
1110
  showName = _ref$showName === void 0 ? true : _ref$showName,
1095
1111
  _ref$isInvalid = _ref.isInvalid,
1096
1112
  isInvalid = _ref$isInvalid === void 0 ? false : _ref$isInvalid,
1097
1113
  handleEditName = _ref.onEditName,
1098
1114
  handleToggleActive = _ref.onToggleActive;
1115
+ var _useTranslation = useTranslation(),
1116
+ t = _useTranslation.t;
1117
+ var nameRef = useReplayFlash(isInvalid);
1099
1118
  return /*#__PURE__*/jsxs("div", {
1100
1119
  className: "mb-meta",
1101
1120
  children: [showName && /*#__PURE__*/jsxs("div", {
@@ -1104,6 +1123,8 @@ var MetaBlock = withT(function (_ref) {
1104
1123
  className: "mb-meta-label",
1105
1124
  children: t("neetoRules.builder.automationName")
1106
1125
  }), /*#__PURE__*/jsxs("div", {
1126
+ ref: nameRef,
1127
+ "data-testid": "rule-name-edit",
1107
1128
  role: handleEditName ? "button" : undefined,
1108
1129
  tabIndex: handleEditName ? 0 : undefined,
1109
1130
  className: classNames("mb-meta-input-wrap", {
@@ -1112,6 +1133,7 @@ var MetaBlock = withT(function (_ref) {
1112
1133
  onClick: handleEditName,
1113
1134
  children: [/*#__PURE__*/jsx("span", {
1114
1135
  className: "mb-meta-name-display",
1136
+ "data-testid": "rule-name",
1115
1137
  children: rule.name
1116
1138
  }), /*#__PURE__*/jsx("span", {
1117
1139
  "aria-hidden": true,
@@ -1133,8 +1155,10 @@ var MetaBlock = withT(function (_ref) {
1133
1155
  })]
1134
1156
  }), /*#__PURE__*/jsxs("label", {
1135
1157
  className: "mb-meta-active",
1158
+ "data-testid": "rule-active-label",
1136
1159
  children: [/*#__PURE__*/jsx("input", {
1137
1160
  checked: rule.active,
1161
+ "data-testid": "rule-active-checkbox",
1138
1162
  readOnly: !handleToggleActive,
1139
1163
  type: "checkbox",
1140
1164
  onChange: handleToggleActive || undefined
@@ -1153,7 +1177,7 @@ var MetaBlock = withT(function (_ref) {
1153
1177
  }), t("neetoRules.builder.activateThisAutomation")]
1154
1178
  })]
1155
1179
  });
1156
- });
1180
+ };
1157
1181
 
1158
1182
  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; }
1159
1183
  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; }
@@ -2815,10 +2839,10 @@ var Canvas = function Canvas(_ref) {
2815
2839
  var flatErrors = useMemo(function () {
2816
2840
  return flatten(errors || {});
2817
2841
  }, [errors]);
2818
- var _useState = useState(false),
2842
+ var _useState = useState(0),
2819
2843
  _useState2 = _slicedToArray(_useState, 2),
2820
- flashing = _useState2[0],
2821
- setFlashing = _useState2[1];
2844
+ flashSeq = _useState2[0],
2845
+ setFlashSeq = _useState2[1];
2822
2846
  var lastSubmitCount = useRef(submitCount);
2823
2847
  useEffect(function () {
2824
2848
  if (submitCount <= lastSubmitCount.current) return undefined;
@@ -2832,9 +2856,9 @@ var Canvas = function Canvas(_ref) {
2832
2856
  }))) {
2833
2857
  return undefined;
2834
2858
  }
2835
- setFlashing(true);
2859
+ setFlashSeq(submitCount);
2836
2860
  var timer = setTimeout(function () {
2837
- return setFlashing(false);
2861
+ return setFlashSeq(0);
2838
2862
  }, FLASH_DURATION_MS);
2839
2863
  return function () {
2840
2864
  return clearTimeout(timer);
@@ -2851,11 +2875,10 @@ var Canvas = function Canvas(_ref) {
2851
2875
  });
2852
2876
  });
2853
2877
  };
2854
- var isInvalid = function isInvalid(_ref4) {
2878
+ var matchesInvalid = function matchesInvalid(_ref4) {
2855
2879
  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;
2856
2880
  var type = _ref4.type,
2857
2881
  index = _ref4.index;
2858
- if (!flashing) return false;
2859
2882
  var conditionMeta = "".concat(fieldKeys.conditions, ".value.").concat(index, ".metadata");
2860
2883
  var actionMeta = "".concat(fieldKeys.actions, ".value.").concat(index, ".metadata");
2861
2884
  // eslint-disable-next-line security/detect-object-injection
@@ -2946,6 +2969,12 @@ var Canvas = function Canvas(_ref) {
2946
2969
  return false;
2947
2970
  }
2948
2971
  };
2972
+
2973
+ // Returns the submit generation, not a boolean, so consumers can replay the
2974
+ // flash animation when the same token is still invalid on a repeat submit.
2975
+ var isInvalid = function isInvalid(args) {
2976
+ return flashSeq && matchesInvalid(args) ? flashSeq : 0;
2977
+ };
2949
2978
  var closePaneIfTargeting = function closePaneIfTargeting(_ref5) {
2950
2979
  var anchors = _ref5.anchors,
2951
2980
  index = _ref5.index;
@@ -3089,6 +3118,7 @@ var Canvas = function Canvas(_ref) {
3089
3118
  }) : /*#__PURE__*/jsx("div", {
3090
3119
  className: "mb-add-row",
3091
3120
  children: /*#__PURE__*/jsx(Button, {
3121
+ "data-testid": "rule-delay-add",
3092
3122
  icon: Plus,
3093
3123
  iconPosition: "left",
3094
3124
  label: t("neetoRules.common.addDelay"),
@@ -3207,6 +3237,7 @@ var ActionConfigFields = function ActionConfigFields(_ref) {
3207
3237
  };
3208
3238
  var noMatches = /*#__PURE__*/jsx("div", {
3209
3239
  className: "mb-pane-empty",
3240
+ "data-testid": "pane-no-matches",
3210
3241
  children: t("neetoRules.builder.noMatches")
3211
3242
  });
3212
3243
  if (type === ACTION_CONFIG_TYPES.emailChannel) {
@@ -3562,11 +3593,16 @@ var ConfigPane = function ConfigPane(_ref) {
3562
3593
  return _ref2.apply(this, arguments);
3563
3594
  };
3564
3595
  }();
3596
+ useHotkeys(SHORTCUTS["continue"].sequence, handleContinue, {
3597
+ enabled: shouldAdvanceToRecipient,
3598
+ mode: "global"
3599
+ });
3565
3600
  return /*#__PURE__*/jsxs(Fragment, {
3566
3601
  children: [/*#__PURE__*/jsx(Panel.Header, {
3567
3602
  children: /*#__PURE__*/jsxs("div", {
3568
3603
  className: "flex w-full flex-col gap-y-2",
3569
3604
  children: [/*#__PURE__*/jsx(Typography, {
3605
+ "data-testid": "pane-title",
3570
3606
  style: "h3",
3571
3607
  children: title
3572
3608
  }), configSubtitle && /*#__PURE__*/jsx(Typography, {
@@ -3576,6 +3612,7 @@ var ConfigPane = function ConfigPane(_ref) {
3576
3612
  }), showSearch && /*#__PURE__*/jsx("div", {
3577
3613
  className: "mb-pane-search",
3578
3614
  children: /*#__PURE__*/jsx(Input, {
3615
+ dataTestid: "pane-search",
3579
3616
  placeholder: t("neetoRules.builder.searchPlaceholder"),
3580
3617
  prefix: /*#__PURE__*/jsx(Search, {}),
3581
3618
  size: "large",
@@ -3617,6 +3654,7 @@ var ConfigPane = function ConfigPane(_ref) {
3617
3654
  })
3618
3655
  }), shouldAdvanceToRecipient && /*#__PURE__*/jsx(Panel.Footer, {
3619
3656
  children: /*#__PURE__*/jsx(Button, {
3657
+ "data-testid": "continue-button",
3620
3658
  label: t("neetoRules.buttons.continue"),
3621
3659
  size: "large",
3622
3660
  onClick: handleContinue
@@ -3673,6 +3711,7 @@ var DelayPane = function DelayPane(_ref) {
3673
3711
  children: /*#__PURE__*/jsxs("div", {
3674
3712
  className: "flex flex-col gap-y-1",
3675
3713
  children: [/*#__PURE__*/jsx(Typography, {
3714
+ "data-testid": "pane-title",
3676
3715
  style: "h3",
3677
3716
  children: t("neetoRules.common.addDelay")
3678
3717
  }), /*#__PURE__*/jsx(Typography, {
@@ -3694,6 +3733,7 @@ var DelayPane = function DelayPane(_ref) {
3694
3733
  className: "flex items-start gap-x-2",
3695
3734
  children: [/*#__PURE__*/jsx(Input$1, {
3696
3735
  className: "w-44",
3736
+ dataTestid: "delay-value",
3697
3737
  max: MAX_DELAY_VALUE,
3698
3738
  min: MIN_DELAY_VALUE,
3699
3739
  name: "".concat(name, ".value.value"),
@@ -3701,6 +3741,7 @@ var DelayPane = function DelayPane(_ref) {
3701
3741
  size: "large",
3702
3742
  type: "number"
3703
3743
  }), /*#__PURE__*/jsx(Select, {
3744
+ dataTestid: "delay-unit",
3704
3745
  defaultValue: findBy({
3705
3746
  value: value === null || value === void 0 ? void 0 : value.unit
3706
3747
  }, unitOptions),
@@ -3737,6 +3778,7 @@ var asText = function asText(value) {
3737
3778
  var NumberStepper = function NumberStepper(_ref) {
3738
3779
  var value = _ref.value,
3739
3780
  onChange = _ref.onChange,
3781
+ dataTestid = _ref.dataTestid,
3740
3782
  label = _ref.label,
3741
3783
  _ref$min = _ref.min,
3742
3784
  min = _ref$min === void 0 ? STEPPER_MIN_VALUE : _ref$min,
@@ -3770,6 +3812,7 @@ var NumberStepper = function NumberStepper(_ref) {
3770
3812
  return /*#__PURE__*/jsx("div", {
3771
3813
  className: "mb-stepper",
3772
3814
  children: /*#__PURE__*/jsx(Input, {
3815
+ dataTestid: dataTestid,
3773
3816
  error: error,
3774
3817
  label: label,
3775
3818
  min: min,
@@ -3782,6 +3825,7 @@ var NumberStepper = function NumberStepper(_ref) {
3782
3825
  children: [/*#__PURE__*/jsx("button", {
3783
3826
  "aria-label": t("neetoRules.builder.aria.increase"),
3784
3827
  className: "mb-stepper-btn",
3828
+ "data-testid": "stepper-increase",
3785
3829
  tabIndex: SKIP_TAB_INDEX,
3786
3830
  type: "button",
3787
3831
  onClick: function onClick() {
@@ -3791,6 +3835,7 @@ var NumberStepper = function NumberStepper(_ref) {
3791
3835
  }), /*#__PURE__*/jsx("button", {
3792
3836
  "aria-label": t("neetoRules.builder.aria.decrease"),
3793
3837
  className: "mb-stepper-btn",
3838
+ "data-testid": "stepper-decrease",
3794
3839
  tabIndex: SKIP_TAB_INDEX,
3795
3840
  type: "button",
3796
3841
  onClick: function onClick() {
@@ -3852,6 +3897,7 @@ var LeadTimePane = function LeadTimePane(_ref) {
3852
3897
  children: /*#__PURE__*/jsxs("div", {
3853
3898
  className: "flex flex-col gap-y-1",
3854
3899
  children: [/*#__PURE__*/jsx(Typography, {
3900
+ "data-testid": "pane-title",
3855
3901
  style: "h3",
3856
3902
  children: t("neetoRules.builder.leadTimeTitle")
3857
3903
  }), /*#__PURE__*/jsx(Typography, {
@@ -3873,6 +3919,7 @@ var LeadTimePane = function LeadTimePane(_ref) {
3873
3919
  children: [/*#__PURE__*/jsx("div", {
3874
3920
  className: "flex-1",
3875
3921
  children: /*#__PURE__*/jsx(NumberStepper, {
3922
+ dataTestid: "lead-time",
3876
3923
  error: touched ? error : "",
3877
3924
  value: amount,
3878
3925
  onChange: function onChange(value) {
@@ -3885,6 +3932,7 @@ var LeadTimePane = function LeadTimePane(_ref) {
3885
3932
  }), /*#__PURE__*/jsx("div", {
3886
3933
  className: "w-32 shrink-0",
3887
3934
  children: /*#__PURE__*/jsx(Select$1, {
3935
+ dataTestid: "lead-time-unit",
3888
3936
  isSearchable: false,
3889
3937
  options: LEAD_TIME_UNITS,
3890
3938
  value: findBy({
@@ -3918,6 +3966,7 @@ var NamePane = function NamePane(_ref) {
3918
3966
  children: /*#__PURE__*/jsxs("div", {
3919
3967
  className: "flex flex-col gap-y-1",
3920
3968
  children: [/*#__PURE__*/jsx(Typography, {
3969
+ "data-testid": "pane-title",
3921
3970
  style: "h3",
3922
3971
  children: t("neetoRules.builder.automationName")
3923
3972
  }), /*#__PURE__*/jsx(Typography, {
@@ -4059,6 +4108,11 @@ var OptionsPane = function OptionsPane(_ref) {
4059
4108
  data: target.data
4060
4109
  });else closePane();
4061
4110
  };
4111
+ var canContinue = cascade && selectedValues.some(Boolean);
4112
+ useHotkeys(SHORTCUTS["continue"].sequence, handleContinue, {
4113
+ enabled: canContinue,
4114
+ mode: "global"
4115
+ });
4062
4116
  var optionLabel = function optionLabel(option) {
4063
4117
  var Icon = option.icon;
4064
4118
  if (!Icon && !option.disabledReason) return option.label;
@@ -4090,6 +4144,7 @@ var OptionsPane = function OptionsPane(_ref) {
4090
4144
  if (isEmpty(filtered)) {
4091
4145
  return /*#__PURE__*/jsx("div", {
4092
4146
  className: "mb-pane-empty",
4147
+ "data-testid": "pane-no-matches",
4093
4148
  children: t("neetoRules.builder.noMatches")
4094
4149
  });
4095
4150
  }
@@ -4149,6 +4204,7 @@ var OptionsPane = function OptionsPane(_ref) {
4149
4204
  children: /*#__PURE__*/jsxs("div", {
4150
4205
  className: "flex w-full flex-col gap-y-2",
4151
4206
  children: [/*#__PURE__*/jsx(Typography, {
4207
+ "data-testid": "pane-title",
4152
4208
  style: "h3",
4153
4209
  children: title
4154
4210
  }), /*#__PURE__*/jsx(Typography, {
@@ -4159,6 +4215,7 @@ var OptionsPane = function OptionsPane(_ref) {
4159
4215
  className: "mb-pane-search",
4160
4216
  ref: searchRef,
4161
4217
  children: /*#__PURE__*/jsx(Input, {
4218
+ dataTestid: "pane-search",
4162
4219
  placeholder: t("neetoRules.builder.searchPlaceholder"),
4163
4220
  prefix: /*#__PURE__*/jsx(Search, {}),
4164
4221
  size: "large",
@@ -4173,7 +4230,8 @@ var OptionsPane = function OptionsPane(_ref) {
4173
4230
  children: [renderBody(), belowContent]
4174
4231
  }), cascade && /*#__PURE__*/jsx(Panel.Footer, {
4175
4232
  children: /*#__PURE__*/jsx(Button, {
4176
- disabled: !selectedValues.some(Boolean),
4233
+ "data-testid": "continue-button",
4234
+ disabled: !canContinue,
4177
4235
  label: t("neetoRules.buttons.continue"),
4178
4236
  size: "large",
4179
4237
  onClick: handleContinue
@@ -4335,6 +4393,7 @@ var RecipientPane = function RecipientPane(_ref) {
4335
4393
  children: /*#__PURE__*/jsxs("div", {
4336
4394
  className: "flex w-full flex-col gap-y-2",
4337
4395
  children: [/*#__PURE__*/jsx(Typography, {
4396
+ "data-testid": "pane-title",
4338
4397
  style: "h3",
4339
4398
  children: meta.recipientTitle || t("neetoRules.builder.panes.recipientTitle")
4340
4399
  }), /*#__PURE__*/jsx(Typography, {
@@ -4381,6 +4440,7 @@ var ConditionValueFields = function ConditionValueFields(_ref) {
4381
4440
  };
4382
4441
  var noMatches = /*#__PURE__*/jsx("div", {
4383
4442
  className: "mb-pane-empty",
4443
+ "data-testid": "pane-no-matches",
4384
4444
  children: t("neetoRules.builder.noMatches")
4385
4445
  });
4386
4446
  if (type === CONDITION_VALUE_TYPES.multiSelect && isNotEmpty(enumOptions)) {
@@ -4535,6 +4595,7 @@ var ValuePane = function ValuePane(_ref) {
4535
4595
  children: /*#__PURE__*/jsxs("div", {
4536
4596
  className: "flex w-full flex-col gap-y-2",
4537
4597
  children: [/*#__PURE__*/jsx(Typography, {
4598
+ "data-testid": "pane-title",
4538
4599
  style: "h3",
4539
4600
  children: t("neetoRules.builder.pickValue", {
4540
4601
  field: (field === null || field === void 0 ? void 0 : field.label) || t("neetoRules.builder.valueWord")
@@ -4549,6 +4610,7 @@ var ValuePane = function ValuePane(_ref) {
4549
4610
  className: "mb-pane-search",
4550
4611
  ref: searchRef,
4551
4612
  children: /*#__PURE__*/jsx(Input, {
4613
+ dataTestid: "pane-search",
4552
4614
  placeholder: t("neetoRules.builder.searchPlaceholder"),
4553
4615
  prefix: /*#__PURE__*/jsx(Search, {}),
4554
4616
  size: "large",