@shopgate/pwa-ui-shared 7.30.0-alpha.7 → 7.30.0-alpha.8

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 (266) hide show
  1. package/AccordionContainer/index.js +39 -5
  2. package/AccordionContainer/spec.js +25 -2
  3. package/ActionButton/index.js +63 -7
  4. package/ActionButton/spec.js +59 -2
  5. package/ActionButton/style.js +22 -1
  6. package/AddToCartButton/index.js +184 -27
  7. package/AddToCartButton/mock.js +18 -4
  8. package/AddToCartButton/spec.js +51 -2
  9. package/AddToCartButton/style.js +127 -11
  10. package/Availability/index.js +34 -2
  11. package/Availability/spec.js +41 -1
  12. package/Availability/style.js +19 -1
  13. package/Button/index.js +76 -5
  14. package/Button/spec.js +33 -1
  15. package/Button/style.js +130 -21
  16. package/ButtonLink/connector.js +11 -2
  17. package/ButtonLink/index.js +44 -6
  18. package/ButtonLink/spec.js +23 -1
  19. package/Card/index.js +19 -2
  20. package/Card/style.js +11 -1
  21. package/CardList/components/Item/index.js +26 -2
  22. package/CardList/components/Item/style.js +7 -1
  23. package/CardList/index.js +34 -3
  24. package/CartTotalLine/components/Amount/index.js +28 -2
  25. package/CartTotalLine/components/Amount/style.js +8 -1
  26. package/CartTotalLine/components/Hint/index.js +23 -2
  27. package/CartTotalLine/components/Hint/style.js +12 -1
  28. package/CartTotalLine/components/Label/index.js +36 -2
  29. package/CartTotalLine/components/Label/style.js +17 -1
  30. package/CartTotalLine/components/Spacer/index.js +16 -2
  31. package/CartTotalLine/index.js +39 -2
  32. package/CartTotalLine/style.js +31 -1
  33. package/Checkbox/index.js +31 -2
  34. package/Checkbox/style.js +18 -1
  35. package/Chip/index.js +61 -2
  36. package/Chip/spec.js +24 -1
  37. package/Chip/style.js +71 -3
  38. package/ContextMenu/ContextMenu.hooks.js +6 -2
  39. package/ContextMenu/ContextMenuProvider.context.js +9 -3
  40. package/ContextMenu/ContextMenuProvider.js +21 -2
  41. package/ContextMenu/components/Item/index.js +67 -5
  42. package/ContextMenu/components/Item/style.js +32 -3
  43. package/ContextMenu/components/Position/index.js +61 -10
  44. package/ContextMenu/components/Position/style.js +11 -1
  45. package/ContextMenu/index.js +124 -3
  46. package/ContextMenu/spec.js +101 -2
  47. package/ContextMenu/style.js +45 -1
  48. package/Dialog/components/BasicDialog/index.js +5 -1
  49. package/Dialog/components/HtmlContentDialog/index.js +22 -2
  50. package/Dialog/components/HtmlContentDialog/spec.js +59 -1
  51. package/Dialog/components/PipelineErrorDialog/index.js +114 -25
  52. package/Dialog/components/PipelineErrorDialog/spec.js +92 -12
  53. package/Dialog/components/TextMessageDialog/index.js +28 -2
  54. package/Dialog/components/TextMessageDialog/spec.js +59 -1
  55. package/Dialog/components/VariantSelectModal/connector.js +11 -2
  56. package/Dialog/components/VariantSelectModal/index.js +65 -6
  57. package/Dialog/components/VariantSelectModal/spec.js +51 -2
  58. package/Dialog/constants.js +6 -1
  59. package/Dialog/index.js +114 -7
  60. package/Dialog/spec.js +81 -3
  61. package/DiscountBadge/index.js +30 -2
  62. package/DiscountBadge/spec.js +19 -1
  63. package/DiscountBadge/style.js +34 -2
  64. package/FavoritesButton/connector.js +18 -3
  65. package/FavoritesButton/index.js +118 -15
  66. package/FavoritesButton/mock.js +50 -4
  67. package/FavoritesButton/spec.js +120 -2
  68. package/FavoritesButton/style.js +26 -1
  69. package/Form/Builder/builders/buildCountryList.js +40 -6
  70. package/Form/Builder/builders/buildFormDefaults.js +35 -6
  71. package/Form/Builder/builders/buildFormElements.js +68 -10
  72. package/Form/Builder/builders/buildProvinceList.js +19 -2
  73. package/Form/Builder/builders/buildValidationErrorList.js +7 -2
  74. package/Form/Builder/classes/ActionListener/constants.js +22 -2
  75. package/Form/Builder/classes/ActionListener/index.js +441 -93
  76. package/Form/Builder/classes/ActionListener/spec.js +321 -19
  77. package/Form/Builder/components/CheckboxElement.js +35 -3
  78. package/Form/Builder/components/CountryElement.js +40 -3
  79. package/Form/Builder/components/ProvinceElement.js +40 -3
  80. package/Form/Builder/components/RadioElement.js +41 -3
  81. package/Form/Builder/components/SelectElement.js +39 -3
  82. package/Form/Builder/components/TextElement.js +49 -4
  83. package/Form/Builder/elementTypes.js +11 -1
  84. package/Form/Builder/index.js +298 -52
  85. package/Form/Builder/iso-3166-2.js +4943 -1
  86. package/Form/Builder/spec.js +300 -16
  87. package/Form/Checkbox/index.js +66 -4
  88. package/Form/Checkbox/style.js +25 -2
  89. package/Form/InfoField/index.js +50 -2
  90. package/Form/InfoField/spec.js +9 -1
  91. package/Form/InfoField/style.js +11 -1
  92. package/Form/Password/index.js +51 -6
  93. package/Form/Password/spec.js +34 -1
  94. package/Form/Password/style.js +11 -1
  95. package/Form/RadioGroup/components/Item/index.js +59 -3
  96. package/Form/RadioGroup/components/Item/style.js +32 -2
  97. package/Form/RadioGroup/index.js +101 -9
  98. package/Form/RadioGroup/spec.js +83 -3
  99. package/Form/RadioGroup/style.js +18 -2
  100. package/Form/Select/index.js +158 -10
  101. package/Form/Select/spec.js +36 -5
  102. package/Form/Select/style.js +27 -1
  103. package/Form/SelectContextChoices/index.js +77 -3
  104. package/Form/SelectContextChoices/spec.js +33 -4
  105. package/Form/SelectContextChoices/style.js +23 -1
  106. package/Form/TextField/index.js +92 -8
  107. package/Form/TextField/spec.js +110 -1
  108. package/Form/TextField/style.js +66 -8
  109. package/Form/index.js +54 -13
  110. package/FormElement/components/ErrorText/index.js +31 -2
  111. package/FormElement/components/ErrorText/style.js +13 -1
  112. package/FormElement/components/Label/index.js +35 -2
  113. package/FormElement/components/Label/style.js +76 -8
  114. package/FormElement/components/Placeholder/index.js +26 -2
  115. package/FormElement/components/Placeholder/style.js +48 -6
  116. package/FormElement/components/Underline/index.js +18 -2
  117. package/FormElement/components/Underline/style.js +51 -4
  118. package/FormElement/index.js +91 -6
  119. package/FormElement/spec.js +67 -2
  120. package/FormElement/style.js +13 -2
  121. package/Glow/index.js +90 -7
  122. package/Glow/spec.js +9 -1
  123. package/Glow/style.js +18 -1
  124. package/IndicatorCircle/index.js +33 -3
  125. package/IndicatorCircle/spec.js +28 -1
  126. package/IndicatorCircle/style.js +57 -3
  127. package/LoadingIndicator/index.js +29 -2
  128. package/LoadingIndicator/style.js +20 -1
  129. package/Manufacturer/index.js +20 -2
  130. package/Manufacturer/style.js +5 -1
  131. package/MessageBar/index.js +36 -2
  132. package/MessageBar/spec.js +79 -1
  133. package/MessageBar/style.js +38 -1
  134. package/NoResults/components/Icon/index.js +130 -2
  135. package/NoResults/components/Icon/style.js +17 -1
  136. package/NoResults/index.js +46 -2
  137. package/NoResults/style.js +31 -1
  138. package/Placeholder/index.js +25 -3
  139. package/Placeholder/style.js +11 -1
  140. package/PlaceholderLabel/index.js +27 -2
  141. package/PlaceholderLabel/spec.js +19 -1
  142. package/PlaceholderLabel/style.js +12 -1
  143. package/PlaceholderParagraph/index.js +36 -2
  144. package/PlaceholderParagraph/spec.js +19 -1
  145. package/Price/index.js +88 -7
  146. package/Price/style.js +22 -1
  147. package/PriceInfo/index.js +20 -2
  148. package/PriceInfo/style.js +5 -1
  149. package/PriceStriked/index.js +83 -12
  150. package/PriceStriked/style.js +33 -3
  151. package/ProductProperties/index.js +32 -2
  152. package/ProgressBar/index.js +101 -13
  153. package/ProgressBar/spec.js +13 -1
  154. package/ProgressBar/style.js +83 -2
  155. package/RadioButton/index.js +18 -2
  156. package/RadioButton/spec.js +21 -1
  157. package/RadioButton/style.js +21 -1
  158. package/RatingNumber/index.js +29 -2
  159. package/RatingStars/constants.js +2 -1
  160. package/RatingStars/index.js +130 -12
  161. package/RatingStars/spec.js +90 -3
  162. package/RatingStars/style.js +51 -2
  163. package/Ripple/components/RippleAnimation/index.js +88 -6
  164. package/Ripple/index.js +218 -40
  165. package/Ripple/style.js +18 -1
  166. package/RippleButton/index.js +52 -5
  167. package/RippleButton/spec.js +45 -1
  168. package/ScannerOverlay/components/CameraOverlay/index.js +13 -2
  169. package/ScannerOverlay/components/CameraOverlay/style.js +41 -1
  170. package/ScannerOverlay/components/ScannerBar/components/FlashlightButton/index.js +34 -2
  171. package/ScannerOverlay/components/ScannerBar/components/FlashlightButton/style.js +28 -1
  172. package/ScannerOverlay/components/ScannerBar/components/ScannerInstructions/index.js +11 -2
  173. package/ScannerOverlay/components/ScannerBar/index.js +31 -2
  174. package/ScannerOverlay/components/ScannerBar/style.js +20 -1
  175. package/ScannerOverlay/index.js +47 -7
  176. package/Sheet/components/Header/components/SearchBar/index.js +46 -2
  177. package/Sheet/components/Header/components/SearchBar/spec.js +21 -3
  178. package/Sheet/components/Header/components/SearchBar/style.js +47 -1
  179. package/Sheet/components/Header/index.js +75 -7
  180. package/Sheet/components/Header/spec.js +14 -1
  181. package/Sheet/components/Header/style.js +50 -1
  182. package/Sheet/index.js +170 -17
  183. package/Sheet/spec.js +85 -5
  184. package/Sheet/style.js +143 -2
  185. package/TaxDisclaimer/index.js +34 -4
  186. package/TaxDisclaimer/spec.js +31 -3
  187. package/TaxDisclaimer/style.js +9 -1
  188. package/TextField/components/ErrorText/index.js +33 -2
  189. package/TextField/components/ErrorText/style.js +25 -3
  190. package/TextField/components/FormElement/index.js +19 -2
  191. package/TextField/components/FormElement/style.js +32 -4
  192. package/TextField/components/Hint/index.js +21 -2
  193. package/TextField/components/Hint/style.js +40 -5
  194. package/TextField/components/Label/index.js +32 -3
  195. package/TextField/components/Label/style.js +68 -8
  196. package/TextField/components/Underline/index.js +19 -2
  197. package/TextField/components/Underline/style.js +51 -4
  198. package/TextField/index.js +189 -27
  199. package/TextField/spec.js +128 -3
  200. package/TextField/style.js +34 -4
  201. package/ToggleIcon/index.js +58 -8
  202. package/ToggleIcon/spec.js +35 -1
  203. package/icons/AccountBoxIcon.js +11 -2
  204. package/icons/AddMoreIcon.js +11 -2
  205. package/icons/ArrowDropIcon.js +11 -2
  206. package/icons/ArrowIcon.js +21 -2
  207. package/icons/BarcodeScannerIcon.js +11 -2
  208. package/icons/BoxIcon.js +11 -2
  209. package/icons/BrowseIcon.js +11 -2
  210. package/icons/BurgerIcon.js +11 -2
  211. package/icons/CalendarIcon.js +15 -3
  212. package/icons/CartCouponIcon.js +72 -2
  213. package/icons/CartIcon.js +11 -2
  214. package/icons/CartPlusIcon.js +11 -2
  215. package/icons/CheckIcon.js +11 -2
  216. package/icons/CheckedIcon.js +11 -2
  217. package/icons/ChevronIcon.js +11 -2
  218. package/icons/CreditCardIcon.js +11 -2
  219. package/icons/CrossIcon.js +11 -2
  220. package/icons/DescriptionIcon.js +11 -2
  221. package/icons/FilterIcon.js +11 -2
  222. package/icons/FlashDisabledIcon.js +11 -2
  223. package/icons/FlashEnabledIcon.js +11 -2
  224. package/icons/GridIcon.js +11 -2
  225. package/icons/HeartIcon.js +11 -2
  226. package/icons/HeartOutlineIcon.js +11 -2
  227. package/icons/HeartPlusIcon.js +12 -2
  228. package/icons/HeartPlusOutlineIcon.js +12 -2
  229. package/icons/HomeIcon.js +11 -2
  230. package/icons/InfoIcon.js +11 -2
  231. package/icons/InfoOutlineIcon.js +11 -2
  232. package/icons/ListIcon.js +11 -2
  233. package/icons/LocalShippingIcon.js +11 -2
  234. package/icons/LocationIcon.js +13 -3
  235. package/icons/LocatorIcon.js +11 -2
  236. package/icons/LockIcon.js +11 -2
  237. package/icons/LogoutIcon.js +11 -2
  238. package/icons/MagnifierIcon.js +11 -2
  239. package/icons/MapMarkerIcon.js +24 -3
  240. package/icons/MoreIcon.js +11 -2
  241. package/icons/MoreVertIcon.js +11 -2
  242. package/icons/NotificationIcon.js +14 -3
  243. package/icons/PersonIcon.js +12 -2
  244. package/icons/PhoneIcon.js +13 -3
  245. package/icons/PlaceholderIcon.js +11 -2
  246. package/icons/RadioCheckedIcon.js +11 -2
  247. package/icons/RadioUncheckedIcon.js +11 -2
  248. package/icons/SecurityIcon.js +11 -2
  249. package/icons/ShippingMethodIcon.js +18 -3
  250. package/icons/ShoppingCartIcon.js +11 -2
  251. package/icons/SortIcon.js +11 -2
  252. package/icons/StarHalfIcon.js +18 -2
  253. package/icons/StarIcon.js +18 -2
  254. package/icons/StarOutlineIcon.js +11 -2
  255. package/icons/StopIcon.js +11 -2
  256. package/icons/TickIcon.js +11 -2
  257. package/icons/TimeIcon.js +14 -3
  258. package/icons/TrashIcon.js +11 -2
  259. package/icons/TrashOutlineIcon.js +12 -2
  260. package/icons/UncheckedIcon.js +11 -2
  261. package/icons/ViewListIcon.js +11 -2
  262. package/icons/VisibilityIcon.js +11 -2
  263. package/icons/VisibilityOffIcon.js +11 -2
  264. package/icons/WarningIcon.js +11 -2
  265. package/index.js +13 -1
  266. package/package.json +5 -5
