aloha-vue 2.66.0 → 2.66.2

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 (432) hide show
  1. package/CHANGELOG.md +1098 -1090
  2. package/dist/aloha-vue.es.js +15671 -15507
  3. package/dist/aloha-vue.umd.js +68 -68
  4. package/package.json +99 -99
  5. package/scss/_base.scss +62 -62
  6. package/scss/aloha-vue.scss +68 -68
  7. package/scss/components/AFilters.scss +304 -304
  8. package/scss/components/AFormElement/AValidatedJson.scss +6 -6
  9. package/scss/components/AMenu.scss +627 -627
  10. package/scss/components/AModal.scss +44 -44
  11. package/scss/components/APagination.scss +167 -167
  12. package/scss/components/ARate.scss +78 -78
  13. package/scss/components/AResizer.scss +63 -63
  14. package/scss/components/ATable.scss +819 -819
  15. package/scss/components/ATableForm.scss +307 -307
  16. package/scss/components/AVerticalScroll.scss +47 -47
  17. package/scss/components/AWizard.scss +669 -669
  18. package/scss/components/ui/ADatepicker.scss +342 -342
  19. package/scss/components/ui/ADatepickerRange.scss +45 -45
  20. package/scss/components/ui/AFieldset.scss +78 -78
  21. package/scss/components/ui/AInputNumber.scss +62 -62
  22. package/scss/components/ui/AInputNumberRange.scss +30 -30
  23. package/scss/components/ui/ASelect.scss +236 -236
  24. package/scss/components/ui/ASlider.scss +186 -186
  25. package/scss/components/ui/ASwitch.scss +148 -148
  26. package/scss/components/ui/ui.scss +254 -254
  27. package/scss/text/text_alignment.scss +39 -39
  28. package/scss/text/text_transform.scss +51 -51
  29. package/scss/text/text_wrapping.scss +40 -40
  30. package/scss/utils/badge.scss +45 -45
  31. package/scss/utils/checkbox_radio.scss +134 -134
  32. package/scss/utils/color.scss +46 -46
  33. package/scss/utils/dropdown.scss +185 -185
  34. package/scss/utils/list.scss +75 -75
  35. package/scss/utils/modal.scss +173 -173
  36. package/scss/utils/sizing.scss +137 -137
  37. package/scss/utils/spacing.scss +63 -63
  38. package/scss/utils/tooltip.scss +63 -63
  39. package/src/AAccordion/AAccordion.js +206 -206
  40. package/src/AAccordion/compositionAPI/IndexesForOpenAPI.js +63 -63
  41. package/src/AAccordion/compositionAPI/ToggleAPI.js +85 -85
  42. package/src/AAlert/AAlert.js +216 -216
  43. package/src/AAlert/compositionAPI/ClassAPI.js +21 -21
  44. package/src/AAlert/i18n/AAlertI18n.js +19 -19
  45. package/src/AAlert/i18n/ar.json +2 -2
  46. package/src/AAlert/i18n/de.json +2 -2
  47. package/src/AAlert/i18n/en.json +2 -2
  48. package/src/AAlert/i18n/es.json +2 -2
  49. package/src/AAlert/i18n/fr.json +2 -2
  50. package/src/AAlert/i18n/hr.json +2 -2
  51. package/src/AAlert/i18n/it.json +2 -2
  52. package/src/AAlert/i18n/ru.json +2 -2
  53. package/src/AButton/AButton.js +275 -275
  54. package/src/ACarousel/ACarousel.js +361 -361
  55. package/src/ACarousel/ACarouselBtn/ACarouselBtn.js +75 -75
  56. package/src/ACarousel/ACarouselBtn/compositionAPI/ClassAPI.js +16 -16
  57. package/src/ACarousel/ACarouselBtn/compositionAPI/TextAPI.js +25 -25
  58. package/src/ACarousel/ACarouselControls/ACarouselControls.js +114 -114
  59. package/src/ACarousel/ACarouselControls/ACarouselControlsIndicator/ACarouselControlsIndicator.js +146 -146
  60. package/src/ACarousel/ACarouselControls/ACarouselControlsIndicator/compositionAPI/ActiveAPI.js +33 -33
  61. package/src/ACarousel/ACarouselControls/ACarouselControlsIndicator/compositionAPI/AttributesAPI.js +40 -40
  62. package/src/ACarousel/ACarouselControls/ACarouselControlsIndicator/compositionAPI/EventsAPI.js +25 -25
  63. package/src/ACarousel/ACarouselControls/ACarouselControlsIndicator/compositionAPI/IconAPI.js +20 -20
  64. package/src/ACarousel/ACarouselControls/compositionAPI/AriaLabelAPI.js +20 -20
  65. package/src/ACarousel/ACarouselItem/ACarouselItem.js +83 -83
  66. package/src/ACarousel/ACarouselItem/compositionAPI/AttributesAPI.js +39 -39
  67. package/src/ACarousel/ACarouselItem/compositionAPI/IsActiveAPI.js +21 -21
  68. package/src/ACarousel/compositionAPI/ActiveAPI.js +111 -111
  69. package/src/ACarousel/compositionAPI/AriaLabelAPI.js +25 -25
  70. package/src/ACarousel/compositionAPI/ArrowsAPI.js +17 -17
  71. package/src/ACarousel/compositionAPI/ClassAPI.js +44 -44
  72. package/src/ACarousel/compositionAPI/DataAPI.js +41 -41
  73. package/src/ACarousel/compositionAPI/IndicatorsAPI.js +148 -148
  74. package/src/ACarousel/compositionAPI/TextsAPI.js +25 -25
  75. package/src/ACarousel/i18n/ACarouselI18n.js +19 -19
  76. package/src/ACarousel/i18n/ar.json +8 -8
  77. package/src/ACarousel/i18n/de.json +8 -8
  78. package/src/ACarousel/i18n/en.json +8 -8
  79. package/src/ACarousel/i18n/es.json +8 -8
  80. package/src/ACarousel/i18n/fr.json +8 -8
  81. package/src/ACarousel/i18n/hr.json +8 -8
  82. package/src/ACarousel/i18n/it.json +8 -8
  83. package/src/ACarousel/i18n/ru.json +8 -8
  84. package/src/ACollapse/ACollapse.js +103 -103
  85. package/src/ADropdown/ADropdown.js +544 -544
  86. package/src/ADropdown/ADropdownGroup.js +85 -85
  87. package/src/ADropdown/compositionAPI/ActionsAPI.js +147 -147
  88. package/src/ADropdown/compositionAPI/AttributesAPI.js +100 -100
  89. package/src/AElement/AElement.js +518 -518
  90. package/src/AElement/compositionAPI/AttributesAPI.js +51 -51
  91. package/src/AElement/compositionAPI/ClickAPI.js +30 -30
  92. package/src/AElement/compositionAPI/ComponentLocalAPI.js +23 -23
  93. package/src/AElement/compositionAPI/DisabledAPI.js +22 -22
  94. package/src/AElement/compositionAPI/HtmlTitleAPI.js +33 -33
  95. package/src/AElement/compositionAPI/KeydownAPI.js +35 -35
  96. package/src/AElement/compositionAPI/LoadingAPI.js +22 -22
  97. package/src/AElement/compositionAPI/RouterLinkAPI.js +20 -20
  98. package/src/AElement/compositionAPI/SwitchAPI.js +33 -33
  99. package/src/AElement/compositionAPI/TagAPI.js +34 -34
  100. package/src/AElement/compositionAPI/TextAPI.js +78 -78
  101. package/src/AElement/compositionAPI/TitleAPI.js +29 -29
  102. package/src/AFilters/AFilterCenter/AFilterCenter.js +154 -154
  103. package/src/AFilters/AFilterCenter/AFilterCenterItem/AFilterCenterItem.js +207 -207
  104. package/src/AFilters/AFilters/AFilters.js +282 -282
  105. package/src/AFilters/i18n/ar.json +30 -30
  106. package/src/AFilters/i18n/en.json +30 -30
  107. package/src/AFilters/i18n/es.json +30 -30
  108. package/src/AFilters/i18n/fr.json +30 -30
  109. package/src/AFilters/i18n/hr.json +30 -30
  110. package/src/AFilters/i18n/it.json +30 -30
  111. package/src/AFilters/i18n/ru.json +30 -30
  112. package/src/AGroupButtonDropdown/compositionAPI/ActionsAPI.js +143 -143
  113. package/src/ALink/ALink.js +253 -253
  114. package/src/AMenu/AMenu.js +578 -578
  115. package/src/AMenu/AMenuBreadcrumbs/compositionAPI/RenderTruncatedAPI.js +74 -74
  116. package/src/AMenu/AMenuButtonToggle/AMenuButtonToggle.js +94 -94
  117. package/src/AMenu/AMenuButtonToggle/compositionAPI/ToggleAPI.js +95 -95
  118. package/src/AMenu/AMenuPanelLink/AMenuPanelLink.js +250 -250
  119. package/src/AMenu/compositionAPI/BackdropAPI.js +42 -42
  120. package/src/AMenu/compositionAPI/KeydownAPI.js +197 -197
  121. package/src/AMenu/compositionAPI/LinkClickAPI.js +48 -48
  122. package/src/AMenu/compositionAPI/MenuAttributesAPI.js +51 -51
  123. package/src/AMenu/compositionAPI/PanelsAPI.js +78 -78
  124. package/src/AMenu/compositionAPI/ResizeAPI.js +74 -74
  125. package/src/AModal/AModal.js +530 -530
  126. package/src/AModalForm/AModalForm.js +383 -383
  127. package/src/AModalWizard/AModalWizard.js +563 -563
  128. package/src/ANotification/ANotification.js +60 -60
  129. package/src/APagination/APagination.js +111 -111
  130. package/src/APagination/APaginationCountPerPage/APaginationCountPerPage.js +209 -209
  131. package/src/APagination/APaginationCountPerPage/compositionAPI/MainAPI.js +40 -40
  132. package/src/APagination/APaginationCountPerPage/compositionAPI/TextsAPI.js +54 -54
  133. package/src/APagination/APaginationPages/APaginationPages.js +282 -282
  134. package/src/APagination/APaginationPages/compositionAPI/PaginationItemsAPI.js +102 -102
  135. package/src/APagination/APaginationPages/compositionAPI/TextsAPI.js +74 -74
  136. package/src/APagination/compositionAPI/ComponentsAPI.js +79 -79
  137. package/src/APagination/i18n/ar.json +12 -12
  138. package/src/APagination/i18n/es.json +12 -12
  139. package/src/APagination/i18n/fr.json +12 -12
  140. package/src/APagination/i18n/hr.json +12 -12
  141. package/src/APagination/i18n/it.json +12 -12
  142. package/src/APagination/i18n/ru.json +12 -12
  143. package/src/APopup/APopup.js +115 -115
  144. package/src/ATable/ATable.js +1159 -1157
  145. package/src/ATable/ATableHeaderThAction/ATableHeaderThAction.js +241 -241
  146. package/src/ATable/ATableSortingAdditional/__tests__/ATableSortingAdditional.ModelAPI.test.js +200 -200
  147. package/src/ATable/ATableSortingAdditional/compositionAPI/ModelAPI.js +152 -152
  148. package/src/ATable/ATableTd/ATableTd.js +145 -145
  149. package/src/ATable/ATableTdAction/ATableTdAction.js +223 -218
  150. package/src/ATable/ATableTopPanel/ATableTopPanel.js +433 -433
  151. package/src/ATable/ATableTr/ATableTr.js +8 -0
  152. package/src/ATable/ATableTr/compositionAPI/AttributesAPI.js +3 -1
  153. package/src/ATable/__tests__/ATable.RowIdsAPI.test.js +66 -0
  154. package/src/ATable/compositionAPI/ColumnActionAPI.js +105 -105
  155. package/src/ATable/compositionAPI/ColumnStylesAPI.js +50 -50
  156. package/src/ATable/compositionAPI/ColumnsGroupedAPI.js +187 -187
  157. package/src/ATable/compositionAPI/PaginationModesAPI.js +44 -44
  158. package/src/ATable/compositionAPI/PreviewAPI.js +201 -201
  159. package/src/ATable/compositionAPI/PreviewRightResizeAPI.js +135 -135
  160. package/src/ATable/compositionAPI/RowActionsAPI.js +3 -1
  161. package/src/ATable/compositionAPI/ScrollControlAPI.js +249 -249
  162. package/src/ATable/compositionAPI/SortAPI.js +86 -86
  163. package/src/ATable/compositionAPI/WidthAPI.js +73 -73
  164. package/src/ATableForm/ATableForm.js +595 -595
  165. package/src/ATableForm/ATableFormCell/ATableFormCell.js +204 -204
  166. package/src/ATableForm/ATableFormCell/compositionAPI/DisabledAPI.js +23 -23
  167. package/src/ATableForm/ATableFormCell/compositionAPI/ReadonlyAPI.js +31 -31
  168. package/src/ATableForm/ATableFormCellAction/ATableFormCellAction.js +282 -282
  169. package/src/ATableForm/ATableFormCellAction/compositionAPI/DeleteAPI.js +80 -80
  170. package/src/ATableForm/ATableFormCellAction/compositionAPI/DisabledAPI.js +60 -60
  171. package/src/ATableForm/ATableFormCellAction/compositionAPI/HiddenAPI.js +46 -46
  172. package/src/ATableForm/ATableFormCellAction/compositionAPI/IdsAPI.js +31 -31
  173. package/src/ATableForm/ATableFormCellAction/compositionAPI/StylesAPI.js +27 -27
  174. package/src/ATableForm/ATableFormCellAction/compositionAPI/TitleAPI.js +47 -47
  175. package/src/ATableForm/ATableFormCellDnd/compositionAPI/IdAPI.js +21 -21
  176. package/src/ATableForm/ATableFormCellList/ATableFormCellList.js +127 -127
  177. package/src/ATableForm/ATableFormCellList/compositionAPI/DataAPI.js +77 -77
  178. package/src/ATableForm/ATableFormRow/ATableFormRow.js +592 -592
  179. package/src/ATableForm/ATableFormRow/compositionAPI/ErrorsAPI.js +40 -40
  180. package/src/ATableForm/ATableFormRow/compositionAPI/FocusAPI.js +55 -55
  181. package/src/ATableForm/ATableFormRow/compositionAPI/IdAPI.js +19 -19
  182. package/src/ATableForm/__tests__/ATableForm.ListView.test.js +864 -864
  183. package/src/ATableForm/compositionAPI/ClassesAPI.js +23 -23
  184. package/src/ATableForm/compositionAPI/ColumnsGrowAPI.js +180 -180
  185. package/src/ATableForm/compositionAPI/DeleteAPI.js +9 -9
  186. package/src/ATableForm/compositionAPI/EditAPI.js +125 -125
  187. package/src/ATableForm/compositionAPI/RowsAPI.js +42 -42
  188. package/src/ATableForm/compositionAPI/StylesAPI.js +62 -62
  189. package/src/ATableForm/compositionAPI/WidthsAPI.js +20 -20
  190. package/src/ATableForm/i18n/ATableFormI18n.js +19 -19
  191. package/src/ATableForm/utils/getFormElement.js +32 -32
  192. package/src/ATabs/ATabsContent/ATabsContent.js +102 -102
  193. package/src/ATabs/ATabsTab/ATabsTab.js +185 -185
  194. package/src/ATooltip/ATooltip.js +221 -221
  195. package/src/ATranslation/compositionAPI/UtilsAPI.js +187 -187
  196. package/src/AVerticalScroll/compositionAPI/ScrollAPI.js +55 -55
  197. package/src/AWizard/AWizard.js +467 -467
  198. package/src/compositionAPI/AEventOutsideAPI.js +46 -46
  199. package/src/compositionAPI/AFiltersAPI.js +178 -178
  200. package/src/compositionAPI/AMobileAPI.js +32 -32
  201. package/src/compositionAPI/APageTabTitleAPI.js +84 -84
  202. package/src/compositionAPI/ARemPxAPI.js +47 -47
  203. package/src/compositionAPI/FocusByDestroyAPI.js +67 -67
  204. package/src/const/AKeys.js +9 -9
  205. package/src/directives/AOnHooks.js +0 -0
  206. package/src/filters/__tests__/filterValueByCondition.test.js +94 -94
  207. package/src/filters/filterValueByCondition.js +87 -87
  208. package/src/i18n/allLanguages.js +377 -377
  209. package/src/i18n/ar.json +4 -4
  210. package/src/i18n/de.json +4 -4
  211. package/src/i18n/en.json +4 -4
  212. package/src/i18n/es.json +4 -4
  213. package/src/i18n/fr.json +4 -4
  214. package/src/i18n/hr.json +4 -4
  215. package/src/i18n/it.json +4 -4
  216. package/src/i18n/ru.json +4 -4
  217. package/src/index.js +403 -403
  218. package/src/plugins/AAlertPlugin.js +53 -53
  219. package/src/plugins/ACarouselPlugin.js +34 -34
  220. package/src/plugins/ADatepickerPlugin.js +57 -57
  221. package/src/plugins/AFiltersPlugin.js +102 -102
  222. package/src/plugins/AInputCurrencyPlugin.js +31 -31
  223. package/src/plugins/AMobilePlugin.js +32 -32
  224. package/src/plugins/ARemPxPlugin.js +37 -37
  225. package/src/plugins/ASelectPlugin.js +51 -51
  226. package/src/plugins/ASelectStylesPlugin.js +2376 -2376
  227. package/src/temp/px_to_rem_mapping_1_to_800.md +802 -802
  228. package/src/ui/ACheckbox/ACheckbox.js +929 -929
  229. package/src/ui/ACheckbox/ACheckboxItem/ACheckboxItem.js +0 -0
  230. package/src/ui/ACheckboxRadioGroups/ACheckboxRadioGroups.js +0 -0
  231. package/src/ui/ADatepicker/ADatepicker.js +804 -803
  232. package/src/ui/ADatepicker/ADatepickerCalendarPanel/ADatepickerCalendarPanel.js +796 -796
  233. package/src/ui/ADatepicker/ADatepickerCalendarPanel/compositionAPI/CalendarAPI.js +51 -51
  234. package/src/ui/ADatepicker/compositionAPI/LanguagesAPI.js +92 -92
  235. package/src/ui/ADatepicker/compositionAPI/PlaceholderAPI.js +55 -55
  236. package/src/ui/ADatepicker/i18n/ADatepickerI18n.js +19 -19
  237. package/src/ui/ADatepicker/i18n/ar.json +47 -47
  238. package/src/ui/ADatepicker/i18n/de.json +48 -48
  239. package/src/ui/ADatepicker/i18n/en.json +48 -48
  240. package/src/ui/ADatepicker/i18n/es.json +47 -47
  241. package/src/ui/ADatepicker/i18n/fr.json +47 -47
  242. package/src/ui/ADatepicker/i18n/hr.json +47 -47
  243. package/src/ui/ADatepicker/i18n/it.json +47 -47
  244. package/src/ui/ADatepicker/i18n/ru.json +48 -48
  245. package/src/ui/ADatepicker/panel/APanelDate/APanelDate.js +196 -196
  246. package/src/ui/ADatepicker/panel/APanelDate/compositionAPI/DatesAPI.js +66 -66
  247. package/src/ui/ADatepicker/panel/APanelDate/compositionAPI/FocusAPI.js +96 -96
  248. package/src/ui/ADatepicker/panel/APanelDate/compositionAPI/FocusActiveAPI.js +27 -27
  249. package/src/ui/ADatepicker/panel/APanelDate/compositionAPI/SelectAPI.js +21 -21
  250. package/src/ui/ADatepicker/panel/APanelDate/compositionAPI/TableAPI.js +128 -128
  251. package/src/ui/ADatepicker/panel/APanelMonth/APanelMonth.js +129 -129
  252. package/src/ui/ADatepicker/panel/APanelMonth/compositionAPI/FocusAPI.js +94 -94
  253. package/src/ui/ADatepicker/panel/APanelMonth/compositionAPI/FocusActiveAPI.js +21 -21
  254. package/src/ui/ADatepicker/panel/APanelMonth/compositionAPI/MonthsAPI.js +51 -51
  255. package/src/ui/ADatepicker/panel/APanelMonth/compositionAPI/SelectAPI.js +29 -29
  256. package/src/ui/ADatepicker/panel/APanelYearItem/APanelYearItem.js +75 -75
  257. package/src/ui/ADatepicker/panel/APanelYearItem/compositionAPI/AttributesAPI.js +35 -35
  258. package/src/ui/ADatepicker/panel/APanelYearItem/compositionAPI/SelectAPI.js +35 -35
  259. package/src/ui/ADatepickerAlt/ADatepicker.js +1 -0
  260. package/src/ui/ADatepickerRange/ADatepickerRange.js +528 -525
  261. package/src/ui/AErrors/AErrors.js +149 -149
  262. package/src/ui/AErrors/AErrorsElement/AErrorsElement.js +0 -0
  263. package/src/ui/AErrors/i18n/AErrorsI18n.js +19 -19
  264. package/src/ui/AErrors/i18n/ar.json +3 -3
  265. package/src/ui/AErrors/i18n/de.json +2 -2
  266. package/src/ui/AErrors/i18n/en.json +3 -3
  267. package/src/ui/AErrors/i18n/es.json +3 -3
  268. package/src/ui/AErrors/i18n/fr.json +3 -3
  269. package/src/ui/AErrors/i18n/hr.json +3 -3
  270. package/src/ui/AErrors/i18n/it.json +3 -3
  271. package/src/ui/AErrors/i18n/ru.json +3 -3
  272. package/src/ui/AErrorsText/AErrorsText.js +62 -62
  273. package/src/ui/AFieldset/AFieldset.js +535 -535
  274. package/src/ui/AFieldset/compositionAPI/ModelAPI.js +54 -54
  275. package/src/ui/AForm/AForm.js +252 -252
  276. package/src/ui/AFormElement/AFormElement.js +160 -160
  277. package/src/ui/AFormElementBtnClear/AFormElementBtnClear.js +86 -86
  278. package/src/ui/AFormElementBtnClear/i18n/AFormElementBtnClearI18n.js +19 -19
  279. package/src/ui/AFormElementBtnClear/i18n/ar.json +2 -2
  280. package/src/ui/AFormElementBtnClear/i18n/de.json +2 -2
  281. package/src/ui/AFormElementBtnClear/i18n/en.json +2 -2
  282. package/src/ui/AFormElementBtnClear/i18n/es.json +2 -2
  283. package/src/ui/AFormElementBtnClear/i18n/fr.json +2 -2
  284. package/src/ui/AFormElementBtnClear/i18n/hr.json +2 -2
  285. package/src/ui/AFormElementBtnClear/i18n/it.json +2 -2
  286. package/src/ui/AFormElementBtnClear/i18n/ru.json +2 -2
  287. package/src/ui/AFormHelpText/AFormHelpText.js +37 -37
  288. package/src/ui/AFormLabelDescription/AFormLabelDescription.js +43 -43
  289. package/src/ui/AFormReadonly/AFormReadonly.js +193 -193
  290. package/src/ui/AGroup/AGroup.js +427 -427
  291. package/src/ui/AInput/AInput.js +516 -516
  292. package/src/ui/AInput/compositionAPI/ClassAPI.js +43 -43
  293. package/src/ui/AInputCurrency/AInputCurrency.js +620 -619
  294. package/src/ui/AInputCurrency/compositionAPI/IncreaseDecreaseAPI.js +76 -76
  295. package/src/ui/AInputCurrency/compositionAPI/InputEventsAPI.js +752 -752
  296. package/src/ui/AInputCurrency/compositionAPI/ModelAPI.js +88 -88
  297. package/src/ui/AInputCurrency/compositionAPI/UtilsAPI.js +67 -67
  298. package/src/ui/AInputFile/AInputFile.js +244 -243
  299. package/src/ui/AInputNumber/AInputNumber.js +491 -489
  300. package/src/ui/AInputNumber/compositionAPI/InputEventsAPI.js +196 -196
  301. package/src/ui/AInputNumber/compositionAPI/ModelAPI.js +72 -72
  302. package/src/ui/AInputNumberRange/AInputNumberRange.js +508 -505
  303. package/src/ui/AJson/AJson.js +434 -434
  304. package/src/ui/ALabel/ALabel.js +0 -0
  305. package/src/ui/AMultiselectOrdered/AMultiselectOrdered.js +935 -935
  306. package/src/ui/AOneCheckbox/AOneCheckbox.js +366 -366
  307. package/src/ui/ARadio/ARadio.js +924 -924
  308. package/src/ui/ARadio/ARadioItem/ARadioItem.js +0 -0
  309. package/src/ui/ARequired/ARequired.js +0 -0
  310. package/src/ui/ARouterLinkConfig/ARouterLinkConfig.js +391 -391
  311. package/src/ui/ARouterLinkConfig/compositionAPI/DataFormAPI.js +102 -102
  312. package/src/ui/ARouterLinkConfig/compositionAPI/ModelLocalAPI.js +96 -96
  313. package/src/ui/ARouterLinkConfig/compositionAPI/RouteAPI.js +51 -51
  314. package/src/ui/ASelect/ASelect.js +1210 -1209
  315. package/src/ui/ASelect/ASelectElement/ASelectElement.js +0 -0
  316. package/src/ui/ASelect/ASelectValueCloseable/compositionAPI/CloseAPI.js +28 -28
  317. package/src/ui/ASelect/compositionAPI/ToggleAPI.js +255 -255
  318. package/src/ui/ASelect/i18n/ar.json +6 -6
  319. package/src/ui/ASelect/i18n/de.json +7 -7
  320. package/src/ui/ASelect/i18n/en.json +6 -6
  321. package/src/ui/ASelect/i18n/es.json +6 -6
  322. package/src/ui/ASelect/i18n/fr.json +6 -6
  323. package/src/ui/ASelect/i18n/hr.json +6 -6
  324. package/src/ui/ASelect/i18n/it.json +6 -6
  325. package/src/ui/ASelect/i18n/ru.json +6 -6
  326. package/src/ui/ASelectIcon/ASelectIcon.js +386 -386
  327. package/src/ui/ASelectStyle/ASelectStyle.js +391 -391
  328. package/src/ui/ASelectStyle/compositionAPI/DataAPI.js +68 -68
  329. package/src/ui/ASelectStyle/compositionAPI/EventsAPI.js +24 -24
  330. package/src/ui/ASelectStyle/compositionAPI/KeyLabelCallbackAPI.js +15 -15
  331. package/src/ui/ASelectStyle/compositionAPI/TypeAPI.js +24 -24
  332. package/src/ui/ASelectStyle/i18n/ASelectStyleI18n.js +19 -19
  333. package/src/ui/ASelectStyle/i18n/ar.json +277 -277
  334. package/src/ui/ASelectStyle/i18n/de.json +277 -277
  335. package/src/ui/ASelectStyle/i18n/en.json +277 -277
  336. package/src/ui/ASelectStyle/i18n/es.json +277 -277
  337. package/src/ui/ASelectStyle/i18n/fr.json +277 -277
  338. package/src/ui/ASelectStyle/i18n/hr.json +277 -277
  339. package/src/ui/ASelectStyle/i18n/it.json +277 -277
  340. package/src/ui/ASelectStyle/i18n/ru.json +277 -277
  341. package/src/ui/ASlider/ASlider.js +672 -672
  342. package/src/ui/ASlider/compositionAPI/AriaAttributesAPI.js +121 -121
  343. package/src/ui/ASlider/compositionAPI/AttributesAPI.js +15 -15
  344. package/src/ui/ASlider/compositionAPI/DataAPI.js +115 -115
  345. package/src/ui/ASlider/compositionAPI/DragAndDropAPI.js +198 -198
  346. package/src/ui/ASlider/compositionAPI/LabelAPI.js +13 -13
  347. package/src/ui/ASlider/compositionAPI/MarksAPI.js +32 -32
  348. package/src/ui/ASlider/compositionAPI/SliderAPI.js +289 -289
  349. package/src/ui/ASlider/compositionAPI/StopsAPI.js +47 -47
  350. package/src/ui/ASlider/compositionAPI/StylesAPI.js +79 -79
  351. package/src/ui/ASlider/compositionAPI/TitleAPI.js +42 -42
  352. package/src/ui/ASlider/i18n/ASliderI18n.js +19 -19
  353. package/src/ui/ASlider/i18n/en.json +4 -4
  354. package/src/ui/ASwitch/ASwitch.js +439 -438
  355. package/src/ui/ATemplate/ATemplate.js +0 -0
  356. package/src/ui/ATextarea/ATextarea.js +437 -437
  357. package/src/ui/AUiComponents.js +59 -59
  358. package/src/ui/AUiContainerComponents.js +12 -12
  359. package/src/ui/AValidatedJson/AValidatedJson.js +594 -594
  360. package/src/ui/AValidatedJson/AValidatedJsonItem/compositionAPI/DeleteAPI.js +63 -63
  361. package/src/ui/AValidatedJson/AValidatedJsonItem/compositionAPI/DetailsAPI.js +59 -59
  362. package/src/ui/AValidatedJson/AValidatedJsonItem/compositionAPI/MoveAPI.js +50 -50
  363. package/src/ui/AValidatedJson/AValidatedJsonItem/compositionAPI/UpdateAPI.js +48 -48
  364. package/src/ui/AValidatedJson/AValidatedJsonModalCreateOrUpdate/composiitionAPI/DataFormAPI.js +69 -69
  365. package/src/ui/AValidatedJson/AValidatedJsonModalCreateOrUpdate/composiitionAPI/DisabledAPI.js +35 -35
  366. package/src/ui/AValidatedJson/AValidatedJsonModalCreateOrUpdate/composiitionAPI/ModelAPI.js +31 -31
  367. package/src/ui/AValidatedJson/AValidatedJsonModalCreateOrUpdate/composiitionAPI/SaveAPI.js +115 -115
  368. package/src/ui/AValidatedJson/AValidatedJsonModalCreateOrUpdate/composiitionAPI/TextAPI.js +25 -25
  369. package/src/ui/AValidatedJson/compositionAPI/AValidatedJsonErrorLabelsAPI.js +18 -18
  370. package/src/ui/AValidatedJson/compositionAPI/AttributesAPI.js +15 -15
  371. package/src/ui/AValidatedJson/compositionAPI/ChildrenAPI.js +70 -70
  372. package/src/ui/AValidatedJson/compositionAPI/EventsAPI.js +19 -19
  373. package/src/ui/AValidatedJson/compositionAPI/JsonModeAPI.js +119 -119
  374. package/src/ui/AValidatedJson/compositionAPI/ListModeAPI.js +144 -144
  375. package/src/ui/AValidatedJson/compositionAPI/ModelAPI.js +38 -38
  376. package/src/ui/AValidatedJson/compositionAPI/SingleModeAPI.js +112 -112
  377. package/src/ui/AValidatedJson/compositionAPI/TranslateAPI.js +22 -22
  378. package/src/ui/AValidatedJson/i18n/AValidatedJsonI18n.js +19 -19
  379. package/src/ui/AValidatedJson/i18n/ar.json +3 -3
  380. package/src/ui/AValidatedJson/i18n/de.json +22 -22
  381. package/src/ui/AValidatedJson/i18n/en.json +3 -3
  382. package/src/ui/AValidatedJson/i18n/es.json +3 -3
  383. package/src/ui/AValidatedJson/i18n/fr.json +3 -3
  384. package/src/ui/AValidatedJson/i18n/hr.json +3 -3
  385. package/src/ui/AValidatedJson/i18n/it.json +3 -3
  386. package/src/ui/AValidatedJson/i18n/ru.json +6 -6
  387. package/src/ui/compositionApi/UIDataGroupAPI.js +94 -94
  388. package/src/ui/compositionApi/UiAPI.js +185 -185
  389. package/src/ui/compositionApi/UiClearButtonAPI.js +19 -19
  390. package/src/ui/compositionApi/UiDataSortAPI.js +29 -29
  391. package/src/ui/compositionApi/UiDataWithKeyIdAndLabelAPI.js +155 -155
  392. package/src/ui/const/AUiTypes.js +69 -69
  393. package/src/ui/mixins/UiMixinProps.js +129 -129
  394. package/src/ui/utils/utils.js +79 -79
  395. package/src/utils/__tests__/utils.aOrderBy.test.js +237 -237
  396. package/src/utils/__tests__/utils.aSortBy.test.js +331 -331
  397. package/src/utils/__tests__/utilsArray.aFirst.test.js +54 -54
  398. package/src/utils/__tests__/utilsArray.aLast.test.js +54 -54
  399. package/src/utils/__tests__/utilsLang.isArguments.test.js +52 -52
  400. package/src/utils/__tests__/utilsLang.isArray.test.js +50 -50
  401. package/src/utils/__tests__/utilsLang.isArrayBuffer.test.js +48 -48
  402. package/src/utils/__tests__/utilsLang.isBoolean.test.js +56 -56
  403. package/src/utils/__tests__/utilsLang.isBuffer.test.js +47 -47
  404. package/src/utils/__tests__/utilsLang.isDate.test.js +54 -54
  405. package/src/utils/__tests__/utilsLang.isElement.test.js +53 -53
  406. package/src/utils/__tests__/utilsLang.isError.test.js +52 -52
  407. package/src/utils/__tests__/utilsLang.isFinite.test.js +57 -57
  408. package/src/utils/__tests__/utilsLang.isFunction.test.js +46 -46
  409. package/src/utils/__tests__/utilsLang.isInteger.test.js +58 -58
  410. package/src/utils/__tests__/utilsLang.isMap.test.js +50 -50
  411. package/src/utils/__tests__/utilsLang.isNaN.test.js +55 -55
  412. package/src/utils/__tests__/utilsLang.isNil.test.js +57 -57
  413. package/src/utils/__tests__/utilsLang.isNull.test.js +53 -53
  414. package/src/utils/__tests__/utilsLang.isNumber.test.js +54 -54
  415. package/src/utils/__tests__/utilsLang.isObject.test.js +49 -49
  416. package/src/utils/__tests__/utilsLang.isObjectLike.test.js +45 -45
  417. package/src/utils/__tests__/utilsLang.isPlainObject.test.js +60 -60
  418. package/src/utils/__tests__/utilsLang.isPromise.test.js +93 -93
  419. package/src/utils/__tests__/utilsLang.isRegExp.test.js +46 -46
  420. package/src/utils/__tests__/utilsLang.isSet.test.js +50 -50
  421. package/src/utils/__tests__/utilsLang.isString.test.js +50 -50
  422. package/src/utils/__tests__/utilsLang.isSymbol.test.js +45 -45
  423. package/src/utils/__tests__/utilsLang.isUndefined.test.js +57 -57
  424. package/src/utils/__tests__/utilsLang.isWeakMap.test.js +49 -49
  425. package/src/utils/__tests__/utilsLang.isWeakSet.test.js +49 -49
  426. package/src/utils/actions.js +67 -67
  427. package/src/utils/autosize.js +277 -277
  428. package/src/utils/isBrowser.js +12 -12
  429. package/src/utils/utils.js +253 -253
  430. package/src/utils/utilsArray.js +29 -29
  431. package/src/utils/utilsDOM.js +188 -188
  432. package/src/utils/utilsLang.js +346 -346