@@ -1,97 +1,445 @@
1
- function _slicedToArray(arr,i){return _arrayWithHoles(arr)||_iterableToArrayLimit(arr,i)||_nonIterableRest();}function _nonIterableRest(){throw new TypeError("Invalid attempt to destructure non-iterable instance");}function _iterableToArrayLimit(arr,i){var _arr=[];var _n=true;var _d=false;var _e=undefined;try{for(var _i=arr[Symbol.iterator](),_s;!(_n=(_s=_i.next()).done);_n=true){_arr.push(_s.value);if(i&&_arr.length===i)break;}}catch(err){_d=true;_e=err;}finally{try{if(!_n&&_i["return"]!=null)_i["return"]();}finally{if(_d)throw _e;}}return _arr;}function _arrayWithHoles(arr){if(Array.isArray(arr))return arr;}function _typeof(obj){if(typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"){_typeof=function _typeof(obj){return typeof obj;};}else{_typeof=function _typeof(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};}return _typeof(obj);}function _extends(){_extends=Object.assign||function(target){for(var i=1;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(Object.prototype.hasOwnProperty.call(source,key)){target[key]=source[key];}}}return target;};return _extends.apply(this,arguments);}function _defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor);}}function _createClass(Constructor,protoProps,staticProps){if(protoProps)_defineProperties(Constructor.prototype,protoProps);if(staticProps)_defineProperties(Constructor,staticProps);return Constructor;}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function");}}function _defineProperty(obj,key,value){if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:true,configurable:true,writable:true});}else{obj[key]=value;}return obj;}import{logger}from'@shopgate/pwa-core/helpers';import{ELEMENT_TYPE_NUMBER,ELEMENT_TYPE_COUNTRY,ELEMENT_TYPE_PROVINCE,ELEMENT_TYPE_CHECKBOX}from"../../elementTypes";import{ACTION_TYPE_UPDATE_PROVINCE_ELEMENT,ACTION_TYPE_SET_VISIBILITY,ACTION_TYPE_SET_VALUE,ACTION_TYPE_TRANSFORM,ACTION_SET_VALUE_FIXED,ACTION_SET_VALUE_COPY_FROM,ACTION_SET_VALUE_LENGTH_OF,ACTION_RULE_TYPE_NOT_IN,ACTION_RULE_TYPE_ONE_OF,ACTION_RULE_TYPE_BOOLEAN,ACTION_RULE_TYPE_REGEX,ACTION_RULE_DATA_TYPES,ACTION_RULES_CONCAT_METHOD_ALL,ACTION_RULES_CONCAT_METHOD_ANY,ACTION_RULES_CONCAT_METHOD_NONE}from"./constants";/**
1
+ import { logger } from '@shopgate/pwa-core/helpers';
2
+ import { ELEMENT_TYPE_NUMBER, ELEMENT_TYPE_COUNTRY, ELEMENT_TYPE_PROVINCE, ELEMENT_TYPE_CHECKBOX } from "../../elementTypes";
3
+ import { ACTION_TYPE_UPDATE_PROVINCE_ELEMENT, ACTION_TYPE_SET_VISIBILITY, ACTION_TYPE_SET_VALUE, ACTION_TYPE_TRANSFORM, ACTION_SET_VALUE_FIXED, ACTION_SET_VALUE_COPY_FROM, ACTION_SET_VALUE_LENGTH_OF, ACTION_RULE_TYPE_NOT_IN, ACTION_RULE_TYPE_ONE_OF, ACTION_RULE_TYPE_BOOLEAN, ACTION_RULE_TYPE_REGEX, ACTION_RULE_DATA_TYPES, ACTION_RULES_CONCAT_METHOD_ALL, ACTION_RULES_CONCAT_METHOD_ANY, ACTION_RULES_CONCAT_METHOD_NONE } from "./constants";
4
+
5
+ /**
2
6
  * ActionListener and handler for the FormBuilder component
3
- */var ActionListener=/*#__PURE__*/_createClass(/**
7
+ */
8
+ class ActionListener {
9
+ /**
4
10
  * Constructor
5
11
  * @param {function(string)} getProvincesList Takes a country code and returns a list of provinces
6
12
  * @param {Object} defaults Form defaults
7
- */function ActionListener(getProvincesList,defaults){var _this=this;_classCallCheck(this,ActionListener);/**
8
- * Takes the elements to be rendered by the FormBuilder and attaches available action listeners
9
- * to the component.
10
- * @param {FormElement[]} elementList List of all elements
11
- */_defineProperty(this,"attachAll",function(elementList){// Attach action listeners for element (context) actions
12
- elementList.forEach(function(element){var elementActions=element.actions;if(element.type===ELEMENT_TYPE_PROVINCE){elementActions=elementActions||[];// Requires a country element to create a "update provinces" action
13
- var countryElement=elementList.find(function(el){return el.type===ELEMENT_TYPE_COUNTRY;});if(countryElement){// Attach new action, which is always triggered, when the (only) country element changes
14
- elementActions.push({type:ACTION_TYPE_UPDATE_PROVINCE_ELEMENT,rules:[{context:countryElement.id}]});}}if(elementActions===undefined){return;}// Create listeners for all supported actions
15
- elementActions.forEach(function(action){var actionRules=action.rules||[];// Always apply action to itself if no rules given
16
- if(actionRules.length===0){// Define a basic rule if no rules given
17
- actionRules.push({context:element.id});}// Actions do have a fixed structure which needs to be fulfilled
18
- var normalizedAction=_extends({},action,{rules:actionRules});// Assign the action listeners to all contexts of the current element
19
- actionRules.forEach(function(rule){_this.attach(element,normalizedAction,rule);});});});});/**
20
- * Attaches one or possibly multiple action listeners for the given rule
21
- * @param {FormElement} element The current element that is modified by the action
22
- * @param {FormFieldAction} action The action and it's params
23
- * @param {FormFieldActionRule} rule The rule to check in case the action listener is triggered
24
- */_defineProperty(this,"attach",function(element,action,rule){var actionListener;switch(action.type){case ACTION_TYPE_UPDATE_PROVINCE_ELEMENT:{actionListener=_this.createUpdateProvinceElementHandler(element,action);break;}case ACTION_TYPE_SET_VISIBILITY:{// Visibility is special and uses the result of the evaluation itself
25
- actionListener=_this.createSetVisibilityHandler(element,action);break;}case ACTION_TYPE_SET_VALUE:{actionListener=_this.createEvaluatedHandler(element,action,_this.createSetValueHandler(element,action));break;}case ACTION_TYPE_TRANSFORM:{actionListener=_this.createEvaluatedHandler(element,action,_this.createTransformHandler(element,action));break;}default:return;}_this.register(rule.context,actionListener);});/**
26
- * Action listener creator to check all related rules before calling any further action listeners
27
- * @param {FormElement} element The element for which the listener should be created for
28
- * @param {FormFieldAction} action The action to be create a listener for
29
- * @param {Function} actionListener The action listener to call if the rule applies
30
- * @returns {Function} Returns a function to modify and return the modified state.
31
- */_defineProperty(this,"createEvaluatedHandler",function(element,action,actionListener){return function(prevState,nextState){// Apply rules before accepting any changes
32
- if(!_this.evaluateRules(element,action,nextState)){return nextState;}return actionListener(prevState,nextState);};});/**
33
- * Action listener creator to handle "updateCountryChange" action
34
- * @param {FormElement} provinceEl The element for which the listener should be created for
35
- * @param {FormFieldAction} action The action to be create a listener for
36
- * @returns {Function} Returns a function to modify and return the modified state.
37
- */_defineProperty(this,"createUpdateProvinceElementHandler",function(provinceEl,action){return function(prevState,nextState){var countryElementId=action.rules[0].context;var countryValue=nextState.formData[countryElementId];var countryDefault=_this.defaults[countryElementId];var newState=_extends({},nextState);// Overwrite province with the form's default, if country matches the default as well
38
- if(countryValue===countryDefault){newState.formData[provinceEl.id]=_this.defaults[provinceEl.id];}else{// Update province to first or no selection, based on "required" attribute
39
- newState.formData[provinceEl.id]=!provinceEl.required?'':Object.keys(_this.getProvincesList(countryValue))[0];}return newState;};});/**
40
- * Action listener creator to handle "setVisibility" actions
41
- * @param {FormElement} element The element for which the listener should be created for
42
- * @param {FormFieldAction} action The action to be create a listener for
43
- * @returns {Function} Returns a function to modify and return the modified state.
44
- */_defineProperty(this,"createSetVisibilityHandler",function(element,action){return function(prevState,nextState){var newState=_extends({},nextState,{elementVisibility:_extends({},nextState.elementVisibility,_defineProperty({},element.id,_this.evaluateRules(element,action,nextState))),// Copy form data to be able to check changes and all follow up actions
45
- formData:_extends({},nextState.formData)});if(newState.formData[element.id]===undefined&&newState.elementVisibility[element.id]){newState.formData[element.id]=_this.defaults[element.id];}else if(!newState.elementVisibility[element.id]&&newState.formData[element.id]!==undefined){delete newState.formData[element.id];}// Notify follow up listeners about the current change
46
- if(nextState.formData[element.id]!==newState.formData[element.id]){newState=_this.notify(element.id,prevState,newState);}return newState;};});/**
47
- * Action listener creator to handle "setValue" actions
48
- * @param {FormElement} element The element for which the listener should be created for
49
- * @param {FormFieldAction} action The action to be create a listener for
50
- * @returns {Function} Returns the modified state.
51
- */_defineProperty(this,"createSetValueHandler",function(element,action){return function(prevState,nextState){if(_typeof(action.params)!=='object'||Array.isArray(action.params)){logger.error("Error: Invalid or missing form action in element '".concat(element.id,"'. ")+'Params must be in the format: { "type": string, "value": string }');return nextState;}var value=action.params.value;// Check correctness of value data type
52
- switch(_typeof(value)){case'boolean':if(element.type!==ELEMENT_TYPE_CHECKBOX){logger.error("Error: Invalid form action param in element '".concat(element.id,"'. ")+"Allowed '".concat(ELEMENT_TYPE_CHECKBOX,"' data type for 'params.value' is: 'boolean'"));return nextState;}break;case'number':if(element.type!==ELEMENT_TYPE_NUMBER){logger.error("Error: Invalid form action param in element '".concat(element.id,"'. ")+"Allowed '".concat(ELEMENT_TYPE_NUMBER,"' data types for 'params.value' are: ")+"'number' and 'string'");return nextState;}break;case'string':if(element.type===ELEMENT_TYPE_CHECKBOX){logger.error("Error: Invalid form action param in element '".concat(element.id,"'. ")+"Allowed '".concat(ELEMENT_TYPE_CHECKBOX,"' data type for 'params.value' is: 'boolean'"));return nextState;}break;default:logger.error("Error: Invalid form action param in element '".concat(element.id,"'. ")+"Can not use '".concat(_typeof(value),"' data for elements of type '").concat(element.type,"'"));return nextState;}// Perform action based on "setValue" type, defined in params
53
- switch(action.params.type){case ACTION_SET_VALUE_LENGTH_OF:value="".concat(nextState.formData[action.params.value].length);break;case ACTION_SET_VALUE_COPY_FROM:value=nextState.formData[action.params.value];break;case undefined:case ACTION_SET_VALUE_FIXED:break;default:logger.error("Error: Invalid form action param 'type' in element '".concat(element.id,"'. ")+"Allowed param types are: '".concat(ACTION_SET_VALUE_LENGTH_OF,"', ")+"'".concat(ACTION_SET_VALUE_COPY_FROM,"', '").concat(ACTION_SET_VALUE_FIXED,"'"));return nextState;}var newState=_extends({},nextState,{formData:_extends({},nextState.formData,_defineProperty({},element.id,value))});// Notify follow up listeners about the current change, if there are any changes
54
- if(nextState.formData[element.id]!==value){newState=_this.notify(element.id,prevState,newState);}return newState;};});/**
55
- * Action listener creator to handle "transform" actions
56
- * @param {FormElement} element The element for which the listener should be created for
57
- * @param {FormFieldAction} action The action to be create a listener for
58
- * @returns {Function} Returns a function to modify and return the modified state.
59
- */_defineProperty(this,"createTransformHandler",function(element,action){return function(prevState,nextState){/**
60
- * Takes a string and applies a case function on it
61
- * @param {string|boolean|number} subject The subject to be transformed
62
- * @returns {string|boolean|number}
63
- */var transform=function transform(subject){// Get optional params to be applied in the transformation process
64
- var args=action.params.value||[];if(Array.isArray(action.params.value)){args=action.params.value;}switch(_typeof(subject)){case'string':{if(typeof String.prototype[action.params.type]!=='function'&&typeof String[action.params.type]!=='function'){logger.error("Error: Invalid transform function passed to actions 'params.type' "+"attribute in element '".concat(element.id,"'. Must be withing 'String.prototype'!"));return subject;}if(typeof String.prototype[action.params.type]==='function'){return String.prototype[action.params.type].apply(subject,args);}return String[action.params.type](subject);}case'boolean':{if(typeof Boolean.prototype[action.params.type]!=='function'&&typeof Boolean[action.params.type]!=='function'){logger.error("Error: Invalid transform function passed to actions 'params.type' "+"attribute in element '".concat(element.id,"'. Must be withing 'String.prototype'!"));return subject;}if(typeof Boolean.prototype[action.params.type]==='function'){return Boolean.prototype[action.params.type].apply(subject,args);}return Boolean[action.params.type](subject);}case'number':{if(typeof Number.prototype[action.params.type]!=='function'&&typeof Number[action.params.type]!=='function'){logger.error("Error: Invalid transform function passed to actions 'params.type' "+"attribute in element '".concat(element.id,"'. Must be withing 'String.prototype'!"));return subject;}if(typeof Number.prototype[action.params.type]==='function'){return Number.prototype[action.params.type].apply(subject,args);}return Number[action.params.type](subject);}default:logger.error("Error: The given data can not be transformed. Must be of type 'string', "+"'boolean' or 'number'");return subject;}};var newState=_extends({},nextState,{formData:_extends({},nextState.formData,_defineProperty({},element.id,transform(nextState.formData[element.id])))});// Notify follow up listeners about the current change
65
- if(nextState.formData[element.id]!==newState.formData[element.id]){newState=_this.notify(element.id,prevState,newState);}return newState;};});/**
66
- * Evaluates all action rules of a given element action
67
- *
68
- * @param {FormElement} element The element of which the action rules should be evaluated
69
- * @param {FormFieldAction} action The current action to be evaluate rules for
70
- * @param {Object} nextState The state at the time before the "action" event finished
71
- * @returns {boolean}
72
- */_defineProperty(this,"evaluateRules",function(element,action,nextState){var concatRules=_this.createConcatMethod(action.ruleConcatMethod);var resultInitValue=action.ruleConcatMethod!==ACTION_RULES_CONCAT_METHOD_ANY;var result=resultInitValue;action.rules.forEach(function(rule){var tmpResult=resultInitValue;var ruleType=rule.type;var ruleData=rule.data;// Default to rule type "boolean" and data true when type not given
73
- if(ruleType===undefined){ruleType=ACTION_RULE_TYPE_BOOLEAN;ruleData=true;}// Check rule validity
74
- if(!ACTION_RULE_DATA_TYPES[ruleType]){logger.error("Error: Unknown action rule type '".concat(ruleType,"'in element '").concat(element.id,"'"));return;}// Check type of ruleData
75
- var ruleDataType=ACTION_RULE_DATA_TYPES[ruleType];if(ruleDataType==='array'&&!Array.isArray(ruleData)){logger.error("Error: Invalid FormBuilder action rule in element '".concat(element.id,"': ")+"data must be an 'array' for rule type '".concat(ruleType,"'"));return;}// eslint-disable-next-line valid-typeof
76
- if(ruleDataType!=='array'&&_typeof(ruleData)!==ruleDataType){logger.error("Error: Invalid FormBuilder action rule in element '".concat(element.id,"': ")+"data must be '".concat(ruleDataType,"' for rule type '").concat(ruleType,"'"));return;}switch(ruleType){case ACTION_RULE_TYPE_ONE_OF:{tmpResult=ruleData.includes(nextState.formData[rule.context]);break;}case ACTION_RULE_TYPE_NOT_IN:{tmpResult=!ruleData.includes(nextState.formData[rule.context]);break;}case ACTION_RULE_TYPE_BOOLEAN:{tmpResult=ruleData;break;}case ACTION_RULE_TYPE_REGEX:{var regexParts=ruleData.split('/');var regexPattern='';var regexParam='';if(regexParts.length===1){var _regexParts=_slicedToArray(regexParts,1);regexPattern=_regexParts[0];}else if(regexParts.length===3){regexParts.shift();var _regexParts2=_slicedToArray(regexParts,2);regexPattern=_regexParts2[0];var _regexParts2$=_regexParts2[1];regexParam=_regexParts2$===void 0?'':_regexParts2$;}else{logger.error("Error: Invalid regex string in action rule in element ".concat(element.id));break;}var regex=new RegExp(regexPattern,regexParam);tmpResult=regex.test(nextState.formData[rule.context]);break;}default:break;}// Concat rules based on the rule concat method of the action
77
- result=concatRules(result,tmpResult);});return result;});/**
78
- * Creates a concat function that defines how to concatenate action rule results
79
- *
80
- * @param {string} method The method defined by the action
81
- * @returns {Function}
82
- */_defineProperty(this,"createConcatMethod",function(method){return function(prev,next){switch(method){case ACTION_RULES_CONCAT_METHOD_NONE:return prev&&!next;case ACTION_RULES_CONCAT_METHOD_ANY:return prev||next;case ACTION_RULES_CONCAT_METHOD_ALL:default:return prev&&next;}};});/**
83
- * Adds a "action" listener to a given context element
84
- *
85
- * @param {string} elementId the element to listen for
86
- * @param {Function} handler The listener to call when something has changed
87
- */_defineProperty(this,"register",function(elementId,handler){if(!_this.actionListeners[elementId]){_this.actionListeners[elementId]=[];}_this.actionListeners[elementId].push(handler);});/**
88
- * Takes an element id, the state to work with and optional data and notifies all "action"
89
- * listeners about the change. Every listener can manipulate the state.
90
- * Returns the new state.
91
- *
92
- * @param {string} elementId The id of the element that was changed
93
- * @param {Object} prevState The state before any changes took place
94
- * @param {Object} nextState The state containing all updates before the listeners are executed
95
- * @returns {Object} The new state after all handlers have been executed.
96
- */_defineProperty(this,"notify",function(elementId,prevState,nextState){var newState=nextState;if(_this.actionListeners[elementId]){_this.actionListeners[elementId].forEach(function(notifyListener){// Note: The order of state changes is applied in the same order of listener registration
97
- newState=notifyListener(prevState,newState);});}return newState;});this.defaults=defaults;this.getProvincesList=getProvincesList;this.actionListeners={};});export default ActionListener;
13
+ */
14
+ constructor(getProvincesList, defaults) {
15
+ /**
16
+ * Takes the elements to be rendered by the FormBuilder and attaches available action listeners
17
+ * to the component.
18
+ * @param {FormElement[]} elementList List of all elements
19
+ */
20
+ this.attachAll = elementList => {
21
+ // Attach action listeners for element (context) actions
22
+ elementList.forEach(element => {
23
+ let elementActions = element.actions;
24
+ if (element.type === ELEMENT_TYPE_PROVINCE) {
25
+ elementActions = elementActions || [];
26
+
27
+ // Requires a country element to create a "update provinces" action
28
+ const countryElement = elementList.find(el => el.type === ELEMENT_TYPE_COUNTRY);
29
+ if (countryElement) {
30
+ // Attach new action, which is always triggered, when the (only) country element changes
31
+ elementActions.push({
32
+ type: ACTION_TYPE_UPDATE_PROVINCE_ELEMENT,
33
+ rules: [{
34
+ context: countryElement.id
35
+ }]
36
+ });
37
+ }
38
+ }
39
+ if (elementActions === undefined) {
40
+ return;
41
+ }
42
+
43
+ // Create listeners for all supported actions
44
+ elementActions.forEach(action => {
45
+ const actionRules = action.rules || [];
46
+ // Always apply action to itself if no rules given
47
+ if (actionRules.length === 0) {
48
+ // Define a basic rule if no rules given
49
+ actionRules.push({
50
+ context: element.id
51
+ });
52
+ }
53
+
54
+ // Actions do have a fixed structure which needs to be fulfilled
55
+ const normalizedAction = {
56
+ ...action,
57
+ rules: actionRules
58
+ };
59
+
60
+ // Assign the action listeners to all contexts of the current element
61
+ actionRules.forEach(rule => {
62
+ this.attach(element, normalizedAction, rule);
63
+ });
64
+ });
65
+ });
66
+ };
67
+ /**
68
+ * Attaches one or possibly multiple action listeners for the given rule
69
+ * @param {FormElement} element The current element that is modified by the action
70
+ * @param {FormFieldAction} action The action and it's params
71
+ * @param {FormFieldActionRule} rule The rule to check in case the action listener is triggered
72
+ */
73
+ this.attach = (element, action, rule) => {
74
+ let actionListener;
75
+ switch (action.type) {
76
+ case ACTION_TYPE_UPDATE_PROVINCE_ELEMENT:
77
+ {
78
+ actionListener = this.createUpdateProvinceElementHandler(element, action);
79
+ break;
80
+ }
81
+ case ACTION_TYPE_SET_VISIBILITY:
82
+ {
83
+ // Visibility is special and uses the result of the evaluation itself
84
+ actionListener = this.createSetVisibilityHandler(element, action);
85
+ break;
86
+ }
87
+ case ACTION_TYPE_SET_VALUE:
88
+ {
89
+ actionListener = this.createEvaluatedHandler(element, action, this.createSetValueHandler(element, action));
90
+ break;
91
+ }
92
+ case ACTION_TYPE_TRANSFORM:
93
+ {
94
+ actionListener = this.createEvaluatedHandler(element, action, this.createTransformHandler(element, action));
95
+ break;
96
+ }
97
+ default:
98
+ return;
99
+ }
100
+ this.register(rule.context, actionListener);
101
+ };
102
+ /**
103
+ * Action listener creator to check all related rules before calling any further action listeners
104
+ * @param {FormElement} element The element for which the listener should be created for
105
+ * @param {FormFieldAction} action The action to be create a listener for
106
+ * @param {Function} actionListener The action listener to call if the rule applies
107
+ * @returns {Function} Returns a function to modify and return the modified state.
108
+ */
109
+ this.createEvaluatedHandler = (element, action, actionListener) => (prevState, nextState) => {
110
+ // Apply rules before accepting any changes
111
+ if (!this.evaluateRules(element, action, nextState)) {
112
+ return nextState;
113
+ }
114
+ return actionListener(prevState, nextState);
115
+ };
116
+ /**
117
+ * Action listener creator to handle "updateCountryChange" action
118
+ * @param {FormElement} provinceEl The element for which the listener should be created for
119
+ * @param {FormFieldAction} action The action to be create a listener for
120
+ * @returns {Function} Returns a function to modify and return the modified state.
121
+ */
122
+ this.createUpdateProvinceElementHandler = (provinceEl, action) => (prevState, nextState) => {
123
+ const countryElementId = action.rules[0].context;
124
+ const countryValue = nextState.formData[countryElementId];
125
+ const countryDefault = this.defaults[countryElementId];
126
+ const newState = {
127
+ ...nextState
128
+ };
129
+
130
+ // Overwrite province with the form's default, if country matches the default as well
131
+ if (countryValue === countryDefault) {
132
+ newState.formData[provinceEl.id] = this.defaults[provinceEl.id];
133
+ } else {
134
+ // Update province to first or no selection, based on "required" attribute
135
+ newState.formData[provinceEl.id] = !provinceEl.required ? '' : Object.keys(this.getProvincesList(countryValue))[0];
136
+ }
137
+ return newState;
138
+ };
139
+ /**
140
+ * Action listener creator to handle "setVisibility" actions
141
+ * @param {FormElement} element The element for which the listener should be created for
142
+ * @param {FormFieldAction} action The action to be create a listener for
143
+ * @returns {Function} Returns a function to modify and return the modified state.
144
+ */
145
+ this.createSetVisibilityHandler = (element, action) => (prevState, nextState) => {
146
+ let newState = {
147
+ ...nextState,
148
+ elementVisibility: {
149
+ ...nextState.elementVisibility,
150
+ [element.id]: this.evaluateRules(element, action, nextState)
151
+ },
152
+ // Copy form data to be able to check changes and all follow up actions
153
+ formData: {
154
+ ...nextState.formData
155
+ }
156
+ };
157
+ if (newState.formData[element.id] === undefined && newState.elementVisibility[element.id]) {
158
+ newState.formData[element.id] = this.defaults[element.id];
159
+ } else if (!newState.elementVisibility[element.id] && newState.formData[element.id] !== undefined) {
160
+ delete newState.formData[element.id];
161
+ }
162
+
163
+ // Notify follow up listeners about the current change
164
+ if (nextState.formData[element.id] !== newState.formData[element.id]) {
165
+ newState = this.notify(element.id, prevState, newState);
166
+ }
167
+ return newState;
168
+ };
169
+ /**
170
+ * Action listener creator to handle "setValue" actions
171
+ * @param {FormElement} element The element for which the listener should be created for
172
+ * @param {FormFieldAction} action The action to be create a listener for
173
+ * @returns {Function} Returns the modified state.
174
+ */
175
+ this.createSetValueHandler = (element, action) => (prevState, nextState) => {
176
+ if (typeof action.params !== 'object' || Array.isArray(action.params)) {
177
+ logger.error(`Error: Invalid or missing form action in element '${element.id}'. ` + 'Params must be in the format: { "type": string, "value": string }');
178
+ return nextState;
179
+ }
180
+ let {
181
+ value
182
+ } = action.params;
183
+
184
+ // Check correctness of value data type
185
+ switch (typeof value) {
186
+ case 'boolean':
187
+ if (element.type !== ELEMENT_TYPE_CHECKBOX) {
188
+ logger.error(`Error: Invalid form action param in element '${element.id}'. ` + `Allowed '${ELEMENT_TYPE_CHECKBOX}' data type for 'params.value' is: 'boolean'`);
189
+ return nextState;
190
+ }
191
+ break;
192
+ case 'number':
193
+ if (element.type !== ELEMENT_TYPE_NUMBER) {
194
+ logger.error(`Error: Invalid form action param in element '${element.id}'. ` + `Allowed '${ELEMENT_TYPE_NUMBER}' data types for 'params.value' are: ` + "'number' and 'string'");
195
+ return nextState;
196
+ }
197
+ break;
198
+ case 'string':
199
+ if (element.type === ELEMENT_TYPE_CHECKBOX) {
200
+ logger.error(`Error: Invalid form action param in element '${element.id}'. ` + `Allowed '${ELEMENT_TYPE_CHECKBOX}' data type for 'params.value' is: 'boolean'`);
201
+ return nextState;
202
+ }
203
+ break;
204
+ default:
205
+ logger.error(`Error: Invalid form action param in element '${element.id}'. ` + `Can not use '${typeof value}' data for elements of type '${element.type}'`);
206
+ return nextState;
207
+ }
208
+
209
+ // Perform action based on "setValue" type, defined in params
210
+ switch (action.params.type) {
211
+ case ACTION_SET_VALUE_LENGTH_OF:
212
+ value = `${nextState.formData[action.params.value].length}`;
213
+ break;
214
+ case ACTION_SET_VALUE_COPY_FROM:
215
+ value = nextState.formData[action.params.value];
216
+ break;
217
+ case undefined:
218
+ case ACTION_SET_VALUE_FIXED:
219
+ break;
220
+ default:
221
+ logger.error(`Error: Invalid form action param 'type' in element '${element.id}'. ` + `Allowed param types are: '${ACTION_SET_VALUE_LENGTH_OF}', ` + `'${ACTION_SET_VALUE_COPY_FROM}', '${ACTION_SET_VALUE_FIXED}'`);
222
+ return nextState;
223
+ }
224
+ let newState = {
225
+ ...nextState,
226
+ formData: {
227
+ ...nextState.formData,
228
+ [element.id]: value
229
+ }
230
+ };
231
+
232
+ // Notify follow up listeners about the current change, if there are any changes
233
+ if (nextState.formData[element.id] !== value) {
234
+ newState = this.notify(element.id, prevState, newState);
235
+ }
236
+ return newState;
237
+ };
238
+ /**
239
+ * Action listener creator to handle "transform" actions
240
+ * @param {FormElement} element The element for which the listener should be created for
241
+ * @param {FormFieldAction} action The action to be create a listener for
242
+ * @returns {Function} Returns a function to modify and return the modified state.
243
+ */
244
+ this.createTransformHandler = (element, action) => (prevState, nextState) => {
245
+ /**
246
+ * Takes a string and applies a case function on it
247
+ * @param {string|boolean|number} subject The subject to be transformed
248
+ * @returns {string|boolean|number}
249
+ */
250
+ const transform = subject => {
251
+ // Get optional params to be applied in the transformation process
252
+ let args = action.params.value || [];
253
+ if (Array.isArray(action.params.value)) {
254
+ args = action.params.value;
255
+ }
256
+ switch (typeof subject) {
257
+ case 'string':
258
+ {
259
+ if (typeof String.prototype[action.params.type] !== 'function' && typeof String[action.params.type] !== 'function') {
260
+ logger.error("Error: Invalid transform function passed to actions 'params.type' " + `attribute in element '${element.id}'. Must be withing 'String.prototype'!`);
261
+ return subject;
262
+ }
263
+ if (typeof String.prototype[action.params.type] === 'function') {
264
+ return String.prototype[action.params.type].apply(subject, args);
265
+ }
266
+ return String[action.params.type](subject);
267
+ }
268
+ case 'boolean':
269
+ {
270
+ if (typeof Boolean.prototype[action.params.type] !== 'function' && typeof Boolean[action.params.type] !== 'function') {
271
+ logger.error("Error: Invalid transform function passed to actions 'params.type' " + `attribute in element '${element.id}'. Must be withing 'String.prototype'!`);
272
+ return subject;
273
+ }
274
+ if (typeof Boolean.prototype[action.params.type] === 'function') {
275
+ return Boolean.prototype[action.params.type].apply(subject, args);
276
+ }
277
+ return Boolean[action.params.type](subject);
278
+ }
279
+ case 'number':
280
+ {
281
+ if (typeof Number.prototype[action.params.type] !== 'function' && typeof Number[action.params.type] !== 'function') {
282
+ logger.error("Error: Invalid transform function passed to actions 'params.type' " + `attribute in element '${element.id}'. Must be withing 'String.prototype'!`);
283
+ return subject;
284
+ }
285
+ if (typeof Number.prototype[action.params.type] === 'function') {
286
+ return Number.prototype[action.params.type].apply(subject, args);
287
+ }
288
+ return Number[action.params.type](subject);
289
+ }
290
+ default:
291
+ logger.error("Error: The given data can not be transformed. Must be of type 'string', " + "'boolean' or 'number'");
292
+ return subject;
293
+ }
294
+ };
295
+ let newState = {
296
+ ...nextState,
297
+ formData: {
298
+ ...nextState.formData,
299
+ [element.id]: transform(nextState.formData[element.id])
300
+ }
301
+ };
302
+
303
+ // Notify follow up listeners about the current change
304
+ if (nextState.formData[element.id] !== newState.formData[element.id]) {
305
+ newState = this.notify(element.id, prevState, newState);
306
+ }
307
+ return newState;
308
+ };
309
+ /**
310
+ * Evaluates all action rules of a given element action
311
+ *
312
+ * @param {FormElement} element The element of which the action rules should be evaluated
313
+ * @param {FormFieldAction} action The current action to be evaluate rules for
314
+ * @param {Object} nextState The state at the time before the "action" event finished
315
+ * @returns {boolean}
316
+ */
317
+ this.evaluateRules = (element, action, nextState) => {
318
+ const concatRules = this.createConcatMethod(action.ruleConcatMethod);
319
+ const resultInitValue = action.ruleConcatMethod !== ACTION_RULES_CONCAT_METHOD_ANY;
320
+ let result = resultInitValue;
321
+ action.rules.forEach(rule => {
322
+ let tmpResult = resultInitValue;
323
+ let ruleType = rule.type;
324
+ let ruleData = rule.data;
325
+
326
+ // Default to rule type "boolean" and data true when type not given
327
+ if (ruleType === undefined) {
328
+ ruleType = ACTION_RULE_TYPE_BOOLEAN;
329
+ ruleData = true;
330
+ }
331
+
332
+ // Check rule validity
333
+ if (!ACTION_RULE_DATA_TYPES[ruleType]) {
334
+ logger.error(`Error: Unknown action rule type '${ruleType}'in element '${element.id}'`);
335
+ return;
336
+ }
337
+ // Check type of ruleData
338
+ const ruleDataType = ACTION_RULE_DATA_TYPES[ruleType];
339
+ if (ruleDataType === 'array' && !Array.isArray(ruleData)) {
340
+ logger.error(`Error: Invalid FormBuilder action rule in element '${element.id}': ` + `data must be an 'array' for rule type '${ruleType}'`);
341
+ return;
342
+ }
343
+ // eslint-disable-next-line valid-typeof
344
+ if (ruleDataType !== 'array' && typeof ruleData !== ruleDataType) {
345
+ logger.error(`Error: Invalid FormBuilder action rule in element '${element.id}': ` + `data must be '${ruleDataType}' for rule type '${ruleType}'`);
346
+ return;
347
+ }
348
+ switch (ruleType) {
349
+ case ACTION_RULE_TYPE_ONE_OF:
350
+ {
351
+ tmpResult = ruleData.includes(nextState.formData[rule.context]);
352
+ break;
353
+ }
354
+ case ACTION_RULE_TYPE_NOT_IN:
355
+ {
356
+ tmpResult = !ruleData.includes(nextState.formData[rule.context]);
357
+ break;
358
+ }
359
+ case ACTION_RULE_TYPE_BOOLEAN:
360
+ {
361
+ tmpResult = ruleData;
362
+ break;
363
+ }
364
+ case ACTION_RULE_TYPE_REGEX:
365
+ {
366
+ const regexParts = ruleData.split('/');
367
+ let regexPattern = '';
368
+ let regexParam = '';
369
+ if (regexParts.length === 1) {
370
+ [regexPattern] = regexParts;
371
+ } else if (regexParts.length === 3) {
372
+ regexParts.shift();
373
+ [regexPattern, regexParam = ''] = regexParts;
374
+ } else {
375
+ logger.error(`Error: Invalid regex string in action rule in element ${element.id}`);
376
+ break;
377
+ }
378
+ const regex = new RegExp(regexPattern, regexParam);
379
+ tmpResult = regex.test(nextState.formData[rule.context]);
380
+ break;
381
+ }
382
+ default:
383
+ break;
384
+ }
385
+
386
+ // Concat rules based on the rule concat method of the action
387
+ result = concatRules(result, tmpResult);
388
+ });
389
+ return result;
390
+ };
391
+ /**
392
+ * Creates a concat function that defines how to concatenate action rule results
393
+ *
394
+ * @param {string} method The method defined by the action
395
+ * @returns {Function}
396
+ */
397
+ this.createConcatMethod = method => (prev, next) => {
398
+ switch (method) {
399
+ case ACTION_RULES_CONCAT_METHOD_NONE:
400
+ return prev && !next;
401
+ case ACTION_RULES_CONCAT_METHOD_ANY:
402
+ return prev || next;
403
+ case ACTION_RULES_CONCAT_METHOD_ALL:
404
+ default:
405
+ return prev && next;
406
+ }
407
+ };
408
+ /**
409
+ * Adds a "action" listener to a given context element
410
+ *
411
+ * @param {string} elementId the element to listen for
412
+ * @param {Function} handler The listener to call when something has changed
413
+ */
414
+ this.register = (elementId, handler) => {
415
+ if (!this.actionListeners[elementId]) {
416
+ this.actionListeners[elementId] = [];
417
+ }
418
+ this.actionListeners[elementId].push(handler);
419
+ };
420
+ /**
421
+ * Takes an element id, the state to work with and optional data and notifies all "action"
422
+ * listeners about the change. Every listener can manipulate the state.
423
+ * Returns the new state.
424
+ *
425
+ * @param {string} elementId The id of the element that was changed
426
+ * @param {Object} prevState The state before any changes took place
427
+ * @param {Object} nextState The state containing all updates before the listeners are executed
428
+ * @returns {Object} The new state after all handlers have been executed.
429
+ */
430
+ this.notify = (elementId, prevState, nextState) => {
431
+ let newState = nextState;
432
+ if (this.actionListeners[elementId]) {
433
+ this.actionListeners[elementId].forEach(notifyListener => {
434
+ // Note: The order of state changes is applied in the same order of listener registration
435
+ newState = notifyListener(prevState, newState);
436
+ });
437
+ }
438
+ return newState;
439
+ };
440
+ this.defaults = defaults;
441
+ this.getProvincesList = getProvincesList;
442
+ this.actionListeners = {};
443
+ }
444
+ }
445
+ export default ActionListener;