@@ -1,864 +1,864 @@
1
- import {
2
- computed,
3
- nextTick,
4
- reactive,
5
- ref,
6
- } from "vue";
7
- import {
8
- describe,
9
- expect,
10
- it,
11
- jest,
12
- } from "@jest/globals";
13
- import {
14
- mount,
15
- } from "@vue/test-utils";
16
-
17
- import AForm from "../../ui/AForm/AForm";
18
- import ATableFormCellList from "../ATableFormCellList/ATableFormCellList";
19
-
20
- import CellActionStylesAPI from "../ATableFormCellAction/compositionAPI/StylesAPI";
21
- import CellDisabledAPI from "../ATableFormCell/compositionAPI/DisabledAPI";
22
- import CellReadonlyAPI from "../ATableFormCell/compositionAPI/ReadonlyAPI";
23
- import ColumnsAPI from "../compositionAPI/ColumnsAPI";
24
- import ColumnsGrowAPI from "../compositionAPI/ColumnsGrowAPI";
25
- import DataAPI from "../ATableFormCellList/compositionAPI/DataAPI";
26
- import RowEditAPI from "../ATableFormRow/compositionAPI/EditAPI";
27
- import TableEditAPI from "../compositionAPI/EditAPI";
28
-
29
- import ATableForm from "../ATableForm";
30
- import getFormElement from "../utils/getFormElement";
31
-
32
- jest.mock("../../ui/AForm/AForm", () => {
33
- const {
34
- h,
35
- } = require("vue");
36
-
37
- return {
38
- __esModule: true,
39
- default: {
40
- name: "AForm",
41
- props: {
42
- data: Array,
43
- errors: Object,
44
- idPrefix: String,
45
- modelValue: Object,
46
- readonly: Boolean,
47
- showErrors: Boolean,
48
- showRequiredText: Boolean,
49
- tag: String,
50
- useFlatErrors: Boolean,
51
- useFlatModel: Boolean,
52
- },
53
- emits: [
54
- "change",
55
- ],
56
- render() {
57
- return h(this.tag || "div", {}, this.data.map(item => {
58
- return h("div", {
59
- "data-column-id": item["data-column-id"],
60
- }, [
61
- h("input", {
62
- disabled: this.readonly || item.disabled,
63
- id: `${ this.idPrefix }${ item.id }`,
64
- }),
65
- ]);
66
- }));
67
- },
68
- },
69
- };
70
- });
71
-
72
- jest.mock("../../ui/AFormElement/AFormElement", () => {
73
- const {
74
- h,
75
- } = require("vue");
76
-
77
- return {
78
- __esModule: true,
79
- default: {
80
- name: "AFormElement",
81
- render() {
82
- return h("input");
83
- },
84
- },
85
- };
86
- });
87
-
88
- jest.mock("../../index", () => {
89
- const {
90
- h,
91
- } = require("vue");
92
-
93
- return {
94
- AAlert: {
95
- name: "AAlert",
96
- render() {
97
- return h("div");
98
- },
99
- },
100
- AConfirmAPI: () => ({
101
- closeConfirm: jest.fn(),
102
- openConfirm: jest.fn(),
103
- }),
104
- AErrors: {
105
- name: "AErrors",
106
- render() {
107
- return h("div");
108
- },
109
- },
110
- };
111
- });
112
-
113
- jest.mock("../../AButton/AButton", () => {
114
- const {
115
- h,
116
- } = require("vue");
117
-
118
- return {
119
- __esModule: true,
120
- default: {
121
- name: "AButton",
122
- props: {
123
- disabled: Boolean,
124
- id: String,
125
- },
126
- emits: [
127
- "click",
128
- ],
129
- render() {
130
- return h("button", {
131
- disabled: this.disabled,
132
- id: this.id,
133
- onClick: $event => this.$emit("click", $event),
134
- });
135
- },
136
- },
137
- };
138
- });
139
-
140
- jest.mock("aloha-svg/dist/js/bootstrap/ChevronDown", () => ({
141
- __esModule: true,
142
- default: "<svg></svg>",
143
- }));
144
- jest.mock("aloha-svg/dist/js/bootstrap/ChevronUp", () => ({
145
- __esModule: true,
146
- default: "<svg></svg>",
147
- }));
148
- jest.mock("aloha-svg/dist/js/bootstrap/ExclamationCircleFill", () => ({
149
- __esModule: true,
150
- default: "<svg></svg>",
151
- }));
152
- jest.mock("aloha-svg/dist/js/bootstrap/Floppy2Fill", () => ({
153
- __esModule: true,
154
- default: "<svg></svg>",
155
- }));
156
- jest.mock("aloha-svg/dist/js/bootstrap/GripVertical", () => ({
157
- __esModule: true,
158
- default: "<svg></svg>",
159
- }));
160
- jest.mock("aloha-svg/dist/js/bootstrap/LockFill", () => ({
161
- __esModule: true,
162
- default: "<svg></svg>",
163
- }));
164
- jest.mock("aloha-svg/dist/js/bootstrap/PencilFill", () => ({
165
- __esModule: true,
166
- default: "<svg></svg>",
167
- }));
168
- jest.mock("aloha-svg/dist/js/bootstrap/Plus", () => ({
169
- __esModule: true,
170
- default: "<svg></svg>",
171
- }));
172
- jest.mock("aloha-svg/dist/js/bootstrap/Trash", () => ({
173
- __esModule: true,
174
- default: "<svg></svg>",
175
- }));
176
- jest.mock("aloha-svg/dist/js/bootstrap/XLg", () => ({
177
- __esModule: true,
178
- default: "<svg></svg>",
179
- }));
180
-
181
- describe("ATableForm list view", () => {
182
- it("uses disabled fields for editable rows and readonly fields for non-editable rows", () => {
183
- const props = reactive({
184
- column: {
185
- formElement: {},
186
- },
187
- isEditable: true,
188
- isEditMode: false,
189
- isFooter: false,
190
- });
191
- const {
192
- disabledLocal,
193
- } = CellDisabledAPI(props);
194
- const {
195
- readonlyLocal,
196
- } = CellReadonlyAPI(props);
197
-
198
- expect(disabledLocal.value).toBe(true);
199
- expect(readonlyLocal.value).toBe(false);
200
-
201
- props.isEditable = false;
202
-
203
- expect(disabledLocal.value).toBe(false);
204
- expect(readonlyLocal.value).toBe(true);
205
- });
206
-
207
- it("merges row-specific form element props only in edit mode", () => {
208
- const formElementEditPropsCallback = jest.fn(({ rowData }) => ({
209
- disabled: rowData.locked,
210
- min: rowData.minimum,
211
- readonly: true,
212
- }));
213
- const props = reactive({
214
- column: {
215
- id: "score",
216
- formElement: {
217
- disabled: false,
218
- min: 0,
219
- type: "integer",
220
- },
221
- formElementEditPropsCallback,
222
- },
223
- columnIndex: 1,
224
- isCreateMode: true,
225
- isEditable: true,
226
- isEditMode: false,
227
- isFooter: false,
228
- row: {
229
- id: 1,
230
- locked: true,
231
- minimum: 10,
232
- },
233
- rowData: {
234
- id: 1,
235
- locked: true,
236
- minimum: 20,
237
- },
238
- rowIndex: 2,
239
- rows: [],
240
- });
241
- const formElement = computed(() => getFormElement({
242
- column: props.column,
243
- columnIndex: props.columnIndex,
244
- isCreateMode: props.isCreateMode,
245
- isEditMode: props.isEditMode,
246
- row: props.row,
247
- rowData: props.rowData,
248
- rowIndex: props.rowIndex,
249
- rows: props.rows,
250
- }));
251
- const {
252
- disabledLocal,
253
- } = CellDisabledAPI(props, {
254
- formElement,
255
- });
256
- const {
257
- readonlyLocal,
258
- } = CellReadonlyAPI(props, {
259
- formElement,
260
- });
261
-
262
- expect(formElement.value).toEqual(props.column.formElement);
263
- expect(formElementEditPropsCallback).not.toHaveBeenCalled();
264
-
265
- props.isEditMode = true;
266
-
267
- expect(formElement.value).toEqual(props.column.formElement);
268
- expect(formElementEditPropsCallback).not.toHaveBeenCalled();
269
-
270
- props.isCreateMode = false;
271
-
272
- expect(formElement.value).toEqual({
273
- disabled: true,
274
- min: 20,
275
- readonly: true,
276
- type: "integer",
277
- });
278
- expect(disabledLocal.value).toBe(true);
279
- expect(readonlyLocal.value).toBe(true);
280
- expect(formElementEditPropsCallback).toHaveBeenCalledWith({
281
- column: props.column,
282
- columnIndex: 1,
283
- row: props.row,
284
- rowData: props.rowData,
285
- rowIndex: 2,
286
- rows: props.rows,
287
- });
288
- });
289
-
290
- it.each([
291
- [true, true, 112],
292
- [true, false, 64],
293
- [false, true, 64],
294
- [false, false, 64],
295
- ])("uses the expected action width for editable=%s and deletable=%s", (isEditable, isDeletable, width) => {
296
- const props = reactive({
297
- hasActiveEditRow: false,
298
- isActiveEditMode: false,
299
- isDeletable,
300
- isDeletableConfirm: false,
301
- isEditable,
302
- widths: {
303
- actionsColumnDouble: 112,
304
- actionsColumnSingle: 64,
305
- },
306
- });
307
- const {
308
- columnStyles,
309
- } = CellActionStylesAPI(props);
310
-
311
- expect(columnStyles.value.width).toBe(`${ width }px`);
312
- });
313
-
314
- it("shows the actions column only for edit, delete, or an active add row", () => {
315
- const isAddRowActive = ref(false);
316
- const props = reactive({
317
- columns: [{ id: "name" }],
318
- isDeletable: false,
319
- isDeletableConfirm: false,
320
- isDragAndDrop: false,
321
- isEditable: false,
322
- rowView: "table",
323
- });
324
- const {
325
- allColumnsLength,
326
- hasActionsColumn,
327
- } = ColumnsAPI(props, {
328
- isAddRowActive,
329
- });
330
-
331
- expect(hasActionsColumn.value).toBe(false);
332
- expect(allColumnsLength.value).toBe(1);
333
-
334
- props.isEditable = true;
335
- expect(hasActionsColumn.value).toBe(true);
336
- expect(allColumnsLength.value).toBe(2);
337
-
338
- props.isEditable = false;
339
- props.isDeletableConfirm = true;
340
- expect(hasActionsColumn.value).toBe(true);
341
-
342
- props.isDeletableConfirm = false;
343
- isAddRowActive.value = true;
344
- expect(hasActionsColumn.value).toBe(true);
345
- });
346
-
347
- it("grows all columns equally only when no column has a positive grow value", async() => {
348
- const resizeObserverOriginal = global.ResizeObserver;
349
- global.ResizeObserver = class {
350
- disconnect() {}
351
- observe() {}
352
- unobserve() {}
353
- };
354
-
355
- const wrapperElement = document.createElement("div");
356
- const tableElement = document.createElement("table");
357
- tableElement.id = "table_grow_fallback";
358
- wrapperElement.getBoundingClientRect = () => ({ width: 500 });
359
- wrapperElement.appendChild(tableElement);
360
- document.body.appendChild(wrapperElement);
361
-
362
- const props = reactive({
363
- id: "table_grow_fallback",
364
- isColumnsGrow: true,
365
- isDeletable: false,
366
- isDeletableConfirm: false,
367
- isDragAndDrop: false,
368
- isEditable: true,
369
- });
370
- const columns = ref([
371
- { grow: 0, id: "first", width: "100px" },
372
- { id: "second", width: "100px" },
373
- ]);
374
- const columnsVisible = computed(() => columns.value);
375
- const {
376
- columnsStylesGrow,
377
- destroyColumnsGrowObserver,
378
- initColumnsGrowObserver,
379
- } = ColumnsGrowAPI(props, {
380
- columnsVisible,
381
- hasActionsColumn: computed(() => true),
382
- widthsLocal: computed(() => ({
383
- actionsColumnDouble: 112,
384
- actionsColumnSingle: 64,
385
- dndColumn: 56,
386
- })),
387
- });
388
-
389
- initColumnsGrowObserver();
390
-
391
- expect(columnsStylesGrow.value).toEqual({
392
- first: {
393
- maxWidth: "217px",
394
- minWidth: "217px",
395
- width: "217px",
396
- },
397
- second: {
398
- maxWidth: "217px",
399
- minWidth: "217px",
400
- width: "217px",
401
- },
402
- });
403
-
404
- columns.value = [
405
- { grow: 1, id: "first", width: "100px" },
406
- { grow: 0, id: "second", width: "100px" },
407
- ];
408
- await nextTick();
409
-
410
- expect(columnsStylesGrow.value.first.width).toBe("334px");
411
- expect(columnsStylesGrow.value.second.width).toBe("100px");
412
-
413
- destroyColumnsGrowObserver();
414
- wrapperElement.remove();
415
- global.ResizeObserver = resizeObserverOriginal;
416
- });
417
-
418
- it("allows adding editable data when row editing is disabled", async() => {
419
- const wrapper = mount(ATableForm, {
420
- props: {
421
- addRow: jest.fn(),
422
- columns: [
423
- {
424
- id: "name",
425
- formElement: {
426
- type: "text",
427
- },
428
- },
429
- ],
430
- isAddable: true,
431
- isEditable: false,
432
- rowView: "list",
433
- rows: [],
434
- },
435
- });
436
-
437
- expect(wrapper.find(".a_table_form__cell_actions").exists()).toBe(false);
438
-
439
- await wrapper.find(".a_mt_3 button").trigger("click");
440
-
441
- expect(wrapper.find("tbody button[id$='_cancel']").exists()).toBe(true);
442
- expect(wrapper.find("tbody button[id$='_save']").exists()).toBe(true);
443
- expect(wrapper.findComponent(AForm).props("readonly")).toBe(false);
444
- });
445
-
446
- it("allows DND but not row-click editing when rows are not editable", async() => {
447
- const wrapper = mount(ATableForm, {
448
- props: {
449
- columns: [
450
- {
451
- id: "name",
452
- formElement: {
453
- type: "text",
454
- },
455
- },
456
- ],
457
- isDragAndDrop: true,
458
- isEditable: false,
459
- isEditOnRowClick: true,
460
- rows: [{ name: "Readonly" }],
461
- },
462
- });
463
-
464
- expect(wrapper.find("tbody .a_table_form__reorder_handle").attributes("draggable")).toBe("true");
465
-
466
- await wrapper.find("tbody tr.a_table_form__row").trigger("click");
467
-
468
- expect(wrapper.find("tbody button[id$='_save']").exists()).toBe(false);
469
- });
470
-
471
- it("enters edit mode by row click only when enabled and row edit is available", async() => {
472
- const rows = [
473
- {
474
- id: 1,
475
- name: "Editable",
476
- },
477
- {
478
- id: 2,
479
- name: "Disabled",
480
- },
481
- ];
482
- const wrapper = mount(ATableForm, {
483
- props: {
484
- actionsDisabledCallback: {
485
- edit: ({ row }) => row.id === 2,
486
- },
487
- columns: [
488
- {
489
- id: "name",
490
- label: "Name",
491
- formElement: {
492
- type: "text",
493
- },
494
- },
495
- ],
496
- isEditable: true,
497
- isEditOnRowClick: true,
498
- keyId: "id",
499
- rows,
500
- },
501
- });
502
-
503
- const bodyRows = wrapper.findAll("tbody tr.a_table_form__row");
504
-
505
- await bodyRows[1].trigger("click");
506
- expect(wrapper.find("tbody tr.a_table_form__row_edit_on_click").exists()).toBe(true);
507
-
508
- await bodyRows[0].trigger("click");
509
- expect(wrapper.find("tbody tr.a_table_form__row_edit_on_click").exists()).toBe(false);
510
- expect(wrapper.find("tbody button[id$='_save']").exists()).toBe(true);
511
- });
512
-
513
- it("does not enter edit mode by row click when the prop is disabled", async() => {
514
- const wrapper = mount(ATableForm, {
515
- props: {
516
- columns: [
517
- {
518
- id: "name",
519
- label: "Name",
520
- formElement: {
521
- type: "text",
522
- },
523
- },
524
- ],
525
- isEditable: true,
526
- rows: [
527
- {
528
- name: "Readonly row click",
529
- },
530
- ],
531
- },
532
- });
533
-
534
- await wrapper.find("tbody tr.a_table_form__row").trigger("click");
535
-
536
- expect(wrapper.find("tbody button[id$='_save']").exists()).toBe(false);
537
- });
538
-
539
- it("focuses the clicked column after entering edit mode by row click", async() => {
540
- const wrapper = mount(ATableForm, {
541
- attachTo: document.body,
542
- props: {
543
- columns: [
544
- {
545
- id: "number",
546
- label: "Number",
547
- formElement: {
548
- type: "text",
549
- },
550
- },
551
- {
552
- id: "name",
553
- label: "Name",
554
- formElement: {
555
- type: "text",
556
- },
557
- },
558
- ],
559
- isEditable: true,
560
- isEditOnRowClick: true,
561
- rows: [
562
- {
563
- name: "Marta Ivanova",
564
- number: 1,
565
- },
566
- ],
567
- },
568
- });
569
-
570
- await wrapper.find("tbody [data-column-id='name']").trigger("click");
571
- await wrapper.vm.$nextTick();
572
-
573
- expect(wrapper.find("tbody button[id$='_save']").exists()).toBe(true);
574
- expect(document.activeElement.closest("[data-column-id]").dataset.columnId).toBe("name");
575
-
576
- wrapper.unmount();
577
- });
578
-
579
- it("focuses the clicked form item in list view after entering edit mode by row click", async() => {
580
- const wrapper = mount(ATableForm, {
581
- attachTo: document.body,
582
- props: {
583
- columns: [
584
- {
585
- id: "number",
586
- label: "Number",
587
- formElement: {
588
- type: "text",
589
- },
590
- },
591
- {
592
- id: "name",
593
- label: "Name",
594
- formElement: {
595
- type: "text",
596
- },
597
- },
598
- ],
599
- isEditable: true,
600
- isEditOnRowClick: true,
601
- rowView: "list",
602
- rows: [
603
- {
604
- name: "Marta Ivanova",
605
- number: 1,
606
- },
607
- ],
608
- },
609
- });
610
-
611
- await wrapper.find("tbody [data-column-id='name']").trigger("click");
612
- await wrapper.vm.$nextTick();
613
-
614
- expect(wrapper.find("tbody button[id$='_save']").exists()).toBe(true);
615
- expect(document.activeElement.closest("[data-column-id]").dataset.columnId).toBe("name");
616
-
617
- wrapper.unmount();
618
- });
619
-
620
- it("uses one content column and finds required fields recursively", () => {
621
- const props = reactive({
622
- columns: [
623
- {
624
- id: "fieldset",
625
- formElement: {
626
- children: [
627
- {
628
- id: "requiredChild",
629
- required: true,
630
- type: "text",
631
- },
632
- ],
633
- type: "fieldset",
634
- },
635
- },
636
- {
637
- id: "secondColumn",
638
- formElement: {
639
- type: "text",
640
- },
641
- },
642
- ],
643
- isAddable: false,
644
- isDeletable: true,
645
- isDeletableConfirm: false,
646
- isDragAndDrop: true,
647
- isEditable: true,
648
- rowView: "list",
649
- rows: [],
650
- });
651
- const {
652
- allColumnsLength,
653
- columnsVisible,
654
- hasActionsColumn,
655
- } = ColumnsAPI(props);
656
- const {
657
- hasRequiredEditableColumns,
658
- } = TableEditAPI(props, {
659
- columnsVisible,
660
- getRowKey: jest.fn(),
661
- });
662
-
663
- expect(allColumnsLength.value).toBe(3);
664
- expect(hasRequiredEditableColumns.value).toBe(true);
665
-
666
- props.rowView = "table";
667
- expect(allColumnsLength.value).toBe(4);
668
- expect(hasActionsColumn.value).toBe(true);
669
- });
670
-
671
- it("converts columns and nested fieldsets to AForm data", () => {
672
- const props = reactive({
673
- columns: [
674
- {
675
- id: "limits",
676
- label: "Limits",
677
- formElement: {
678
- type: "fieldset",
679
- children: [
680
- {
681
- id: "negative",
682
- label: "Negative",
683
- type: "integer",
684
- useRowReadonly: true,
685
- },
686
- ],
687
- },
688
- },
689
- ],
690
- isEditable: true,
691
- isEditMode: false,
692
- });
693
- const {
694
- dataForm,
695
- } = DataAPI(props);
696
-
697
- expect(dataForm.value).toEqual([
698
- {
699
- children: [
700
- {
701
- id: "negative",
702
- label: "Negative",
703
- readonly: true,
704
- type: "integer",
705
- useRowReadonly: true,
706
- },
707
- ],
708
- "data-column-id": "limits",
709
- disabled: true,
710
- id: "limits",
711
- label: "Limits",
712
- type: "fieldset",
713
- },
714
- ]);
715
-
716
- props.isEditMode = true;
717
-
718
- expect(dataForm.value[0].disabled).toBeUndefined();
719
- expect(dataForm.value[0].children[0].readonly).toBe(false);
720
- });
721
-
722
- it("applies row-specific form element props in list edit mode", () => {
723
- const props = reactive({
724
- columns: [
725
- {
726
- id: "score",
727
- formElement: {
728
- min: 0,
729
- type: "integer",
730
- },
731
- formElementEditPropsCallback: ({ rowData }) => ({
732
- disabled: rowData.locked,
733
- min: rowData.minimum,
734
- }),
735
- },
736
- ],
737
- isEditable: true,
738
- isEditMode: false,
739
- row: {
740
- locked: true,
741
- minimum: 10,
742
- },
743
- rowData: {
744
- locked: true,
745
- minimum: 20,
746
- },
747
- rowIndex: 0,
748
- rows: [],
749
- });
750
- const {
751
- dataForm,
752
- } = DataAPI(props);
753
-
754
- expect(dataForm.value[0].min).toBe(0);
755
-
756
- props.isEditMode = true;
757
-
758
- expect(dataForm.value[0]).toEqual(expect.objectContaining({
759
- disabled: true,
760
- min: 20,
761
- type: "integer",
762
- }));
763
- });
764
-
765
- it("passes the complete errors object to AForm and emits its full model", async() => {
766
- const errors = {
767
- negative: ["Value is too low"],
768
- };
769
- const wrapper = mount(ATableFormCellList, {
770
- props: {
771
- columns: [
772
- {
773
- id: "limits",
774
- formElement: {
775
- type: "fieldset",
776
- children: [
777
- {
778
- id: "negative",
779
- type: "integer",
780
- },
781
- ],
782
- },
783
- },
784
- ],
785
- errors,
786
- id: "table_0",
787
- isEditable: true,
788
- isEditMode: true,
789
- row: {
790
- negative: 10,
791
- },
792
- rowIndex: 0,
793
- rows: [],
794
- },
795
- });
796
- const form = wrapper.findComponent(AForm);
797
-
798
- expect(form.props("errors")).toEqual(errors);
799
- expect(form.props("showErrors")).toBe(true);
800
- expect(form.props("showRequiredText")).toBe(false);
801
- expect(form.props("useFlatErrors")).toBe(true);
802
-
803
- form.vm.$emit("change", {
804
- fullModel: {
805
- negative: 20,
806
- },
807
- id: "negative",
808
- item: {
809
- id: "negative",
810
- },
811
- model: 20,
812
- });
813
- await wrapper.vm.$nextTick();
814
-
815
- expect(wrapper.emitted("updateRowData")[0][0]).toEqual(expect.objectContaining({
816
- column: wrapper.props("columns")[0],
817
- columnId: "negative",
818
- fullModel: {
819
- negative: 20,
820
- },
821
- model: 20,
822
- }));
823
- });
824
-
825
- it("replaces the complete edit model and clears the changed field error", () => {
826
- const errorsLocal = ref({
827
- negative: ["Value is too low"],
828
- positive: ["Value is too high"],
829
- });
830
- const {
831
- modelLocal,
832
- updateModelLocal,
833
- } = RowEditAPI(reactive({
834
- changeModel: undefined,
835
- onCancelEditRow: jest.fn(),
836
- row: {
837
- negative: 10,
838
- positive: 10,
839
- },
840
- rowIndex: 0,
841
- rows: [],
842
- saveRow: jest.fn(),
843
- }), {
844
- errorsLocal,
845
- });
846
-
847
- updateModelLocal({
848
- columnId: "negative",
849
- fullModel: {
850
- negative: 20,
851
- positive: 10,
852
- },
853
- model: 20,
854
- });
855
-
856
- expect(modelLocal.value).toEqual({
857
- negative: 20,
858
- positive: 10,
859
- });
860
- expect(errorsLocal.value).toEqual({
861
- positive: ["Value is too high"],
862
- });
863
- });
864
- });
1
+ import {
2
+ computed,
3
+ nextTick,
4
+ reactive,
5
+ ref,
6
+ } from "vue";
7
+ import {
8
+ describe,
9
+ expect,
10
+ it,
11
+ jest,
12
+ } from "@jest/globals";
13
+ import {
14
+ mount,
15
+ } from "@vue/test-utils";
16
+
17
+ import AForm from "../../ui/AForm/AForm";
18
+ import ATableFormCellList from "../ATableFormCellList/ATableFormCellList";
19
+
20
+ import CellActionStylesAPI from "../ATableFormCellAction/compositionAPI/StylesAPI";
21
+ import CellDisabledAPI from "../ATableFormCell/compositionAPI/DisabledAPI";
22
+ import CellReadonlyAPI from "../ATableFormCell/compositionAPI/ReadonlyAPI";
23
+ import ColumnsAPI from "../compositionAPI/ColumnsAPI";
24
+ import ColumnsGrowAPI from "../compositionAPI/ColumnsGrowAPI";
25
+ import DataAPI from "../ATableFormCellList/compositionAPI/DataAPI";
26
+ import RowEditAPI from "../ATableFormRow/compositionAPI/EditAPI";
27
+ import TableEditAPI from "../compositionAPI/EditAPI";
28
+
29
+ import ATableForm from "../ATableForm";
30
+ import getFormElement from "../utils/getFormElement";
31
+
32
+ jest.mock("../../ui/AForm/AForm", () => {
33
+ const {
34
+ h,
35
+ } = require("vue");
36
+
37
+ return {
38
+ __esModule: true,
39
+ default: {
40
+ name: "AForm",
41
+ props: {
42
+ data: Array,
43
+ errors: Object,
44
+ idPrefix: String,
45
+ modelValue: Object,
46
+ readonly: Boolean,
47
+ showErrors: Boolean,
48
+ showRequiredText: Boolean,
49
+ tag: String,
50
+ useFlatErrors: Boolean,
51
+ useFlatModel: Boolean,
52
+ },
53
+ emits: [
54
+ "change",
55
+ ],
56
+ render() {
57
+ return h(this.tag || "div", {}, this.data.map(item => {
58
+ return h("div", {
59
+ "data-column-id": item["data-column-id"],
60
+ }, [
61
+ h("input", {
62
+ disabled: this.readonly || item.disabled,
63
+ id: `${ this.idPrefix }${ item.id }`,
64
+ }),
65
+ ]);
66
+ }));
67
+ },
68
+ },
69
+ };
70
+ });
71
+
72
+ jest.mock("../../ui/AFormElement/AFormElement", () => {
73
+ const {
74
+ h,
75
+ } = require("vue");
76
+
77
+ return {
78
+ __esModule: true,
79
+ default: {
80
+ name: "AFormElement",
81
+ render() {
82
+ return h("input");
83
+ },
84
+ },
85
+ };
86
+ });
87
+
88
+ jest.mock("../../index", () => {
89
+ const {
90
+ h,
91
+ } = require("vue");
92
+
93
+ return {
94
+ AAlert: {
95
+ name: "AAlert",
96
+ render() {
97
+ return h("div");
98
+ },
99
+ },
100
+ AConfirmAPI: () => ({
101
+ closeConfirm: jest.fn(),
102
+ openConfirm: jest.fn(),
103
+ }),
104
+ AErrors: {
105
+ name: "AErrors",
106
+ render() {
107
+ return h("div");
108
+ },
109
+ },
110
+ };
111
+ });
112
+
113
+ jest.mock("../../AButton/AButton", () => {
114
+ const {
115
+ h,
116
+ } = require("vue");
117
+
118
+ return {
119
+ __esModule: true,
120
+ default: {
121
+ name: "AButton",
122
+ props: {
123
+ disabled: Boolean,
124
+ id: String,
125
+ },
126
+ emits: [
127
+ "click",
128
+ ],
129
+ render() {
130
+ return h("button", {
131
+ disabled: this.disabled,
132
+ id: this.id,
133
+ onClick: $event => this.$emit("click", $event),
134
+ });
135
+ },
136
+ },
137
+ };
138
+ });
139
+
140
+ jest.mock("aloha-svg/dist/js/bootstrap/ChevronDown", () => ({
141
+ __esModule: true,
142
+ default: "<svg></svg>",
143
+ }));
144
+ jest.mock("aloha-svg/dist/js/bootstrap/ChevronUp", () => ({
145
+ __esModule: true,
146
+ default: "<svg></svg>",
147
+ }));
148
+ jest.mock("aloha-svg/dist/js/bootstrap/ExclamationCircleFill", () => ({
149
+ __esModule: true,
150
+ default: "<svg></svg>",
151
+ }));
152
+ jest.mock("aloha-svg/dist/js/bootstrap/Floppy2Fill", () => ({
153
+ __esModule: true,
154
+ default: "<svg></svg>",
155
+ }));
156
+ jest.mock("aloha-svg/dist/js/bootstrap/GripVertical", () => ({
157
+ __esModule: true,
158
+ default: "<svg></svg>",
159
+ }));
160
+ jest.mock("aloha-svg/dist/js/bootstrap/LockFill", () => ({
161
+ __esModule: true,
162
+ default: "<svg></svg>",
163
+ }));
164
+ jest.mock("aloha-svg/dist/js/bootstrap/PencilFill", () => ({
165
+ __esModule: true,
166
+ default: "<svg></svg>",
167
+ }));
168
+ jest.mock("aloha-svg/dist/js/bootstrap/Plus", () => ({
169
+ __esModule: true,
170
+ default: "<svg></svg>",
171
+ }));
172
+ jest.mock("aloha-svg/dist/js/bootstrap/Trash", () => ({
173
+ __esModule: true,
174
+ default: "<svg></svg>",
175
+ }));
176
+ jest.mock("aloha-svg/dist/js/bootstrap/XLg", () => ({
177
+ __esModule: true,
178
+ default: "<svg></svg>",
179
+ }));
180
+
181
+ describe("ATableForm list view", () => {
182
+ it("uses disabled fields for editable rows and readonly fields for non-editable rows", () => {
183
+ const props = reactive({
184
+ column: {
185
+ formElement: {},
186
+ },
187
+ isEditable: true,
188
+ isEditMode: false,
189
+ isFooter: false,
190
+ });
191
+ const {
192
+ disabledLocal,
193
+ } = CellDisabledAPI(props);
194
+ const {
195
+ readonlyLocal,
196
+ } = CellReadonlyAPI(props);
197
+
198
+ expect(disabledLocal.value).toBe(true);
199
+ expect(readonlyLocal.value).toBe(false);
200
+
201
+ props.isEditable = false;
202
+
203
+ expect(disabledLocal.value).toBe(false);
204
+ expect(readonlyLocal.value).toBe(true);
205
+ });
206
+
207
+ it("merges row-specific form element props only in edit mode", () => {
208
+ const formElementEditPropsCallback = jest.fn(({ rowData }) => ({
209
+ disabled: rowData.locked,
210
+ min: rowData.minimum,
211
+ readonly: true,
212
+ }));
213
+ const props = reactive({
214
+ column: {
215
+ id: "score",
216
+ formElement: {
217
+ disabled: false,
218
+ min: 0,
219
+ type: "integer",
220
+ },
221
+ formElementEditPropsCallback,
222
+ },
223
+ columnIndex: 1,
224
+ isCreateMode: true,
225
+ isEditable: true,
226
+ isEditMode: false,
227
+ isFooter: false,
228
+ row: {
229
+ id: 1,
230
+ locked: true,
231
+ minimum: 10,
232
+ },
233
+ rowData: {
234
+ id: 1,
235
+ locked: true,
236
+ minimum: 20,
237
+ },
238
+ rowIndex: 2,
239
+ rows: [],
240
+ });
241
+ const formElement = computed(() => getFormElement({
242
+ column: props.column,
243
+ columnIndex: props.columnIndex,
244
+ isCreateMode: props.isCreateMode,
245
+ isEditMode: props.isEditMode,
246
+ row: props.row,
247
+ rowData: props.rowData,
248
+ rowIndex: props.rowIndex,
249
+ rows: props.rows,
250
+ }));
251
+ const {
252
+ disabledLocal,
253
+ } = CellDisabledAPI(props, {
254
+ formElement,
255
+ });
256
+ const {
257
+ readonlyLocal,
258
+ } = CellReadonlyAPI(props, {
259
+ formElement,
260
+ });
261
+
262
+ expect(formElement.value).toEqual(props.column.formElement);
263
+ expect(formElementEditPropsCallback).not.toHaveBeenCalled();
264
+
265
+ props.isEditMode = true;
266
+
267
+ expect(formElement.value).toEqual(props.column.formElement);
268
+ expect(formElementEditPropsCallback).not.toHaveBeenCalled();
269
+
270
+ props.isCreateMode = false;
271
+
272
+ expect(formElement.value).toEqual({
273
+ disabled: true,
274
+ min: 20,
275
+ readonly: true,
276
+ type: "integer",
277
+ });
278
+ expect(disabledLocal.value).toBe(true);
279
+ expect(readonlyLocal.value).toBe(true);
280
+ expect(formElementEditPropsCallback).toHaveBeenCalledWith({
281
+ column: props.column,
282
+ columnIndex: 1,
283
+ row: props.row,
284
+ rowData: props.rowData,
285
+ rowIndex: 2,
286
+ rows: props.rows,
287
+ });
288
+ });
289
+
290
+ it.each([
291
+ [true, true, 112],
292
+ [true, false, 64],
293
+ [false, true, 64],
294
+ [false, false, 64],
295
+ ])("uses the expected action width for editable=%s and deletable=%s", (isEditable, isDeletable, width) => {
296
+ const props = reactive({
297
+ hasActiveEditRow: false,
298
+ isActiveEditMode: false,
299
+ isDeletable,
300
+ isDeletableConfirm: false,
301
+ isEditable,
302
+ widths: {
303
+ actionsColumnDouble: 112,
304
+ actionsColumnSingle: 64,
305
+ },
306
+ });
307
+ const {
308
+ columnStyles,
309
+ } = CellActionStylesAPI(props);
310
+
311
+ expect(columnStyles.value.width).toBe(`${ width }px`);
312
+ });
313
+
314
+ it("shows the actions column only for edit, delete, or an active add row", () => {
315
+ const isAddRowActive = ref(false);
316
+ const props = reactive({
317
+ columns: [{ id: "name" }],
318
+ isDeletable: false,
319
+ isDeletableConfirm: false,
320
+ isDragAndDrop: false,
321
+ isEditable: false,
322
+ rowView: "table",
323
+ });
324
+ const {
325
+ allColumnsLength,
326
+ hasActionsColumn,
327
+ } = ColumnsAPI(props, {
328
+ isAddRowActive,
329
+ });
330
+
331
+ expect(hasActionsColumn.value).toBe(false);
332
+ expect(allColumnsLength.value).toBe(1);
333
+
334
+ props.isEditable = true;
335
+ expect(hasActionsColumn.value).toBe(true);
336
+ expect(allColumnsLength.value).toBe(2);
337
+
338
+ props.isEditable = false;
339
+ props.isDeletableConfirm = true;
340
+ expect(hasActionsColumn.value).toBe(true);
341
+
342
+ props.isDeletableConfirm = false;
343
+ isAddRowActive.value = true;
344
+ expect(hasActionsColumn.value).toBe(true);
345
+ });
346
+
347
+ it("grows all columns equally only when no column has a positive grow value", async() => {
348
+ const resizeObserverOriginal = global.ResizeObserver;
349
+ global.ResizeObserver = class {
350
+ disconnect() {}
351
+ observe() {}
352
+ unobserve() {}
353
+ };
354
+
355
+ const wrapperElement = document.createElement("div");
356
+ const tableElement = document.createElement("table");
357
+ tableElement.id = "table_grow_fallback";
358
+ wrapperElement.getBoundingClientRect = () => ({ width: 500 });
359
+ wrapperElement.appendChild(tableElement);
360
+ document.body.appendChild(wrapperElement);
361
+
362
+ const props = reactive({
363
+ id: "table_grow_fallback",
364
+ isColumnsGrow: true,
365
+ isDeletable: false,
366
+ isDeletableConfirm: false,
367
+ isDragAndDrop: false,
368
+ isEditable: true,
369
+ });
370
+ const columns = ref([
371
+ { grow: 0, id: "first", width: "100px" },
372
+ { id: "second", width: "100px" },
373
+ ]);
374
+ const columnsVisible = computed(() => columns.value);
375
+ const {
376
+ columnsStylesGrow,
377
+ destroyColumnsGrowObserver,
378
+ initColumnsGrowObserver,
379
+ } = ColumnsGrowAPI(props, {
380
+ columnsVisible,
381
+ hasActionsColumn: computed(() => true),
382
+ widthsLocal: computed(() => ({
383
+ actionsColumnDouble: 112,
384
+ actionsColumnSingle: 64,
385
+ dndColumn: 56,
386
+ })),
387
+ });
388
+
389
+ initColumnsGrowObserver();
390
+
391
+ expect(columnsStylesGrow.value).toEqual({
392
+ first: {
393
+ maxWidth: "217px",
394
+ minWidth: "217px",
395
+ width: "217px",
396
+ },
397
+ second: {
398
+ maxWidth: "217px",
399
+ minWidth: "217px",
400
+ width: "217px",
401
+ },
402
+ });
403
+
404
+ columns.value = [
405
+ { grow: 1, id: "first", width: "100px" },
406
+ { grow: 0, id: "second", width: "100px" },
407
+ ];
408
+ await nextTick();
409
+
410
+ expect(columnsStylesGrow.value.first.width).toBe("334px");
411
+ expect(columnsStylesGrow.value.second.width).toBe("100px");
412
+
413
+ destroyColumnsGrowObserver();
414
+ wrapperElement.remove();
415
+ global.ResizeObserver = resizeObserverOriginal;
416
+ });
417
+
418
+ it("allows adding editable data when row editing is disabled", async() => {
419
+ const wrapper = mount(ATableForm, {
420
+ props: {
421
+ addRow: jest.fn(),
422
+ columns: [
423
+ {
424
+ id: "name",
425
+ formElement: {
426
+ type: "text",
427
+ },
428
+ },
429
+ ],
430
+ isAddable: true,
431
+ isEditable: false,
432
+ rowView: "list",
433
+ rows: [],
434
+ },
435
+ });
436
+
437
+ expect(wrapper.find(".a_table_form__cell_actions").exists()).toBe(false);
438
+
439
+ await wrapper.find(".a_mt_3 button").trigger("click");
440
+
441
+ expect(wrapper.find("tbody button[id$='_cancel']").exists()).toBe(true);
442
+ expect(wrapper.find("tbody button[id$='_save']").exists()).toBe(true);
443
+ expect(wrapper.findComponent(AForm).props("readonly")).toBe(false);
444
+ });
445
+
446
+ it("allows DND but not row-click editing when rows are not editable", async() => {
447
+ const wrapper = mount(ATableForm, {
448
+ props: {
449
+ columns: [
450
+ {
451
+ id: "name",
452
+ formElement: {
453
+ type: "text",
454
+ },
455
+ },
456
+ ],
457
+ isDragAndDrop: true,
458
+ isEditable: false,
459
+ isEditOnRowClick: true,
460
+ rows: [{ name: "Readonly" }],
461
+ },
462
+ });
463
+
464
+ expect(wrapper.find("tbody .a_table_form__reorder_handle").attributes("draggable")).toBe("true");
465
+
466
+ await wrapper.find("tbody tr.a_table_form__row").trigger("click");
467
+
468
+ expect(wrapper.find("tbody button[id$='_save']").exists()).toBe(false);
469
+ });
470
+
471
+ it("enters edit mode by row click only when enabled and row edit is available", async() => {
472
+ const rows = [
473
+ {
474
+ id: 1,
475
+ name: "Editable",
476
+ },
477
+ {
478
+ id: 2,
479
+ name: "Disabled",
480
+ },
481
+ ];
482
+ const wrapper = mount(ATableForm, {
483
+ props: {
484
+ actionsDisabledCallback: {
485
+ edit: ({ row }) => row.id === 2,
486
+ },
487
+ columns: [
488
+ {
489
+ id: "name",
490
+ label: "Name",
491
+ formElement: {
492
+ type: "text",
493
+ },
494
+ },
495
+ ],
496
+ isEditable: true,
497
+ isEditOnRowClick: true,
498
+ keyId: "id",
499
+ rows,
500
+ },
501
+ });
502
+
503
+ const bodyRows = wrapper.findAll("tbody tr.a_table_form__row");
504
+
505
+ await bodyRows[1].trigger("click");
506
+ expect(wrapper.find("tbody tr.a_table_form__row_edit_on_click").exists()).toBe(true);
507
+
508
+ await bodyRows[0].trigger("click");
509
+ expect(wrapper.find("tbody tr.a_table_form__row_edit_on_click").exists()).toBe(false);
510
+ expect(wrapper.find("tbody button[id$='_save']").exists()).toBe(true);
511
+ });
512
+
513
+ it("does not enter edit mode by row click when the prop is disabled", async() => {
514
+ const wrapper = mount(ATableForm, {
515
+ props: {
516
+ columns: [
517
+ {
518
+ id: "name",
519
+ label: "Name",
520
+ formElement: {
521
+ type: "text",
522
+ },
523
+ },
524
+ ],
525
+ isEditable: true,
526
+ rows: [
527
+ {
528
+ name: "Readonly row click",
529
+ },
530
+ ],
531
+ },
532
+ });
533
+
534
+ await wrapper.find("tbody tr.a_table_form__row").trigger("click");
535
+
536
+ expect(wrapper.find("tbody button[id$='_save']").exists()).toBe(false);
537
+ });
538
+
539
+ it("focuses the clicked column after entering edit mode by row click", async() => {
540
+ const wrapper = mount(ATableForm, {
541
+ attachTo: document.body,
542
+ props: {
543
+ columns: [
544
+ {
545
+ id: "number",
546
+ label: "Number",
547
+ formElement: {
548
+ type: "text",
549
+ },
550
+ },
551
+ {
552
+ id: "name",
553
+ label: "Name",
554
+ formElement: {
555
+ type: "text",
556
+ },
557
+ },
558
+ ],
559
+ isEditable: true,
560
+ isEditOnRowClick: true,
561
+ rows: [
562
+ {
563
+ name: "Marta Ivanova",
564
+ number: 1,
565
+ },
566
+ ],
567
+ },
568
+ });
569
+
570
+ await wrapper.find("tbody [data-column-id='name']").trigger("click");
571
+ await wrapper.vm.$nextTick();
572
+
573
+ expect(wrapper.find("tbody button[id$='_save']").exists()).toBe(true);
574
+ expect(document.activeElement.closest("[data-column-id]").dataset.columnId).toBe("name");
575
+
576
+ wrapper.unmount();
577
+ });
578
+
579
+ it("focuses the clicked form item in list view after entering edit mode by row click", async() => {
580
+ const wrapper = mount(ATableForm, {
581
+ attachTo: document.body,
582
+ props: {
583
+ columns: [
584
+ {
585
+ id: "number",
586
+ label: "Number",
587
+ formElement: {
588
+ type: "text",
589
+ },
590
+ },
591
+ {
592
+ id: "name",
593
+ label: "Name",
594
+ formElement: {
595
+ type: "text",
596
+ },
597
+ },
598
+ ],
599
+ isEditable: true,
600
+ isEditOnRowClick: true,
601
+ rowView: "list",
602
+ rows: [
603
+ {
604
+ name: "Marta Ivanova",
605
+ number: 1,
606
+ },
607
+ ],
608
+ },
609
+ });
610
+
611
+ await wrapper.find("tbody [data-column-id='name']").trigger("click");
612
+ await wrapper.vm.$nextTick();
613
+
614
+ expect(wrapper.find("tbody button[id$='_save']").exists()).toBe(true);
615
+ expect(document.activeElement.closest("[data-column-id]").dataset.columnId).toBe("name");
616
+
617
+ wrapper.unmount();
618
+ });
619
+
620
+ it("uses one content column and finds required fields recursively", () => {
621
+ const props = reactive({
622
+ columns: [
623
+ {
624
+ id: "fieldset",
625
+ formElement: {
626
+ children: [
627
+ {
628
+ id: "requiredChild",
629
+ required: true,
630
+ type: "text",
631
+ },
632
+ ],
633
+ type: "fieldset",
634
+ },
635
+ },
636
+ {
637
+ id: "secondColumn",
638
+ formElement: {
639
+ type: "text",
640
+ },
641
+ },
642
+ ],
643
+ isAddable: false,
644
+ isDeletable: true,
645
+ isDeletableConfirm: false,
646
+ isDragAndDrop: true,
647
+ isEditable: true,
648
+ rowView: "list",
649
+ rows: [],
650
+ });
651
+ const {
652
+ allColumnsLength,
653
+ columnsVisible,
654
+ hasActionsColumn,
655
+ } = ColumnsAPI(props);
656
+ const {
657
+ hasRequiredEditableColumns,
658
+ } = TableEditAPI(props, {
659
+ columnsVisible,
660
+ getRowKey: jest.fn(),
661
+ });
662
+
663
+ expect(allColumnsLength.value).toBe(3);
664
+ expect(hasRequiredEditableColumns.value).toBe(true);
665
+
666
+ props.rowView = "table";
667
+ expect(allColumnsLength.value).toBe(4);
668
+ expect(hasActionsColumn.value).toBe(true);
669
+ });
670
+
671
+ it("converts columns and nested fieldsets to AForm data", () => {
672
+ const props = reactive({
673
+ columns: [
674
+ {
675
+ id: "limits",
676
+ label: "Limits",
677
+ formElement: {
678
+ type: "fieldset",
679
+ children: [
680
+ {
681
+ id: "negative",
682
+ label: "Negative",
683
+ type: "integer",
684
+ useRowReadonly: true,
685
+ },
686
+ ],
687
+ },
688
+ },
689
+ ],
690
+ isEditable: true,
691
+ isEditMode: false,
692
+ });
693
+ const {
694
+ dataForm,
695
+ } = DataAPI(props);
696
+
697
+ expect(dataForm.value).toEqual([
698
+ {
699
+ children: [
700
+ {
701
+ id: "negative",
702
+ label: "Negative",
703
+ readonly: true,
704
+ type: "integer",
705
+ useRowReadonly: true,
706
+ },
707
+ ],
708
+ "data-column-id": "limits",
709
+ disabled: true,
710
+ id: "limits",
711
+ label: "Limits",
712
+ type: "fieldset",
713
+ },
714
+ ]);
715
+
716
+ props.isEditMode = true;
717
+
718
+ expect(dataForm.value[0].disabled).toBeUndefined();
719
+ expect(dataForm.value[0].children[0].readonly).toBe(false);
720
+ });
721
+
722
+ it("applies row-specific form element props in list edit mode", () => {
723
+ const props = reactive({
724
+ columns: [
725
+ {
726
+ id: "score",
727
+ formElement: {
728
+ min: 0,
729
+ type: "integer",
730
+ },
731
+ formElementEditPropsCallback: ({ rowData }) => ({
732
+ disabled: rowData.locked,
733
+ min: rowData.minimum,
734
+ }),
735
+ },
736
+ ],
737
+ isEditable: true,
738
+ isEditMode: false,
739
+ row: {
740
+ locked: true,
741
+ minimum: 10,
742
+ },
743
+ rowData: {
744
+ locked: true,
745
+ minimum: 20,
746
+ },
747
+ rowIndex: 0,
748
+ rows: [],
749
+ });
750
+ const {
751
+ dataForm,
752
+ } = DataAPI(props);
753
+
754
+ expect(dataForm.value[0].min).toBe(0);
755
+
756
+ props.isEditMode = true;
757
+
758
+ expect(dataForm.value[0]).toEqual(expect.objectContaining({
759
+ disabled: true,
760
+ min: 20,
761
+ type: "integer",
762
+ }));
763
+ });
764
+
765
+ it("passes the complete errors object to AForm and emits its full model", async() => {
766
+ const errors = {
767
+ negative: ["Value is too low"],
768
+ };
769
+ const wrapper = mount(ATableFormCellList, {
770
+ props: {
771
+ columns: [
772
+ {
773
+ id: "limits",
774
+ formElement: {
775
+ type: "fieldset",
776
+ children: [
777
+ {
778
+ id: "negative",
779
+ type: "integer",
780
+ },
781
+ ],
782
+ },
783
+ },
784
+ ],
785
+ errors,
786
+ id: "table_0",
787
+ isEditable: true,
788
+ isEditMode: true,
789
+ row: {
790
+ negative: 10,
791
+ },
792
+ rowIndex: 0,
793
+ rows: [],
794
+ },
795
+ });
796
+ const form = wrapper.findComponent(AForm);
797
+
798
+ expect(form.props("errors")).toEqual(errors);
799
+ expect(form.props("showErrors")).toBe(true);
800
+ expect(form.props("showRequiredText")).toBe(false);
801
+ expect(form.props("useFlatErrors")).toBe(true);
802
+
803
+ form.vm.$emit("change", {
804
+ fullModel: {
805
+ negative: 20,
806
+ },
807
+ id: "negative",
808
+ item: {
809
+ id: "negative",
810
+ },
811
+ model: 20,
812
+ });
813
+ await wrapper.vm.$nextTick();
814
+
815
+ expect(wrapper.emitted("updateRowData")[0][0]).toEqual(expect.objectContaining({
816
+ column: wrapper.props("columns")[0],
817
+ columnId: "negative",
818
+ fullModel: {
819
+ negative: 20,
820
+ },
821
+ model: 20,
822
+ }));
823
+ });
824
+
825
+ it("replaces the complete edit model and clears the changed field error", () => {
826
+ const errorsLocal = ref({
827
+ negative: ["Value is too low"],
828
+ positive: ["Value is too high"],
829
+ });
830
+ const {
831
+ modelLocal,
832
+ updateModelLocal,
833
+ } = RowEditAPI(reactive({
834
+ changeModel: undefined,
835
+ onCancelEditRow: jest.fn(),
836
+ row: {
837
+ negative: 10,
838
+ positive: 10,
839
+ },
840
+ rowIndex: 0,
841
+ rows: [],
842
+ saveRow: jest.fn(),
843
+ }), {
844
+ errorsLocal,
845
+ });
846
+
847
+ updateModelLocal({
848
+ columnId: "negative",
849
+ fullModel: {
850
+ negative: 20,
851
+ positive: 10,
852
+ },
853
+ model: 20,
854
+ });
855
+
856
+ expect(modelLocal.value).toEqual({
857
+ negative: 20,
858
+ positive: 10,
859
+ });
860
+ expect(errorsLocal.value).toEqual({
861
+ positive: ["Value is too high"],
862
+ });
863
+ });
864
+ });