@adyen/bento-mcp 0.10.0 → 0.12.0

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 (429) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.md +24 -2
  3. package/SKILL.md +37 -7
  4. package/dist/assets/components/accordion/accordion.stories.ts +1 -1
  5. package/dist/assets/components/accordion/components/accordion-item.stories.ts +1 -1
  6. package/dist/assets/components/accordion/components/accordion-item.vue +1 -1
  7. package/dist/assets/components/action-bar/action-bar.docs.mdx +10 -3
  8. package/dist/assets/components/action-bar/action-bar.internal.types.ts +1 -0
  9. package/dist/assets/components/action-bar/action-bar.stories.ts +1 -1
  10. package/dist/assets/components/action-bar/action-bar.types.ts +1 -1
  11. package/dist/assets/components/action-bar/action-bar.vue +1 -1
  12. package/dist/assets/components/ai-tag/ai-tag.stories.ts +1 -1
  13. package/dist/assets/components/ai-tag/ai-tag.vue +1 -1
  14. package/dist/assets/components/alert/alert.stories.ts +1 -1
  15. package/dist/assets/components/alert/alert.types.ts +1 -1
  16. package/dist/assets/components/anchor-scroller/anchor-scroller.stories.ts +1 -1
  17. package/dist/assets/components/anchor-scroller/anchor-scroller.vue +1 -1
  18. package/dist/assets/components/avatar/avatar.internal.types.ts +1 -0
  19. package/dist/assets/components/avatar/avatar.stories.ts +1 -1
  20. package/dist/assets/components/avatar/avatar.types.ts +1 -1
  21. package/dist/assets/components/button/button.docs.mdx +4 -3
  22. package/dist/assets/components/button/button.stories.ts +1 -1
  23. package/dist/assets/components/button/button.types.ts +1 -1
  24. package/dist/assets/components/button/components/ai-button/ai-button.stories.ts +1 -1
  25. package/dist/assets/components/button/components/ai-button/ai-button.vue +1 -1
  26. package/dist/assets/components/button/components/button-actions/button-actions.docs.mdx +3 -0
  27. package/dist/assets/components/button/components/button-actions/button-actions.internal.types.ts +1 -0
  28. package/dist/assets/components/button/components/button-actions/button-actions.stories.ts +1 -1
  29. package/dist/assets/components/button/components/button-actions/button-actions.types.ts +1 -1
  30. package/dist/assets/components/button/components/button-actions/button-actions.vue +1 -1
  31. package/dist/assets/components/button/components/loading-button/loading-button.docs.mdx +26 -23
  32. package/dist/assets/components/button/components/loading-button/loading-button.stories.ts +1 -1
  33. package/dist/assets/components/button/components/loading-button/loading-button.vue +1 -1
  34. package/dist/assets/components/button/components/toggle-button/toggle-button.stories.ts +1 -1
  35. package/dist/assets/components/card/card.docs.mdx +18 -1
  36. package/dist/assets/components/card/card.stories.ts +1 -1
  37. package/dist/assets/components/card/card.types.ts +1 -1
  38. package/dist/assets/components/card/card.vue +1 -1
  39. package/dist/assets/components/checkbox/checkbox.stories.ts +1 -1
  40. package/dist/assets/components/checkbox/checkbox.types.ts +1 -1
  41. package/dist/assets/components/checkbox/checkbox.vue +1 -1
  42. package/dist/assets/components/checkbox/components/checkbox-group/checkbox-group.docs.mdx +9 -14
  43. package/dist/assets/components/checkbox/components/checkbox-group/checkbox-group.stories.ts +1 -1
  44. package/dist/assets/components/checkbox/components/checkbox-group/checkbox-group.types.ts +1 -1
  45. package/dist/assets/components/checkbox/components/checkbox-group/checkbox-group.vue +1 -1
  46. package/dist/assets/components/chip/chip.stories.ts +1 -1
  47. package/dist/assets/components/chip/chip.vue +1 -1
  48. package/dist/assets/components/click-outside/click-outside.stories.ts +1 -1
  49. package/dist/assets/components/code-snippet/code-snippet.types.ts +1 -1
  50. package/dist/assets/components/code-snippet/code-snippet.vue +1 -1
  51. package/dist/assets/components/country/country.stories.ts +1 -1
  52. package/dist/assets/components/country/country.types.ts +1 -1
  53. package/dist/assets/components/country/country.vue +1 -1
  54. package/dist/assets/components/currency/currency.stories.ts +1 -1
  55. package/dist/assets/components/currency/currency.vue +1 -1
  56. package/dist/assets/components/dashed-underline/dashed-underline.stories.ts +1 -1
  57. package/dist/assets/components/data-grid/components/data-grid-cell-actions/data-grid-cell-actions.types.ts +1 -1
  58. package/dist/assets/components/data-grid/components/data-grid-cell-actions/data-grid-cell-actions.vue +1 -1
  59. package/dist/assets/components/data-grid/components/data-grid-config-settings/data-grid-config-settings.vue +1 -1
  60. package/dist/assets/components/data-grid/components/data-grid-row/data-grid-row.vue +1 -1
  61. package/dist/assets/components/data-grid/components/data-grid-static-icon/data-grid-static-icon.stories.ts +1 -1
  62. package/dist/assets/components/data-grid/components/data-grid-summary-cell/data-grid-summary-cell.stories.ts +1 -1
  63. package/dist/assets/components/data-grid/components/data-grid-summary-cell/data-grid-summary-cell.vue +1 -1
  64. package/dist/assets/components/data-grid/components/data-grid-tag-with-text-cell/data-grid-tag-with-text-cell.stories.ts +1 -1
  65. package/dist/assets/components/data-grid/components/data-grid-trend-cell/data-grid-trend-cell.stories.ts +1 -1
  66. package/dist/assets/components/data-grid/components/data-grid-trend-cell/data-grid-trend-cell.vue +1 -1
  67. package/dist/assets/components/data-grid/data-grid.docs.mdx +3 -60
  68. package/dist/assets/components/data-grid/data-grid.stories.ts +1 -1
  69. package/dist/assets/components/data-grid/data-grid.vue +1 -1
  70. package/dist/assets/components/date/date.stories.ts +1 -1
  71. package/dist/assets/components/date-picker/date-picker.stories.ts +1 -1
  72. package/dist/assets/components/date-picker/date-picker.types.ts +1 -1
  73. package/dist/assets/components/date-picker/date-picker.vue +1 -1
  74. package/dist/assets/components/date-range-picker/components/date-range-picker-calendar/date-range-picker-calendar.vue +1 -1
  75. package/dist/assets/components/date-range-picker/components/date-time-input/date-time-input.types.ts +1 -1
  76. package/dist/assets/components/date-range-picker/components/date-time-input/date-time-input.vue +1 -1
  77. package/dist/assets/components/date-range-picker/date-range-picker.docs.mdx +31 -6
  78. package/dist/assets/components/date-range-picker/date-range-picker.stories.ts +1 -1
  79. package/dist/assets/components/date-range-picker/date-range-picker.types.ts +1 -1
  80. package/dist/assets/components/date-range-picker/date-range-picker.vue +1 -1
  81. package/dist/assets/components/date-time-picker/date-time-picker.stories.ts +1 -1
  82. package/dist/assets/components/date-time-picker/date-time-picker.types.ts +1 -1
  83. package/dist/assets/components/divider/divider.internal.types.ts +1 -0
  84. package/dist/assets/components/divider/divider.stories.ts +1 -1
  85. package/dist/assets/components/divider/divider.types.ts +1 -1
  86. package/dist/assets/components/divider/divider.vue +1 -1
  87. package/dist/assets/components/draggable/components/draggable-handle/draggable-handle.stories.ts +1 -1
  88. package/dist/assets/components/draggable/draggable.stories.ts +1 -1
  89. package/dist/assets/components/draggable/draggable.vue +1 -1
  90. package/dist/assets/components/drawer/drawer.stories.ts +1 -1
  91. package/dist/assets/components/dropdown/components/dropdown-base-textbox/dropdown-base-textbox.internal.types.ts +1 -0
  92. package/dist/assets/components/dropdown/components/dropdown-base-textbox/dropdown-base-textbox.types.ts +1 -1
  93. package/dist/assets/components/dropdown/components/dropdown-base-textbox/dropdown-base-textbox.vue +1 -1
  94. package/dist/assets/components/dropdown/components/dropdown-default-textbox/dropdown-default-textbox.vue +1 -1
  95. package/dist/assets/components/dropdown/components/dropdown-options-container/dropdown-options-container.vue +1 -1
  96. package/dist/assets/components/dropdown/components/dropdown-small-textbox/dropdown-small-textbox.vue +1 -1
  97. package/dist/assets/components/dropdown/components/variants/dropdown-avatar/dropdown-avatar.stories.ts +1 -1
  98. package/dist/assets/components/dropdown/components/variants/dropdown-avatar/dropdown-avatar.types.ts +1 -1
  99. package/dist/assets/components/dropdown/components/variants/dropdown-avatar/dropdown-avatar.vue +1 -1
  100. package/dist/assets/components/dropdown/components/variants/dropdown-country/dropdown-country.stories.ts +1 -1
  101. package/dist/assets/components/dropdown/components/variants/dropdown-country/dropdown-country.types.ts +1 -1
  102. package/dist/assets/components/dropdown/components/variants/dropdown-country/dropdown-country.vue +1 -1
  103. package/dist/assets/components/dropdown/components/variants/dropdown-currency/dropdown-currency.stories.ts +1 -1
  104. package/dist/assets/components/dropdown/components/variants/dropdown-currency/dropdown-currency.types.ts +1 -1
  105. package/dist/assets/components/dropdown/components/variants/dropdown-currency/dropdown-currency.vue +1 -1
  106. package/dist/assets/components/dropdown/components/variants/dropdown-payment-method/dropdown-payment-method.stories.ts +1 -1
  107. package/dist/assets/components/dropdown/components/variants/dropdown-payment-method/dropdown-payment-method.types.ts +1 -1
  108. package/dist/assets/components/dropdown/components/variants/dropdown-payment-method/dropdown-payment-method.vue +1 -1
  109. package/dist/assets/components/dropdown/components/variants/dropdown-tag/dropdown-tag.stories.ts +1 -1
  110. package/dist/assets/components/dropdown/components/variants/dropdown-tag/dropdown-tag.types.ts +1 -1
  111. package/dist/assets/components/dropdown/components/variants/dropdown-tag/dropdown-tag.vue +1 -1
  112. package/dist/assets/components/dropdown/dropdown.docs.mdx +4 -40
  113. package/dist/assets/components/dropdown/dropdown.internal.types.ts +1 -0
  114. package/dist/assets/components/dropdown/dropdown.stories.ts +1 -1
  115. package/dist/assets/components/dropdown/dropdown.types.ts +1 -1
  116. package/dist/assets/components/dropdown/dropdown.vue +1 -1
  117. package/dist/assets/components/empty-state/empty-state.stories.ts +1 -1
  118. package/dist/assets/components/empty-state/empty-state.types.ts +1 -1
  119. package/dist/assets/components/file-uploader/components/file-uploader-file-card/file-uploader-file-card.stories.ts +1 -1
  120. package/dist/assets/components/file-uploader/components/file-uploader-file-card/file-uploader-file-card.types.ts +1 -1
  121. package/dist/assets/components/file-uploader/components/file-uploader-file-card/file-uploader-file-card.vue +1 -1
  122. package/dist/assets/components/file-uploader/components/file-uploader-restrictions/file-uploader-restrictions.types.ts +1 -1
  123. package/dist/assets/components/file-uploader/components/file-uploader-restrictions/file-uploader-restrictions.vue +1 -1
  124. package/dist/assets/components/file-uploader/file-uploader.internal.types.ts +1 -0
  125. package/dist/assets/components/file-uploader/file-uploader.stories.ts +1 -1
  126. package/dist/assets/components/file-uploader/file-uploader.types.ts +1 -1
  127. package/dist/assets/components/file-uploader/file-uploader.vue +1 -1
  128. package/dist/assets/components/filter-bar/components/all-filters-modal/all-filters-modal.stories.ts +1 -1
  129. package/dist/assets/components/filter-bar/components/all-filters-modal/all-filters-modal.types.ts +1 -1
  130. package/dist/assets/components/filter-bar/components/all-filters-modal/all-filters-modal.vue +1 -1
  131. package/dist/assets/components/filter-bar/components/all-filters-modal/components/all-filters-modal-filter-selection/all-filters-modal-filter-selection.types.ts +1 -0
  132. package/dist/assets/components/filter-bar/components/all-filters-modal/components/all-filters-modal-filter-selection/all-filters-modal-filter-selection.vue +1 -0
  133. package/dist/assets/components/filter-bar/components/all-filters-modal/components/all-filters-modal-selected-filter/all-filters-modal-selected-filter.vue +1 -0
  134. package/dist/assets/components/filter-bar/components/base-filter/base-filter.internal.types.ts +1 -0
  135. package/dist/assets/components/filter-bar/components/base-filter/base-filter.types.ts +1 -1
  136. package/dist/assets/components/filter-bar/components/base-filter/base-filter.vue +1 -1
  137. package/dist/assets/components/filter-bar/components/boolean-filter/boolean-filter.vue +1 -1
  138. package/dist/assets/components/filter-bar/components/date-filter/date-filter.vue +1 -1
  139. package/dist/assets/components/filter-bar/components/date-range-filter/date-range-filter.vue +1 -1
  140. package/dist/assets/components/filter-bar/components/input-filter/input-filter.types.ts +1 -1
  141. package/dist/assets/components/filter-bar/components/input-filter/input-filter.vue +1 -1
  142. package/dist/assets/components/filter-bar/components/input-with-dropdown-filter/input-with-dropdown-filter.stories.ts +1 -1
  143. package/dist/assets/components/filter-bar/components/input-with-dropdown-filter/input-with-dropdown-filter.vue +1 -1
  144. package/dist/assets/components/filter-bar/components/select-filter/components/select-filter-button/select-filter-button.vue +1 -1
  145. package/dist/assets/components/filter-bar/components/select-filter/select-filter.vue +1 -1
  146. package/dist/assets/components/filter-bar/components/select-filter/variants/select-avatar-filter/select-avatar-filter.stories.ts +1 -1
  147. package/dist/assets/components/filter-bar/components/select-filter/variants/select-country-filter/select-country-filter.stories.ts +1 -1
  148. package/dist/assets/components/filter-bar/components/select-filter/variants/select-country-filter/select-country-filter.vue +1 -1
  149. package/dist/assets/components/filter-bar/components/toggle-filter/toggle-filter.vue +1 -1
  150. package/dist/assets/components/filter-bar/filter-bar.docs.mdx +4 -62
  151. package/dist/assets/components/filter-bar/filter-bar.stories.ts +1 -1
  152. package/dist/assets/components/filter-bar/filter-bar.types.ts +1 -1
  153. package/dist/assets/components/filter-bar/filter-bar.vue +1 -1
  154. package/dist/assets/components/form-layout/form-layout.docs.mdx +0 -23
  155. package/dist/assets/components/form-layout/form-layout.stories.ts +1 -1
  156. package/dist/assets/components/header/header.stories.ts +1 -1
  157. package/dist/assets/components/header/header.types.ts +1 -1
  158. package/dist/assets/components/header/header.vue +1 -1
  159. package/dist/assets/components/header-with-views/components/header-with-views-all-views/header-with-views-all-views.vue +1 -1
  160. package/dist/assets/components/header-with-views/components/header-with-views-item-edit-form/header-with-views-edit-form.types.ts +1 -1
  161. package/dist/assets/components/header-with-views/components/header-with-views-item-edit-form/header-with-views-edit-form.vue +1 -1
  162. package/dist/assets/components/header-with-views/header-with-views.internal.types.ts +1 -0
  163. package/dist/assets/components/header-with-views/header-with-views.stories.ts +1 -1
  164. package/dist/assets/components/header-with-views/header-with-views.types.ts +1 -1
  165. package/dist/assets/components/header-with-views/header-with-views.vue +1 -1
  166. package/dist/assets/components/image/image.stories.ts +1 -1
  167. package/dist/assets/components/info-icon/info-icon.stories.ts +1 -1
  168. package/dist/assets/components/input-field/input-field.docs.mdx +1 -13
  169. package/dist/assets/components/input-field/input-field.stories.ts +1 -1
  170. package/dist/assets/components/input-field/input-field.types.ts +1 -1
  171. package/dist/assets/components/input-field/input-field.vue +1 -1
  172. package/dist/assets/components/input-field-password/input-field-password.internal.types.ts +1 -0
  173. package/dist/assets/components/input-field-password/input-field-password.stories.ts +1 -1
  174. package/dist/assets/components/input-field-password/input-field-password.types.ts +1 -1
  175. package/dist/assets/components/input-field-password/input-field-password.vue +1 -1
  176. package/dist/assets/components/input-field-phone-number/input-field-phone-number.stories.ts +1 -1
  177. package/dist/assets/components/input-field-phone-number/input-field-phone-number.types.ts +1 -1
  178. package/dist/assets/components/input-field-phone-number/input-field-phone-number.vue +1 -1
  179. package/dist/assets/components/input-time/input-time.docs.mdx +17 -0
  180. package/dist/assets/components/input-time/input-time.stories.ts +1 -1
  181. package/dist/assets/components/input-time/input-time.types.ts +1 -1
  182. package/dist/assets/components/input-time/input-time.vue +1 -1
  183. package/dist/assets/components/inspector/inspector.stories.ts +1 -1
  184. package/dist/assets/components/inspector/inspector.vue +1 -1
  185. package/dist/assets/components/layout/components/layout-row/layout-row.stories.ts +1 -1
  186. package/dist/assets/components/layout/components/layout-row/layout-row.vue +1 -1
  187. package/dist/assets/components/layout/layout.docs.mdx +10 -0
  188. package/dist/assets/components/layout/layout.internal.types.ts +1 -0
  189. package/dist/assets/components/layout/layout.stories.ts +1 -1
  190. package/dist/assets/components/layout/layout.types.ts +1 -1
  191. package/dist/assets/components/link/link.stories.ts +1 -1
  192. package/dist/assets/components/link/link.types.ts +1 -1
  193. package/dist/assets/components/link/link.vue +1 -1
  194. package/dist/assets/components/list/list.stories.ts +1 -1
  195. package/dist/assets/components/loading-indicator/loading-indicator.stories.ts +1 -1
  196. package/dist/assets/components/menu/components/menu-item/menu-item.types.ts +1 -1
  197. package/dist/assets/components/menu/components/menu-item/menu-item.vue +1 -1
  198. package/dist/assets/components/menu/components/menu-item-list/menu-item-list.vue +1 -1
  199. package/dist/assets/components/menu/components/sub-menu-item-list/sub-menu-item-list.vue +1 -1
  200. package/dist/assets/components/menu/menu.docs.mdx +17 -7
  201. package/dist/assets/components/menu/menu.stories.ts +1 -1
  202. package/dist/assets/components/menu/menu.types.ts +1 -1
  203. package/dist/assets/components/menu/menu.vue +1 -1
  204. package/dist/assets/components/modal/components/base-modal/base-modal.vue +1 -1
  205. package/dist/assets/components/modal/components/modal-page/modal-page.vue +1 -1
  206. package/dist/assets/components/modal/modal.internal.types.ts +1 -0
  207. package/dist/assets/components/modal/modal.stories.ts +1 -1
  208. package/dist/assets/components/modal/modal.types.ts +1 -1
  209. package/dist/assets/components/modal/modal.vue +1 -1
  210. package/dist/assets/components/modal-fullscreen/components/modal-fullscreen-page.vue +1 -1
  211. package/dist/assets/components/modal-fullscreen/modal-fullscreen.stories.ts +1 -1
  212. package/dist/assets/components/modal-fullscreen/modal-fullscreen.vue +1 -1
  213. package/dist/assets/components/navigation-menu/components/navigation-menu-group/navigation-menu-group.internal.types.ts +1 -0
  214. package/dist/assets/components/navigation-menu/components/navigation-menu-group/navigation-menu-group.types.ts +1 -1
  215. package/dist/assets/components/navigation-menu/components/navigation-menu-group/navigation-menu-group.vue +1 -1
  216. package/dist/assets/components/navigation-menu/components/navigation-menu-item/navigation-menu-item.vue +1 -1
  217. package/dist/assets/components/navigation-menu/navigation-menu.internal.types.ts +1 -0
  218. package/dist/assets/components/navigation-menu/navigation-menu.stories.ts +1 -1
  219. package/dist/assets/components/navigation-menu/navigation-menu.types.ts +1 -1
  220. package/dist/assets/components/navigation-menu/navigation-menu.vue +1 -1
  221. package/dist/assets/components/pagination/components/pagination-context/pagination-context.vue +1 -1
  222. package/dist/assets/components/pagination/components/pagination-results-per-page/pagination-results-per-page.vue +1 -1
  223. package/dist/assets/components/pagination/pagination.stories.ts +1 -1
  224. package/dist/assets/components/pagination/pagination.types.ts +1 -1
  225. package/dist/assets/components/pagination/pagination.vue +1 -1
  226. package/dist/assets/components/payment-method/payment-method.stories.ts +1 -1
  227. package/dist/assets/components/payment-method/payment-method.types.ts +1 -1
  228. package/dist/assets/components/popover/popover.docs.mdx +32 -9
  229. package/dist/assets/components/popover/popover.stories.ts +1 -1
  230. package/dist/assets/components/popover/popover.types.ts +1 -1
  231. package/dist/assets/components/popover/popover.vue +1 -1
  232. package/dist/assets/components/popper-container/popper-container.types.ts +1 -1
  233. package/dist/assets/components/popper-container/popper-container.vue +1 -1
  234. package/dist/assets/components/progress-bar/progress-bar.docs.mdx +102 -0
  235. package/dist/assets/components/progress-bar/progress-bar.stories.ts +1 -0
  236. package/dist/assets/components/progress-bar/progress-bar.types.ts +1 -0
  237. package/dist/assets/components/progress-bar/progress-bar.vue +1 -0
  238. package/dist/assets/components/promo-banner/promo-banner.stories.ts +1 -1
  239. package/dist/assets/components/promo-banner/promo-banner.types.ts +1 -1
  240. package/dist/assets/components/promo-banner/promo-banner.vue +1 -1
  241. package/dist/assets/components/radio-group/components/radio-button/radio-button.vue +1 -1
  242. package/dist/assets/components/radio-group/radio-group.docs.mdx +1 -6
  243. package/dist/assets/components/radio-group/radio-group.stories.ts +1 -1
  244. package/dist/assets/components/radio-group/radio-group.types.ts +1 -1
  245. package/dist/assets/components/radio-group/radio-group.vue +1 -1
  246. package/dist/assets/components/rich-text-editor/rich-text-editor.internal.types.ts +1 -0
  247. package/dist/assets/components/rich-text-editor/rich-text-editor.stories.ts +1 -1
  248. package/dist/assets/components/rich-text-editor/rich-text-editor.types.ts +1 -1
  249. package/dist/assets/components/rich-text-editor/rich-text-editor.vue +1 -1
  250. package/dist/assets/components/search-bar/search-bar.stories.ts +1 -1
  251. package/dist/assets/components/search-bar/search-bar.vue +1 -1
  252. package/dist/assets/components/secondary-nav/components/secondary-nav-item/secondary-nav-item.vue +1 -1
  253. package/dist/assets/components/secondary-nav/secondary-nav.stories.ts +1 -1
  254. package/dist/assets/components/secondary-nav/secondary-nav.vue +1 -1
  255. package/dist/assets/components/segmented-control/components/segmented-control-button/segmented-control-button.vue +1 -1
  256. package/dist/assets/components/segmented-control/segmented-control.stories.ts +1 -1
  257. package/dist/assets/components/segmented-control/segmented-control.types.ts +1 -1
  258. package/dist/assets/components/segmented-control/segmented-control.vue +1 -1
  259. package/dist/assets/components/selection-card/components/selection-card-group/selection-card-group.docs.mdx +12 -13
  260. package/dist/assets/components/selection-card/components/selection-card-group/selection-card-group.stories.ts +1 -1
  261. package/dist/assets/components/selection-card/components/selection-card-group/selection-card-group.vue +1 -1
  262. package/dist/assets/components/selection-card/selection-card.stories.ts +1 -1
  263. package/dist/assets/components/selection-card/selection-card.types.ts +1 -1
  264. package/dist/assets/components/selection-card/selection-card.vue +1 -1
  265. package/dist/assets/components/sidepanel/sidepanel.docs.mdx +1 -1
  266. package/dist/assets/components/sidepanel/sidepanel.stories.ts +1 -1
  267. package/dist/assets/components/sidepanel/sidepanel.vue +1 -1
  268. package/dist/assets/components/status/status.stories.ts +1 -1
  269. package/dist/assets/components/status/status.types.ts +1 -1
  270. package/dist/assets/components/stepper/components/step/step.vue +1 -1
  271. package/dist/assets/components/stepper/stepper.stories.ts +1 -1
  272. package/dist/assets/components/stepper/stepper.vue +1 -1
  273. package/dist/assets/components/structured-list/structured-list.stories.ts +1 -1
  274. package/dist/assets/components/structured-list/structured-list.vue +1 -1
  275. package/dist/assets/components/summary-grid/components/summary-grid-item/summary-grid-item.types.ts +1 -1
  276. package/dist/assets/components/summary-grid/summary-grid.stories.ts +1 -1
  277. package/dist/assets/components/summary-grid/summary-grid.types.ts +1 -1
  278. package/dist/assets/components/table-of-contents/components/table-of-contents-list/table-of-contents-list.vue +1 -1
  279. package/dist/assets/components/table-of-contents/table-of-contents.internal.types.ts +1 -0
  280. package/dist/assets/components/table-of-contents/table-of-contents.stories.ts +1 -1
  281. package/dist/assets/components/table-of-contents/table-of-contents.types.ts +1 -1
  282. package/dist/assets/components/table-of-contents/table-of-contents.vue +1 -1
  283. package/dist/assets/components/tabs/components/tab.internal.types.ts +1 -0
  284. package/dist/assets/components/tabs/components/tab.types.ts +1 -1
  285. package/dist/assets/components/tabs/components/tab.vue +1 -1
  286. package/dist/assets/components/tabs/tabs.stories.ts +1 -1
  287. package/dist/assets/components/tabs/tabs.vue +1 -1
  288. package/dist/assets/components/tag/tag.docs.mdx +1 -1
  289. package/dist/assets/components/tag/tag.stories.ts +1 -1
  290. package/dist/assets/components/tag/tag.types.ts +1 -1
  291. package/dist/assets/components/tag/tag.vue +1 -1
  292. package/dist/assets/components/textarea/textarea.docs.mdx +0 -7
  293. package/dist/assets/components/textarea/textarea.stories.ts +1 -1
  294. package/dist/assets/components/textarea/textarea.types.ts +1 -1
  295. package/dist/assets/components/textarea/textarea.vue +1 -1
  296. package/dist/assets/components/timeline/components/timeline-item/timeline-item.stories.ts +1 -1
  297. package/dist/assets/components/timeline/components/timeline-item/timeline-item.vue +1 -1
  298. package/dist/assets/components/timeline/timeline.docs.mdx +0 -10
  299. package/dist/assets/components/timeline/timeline.internal.types.ts +1 -0
  300. package/dist/assets/components/timeline/timeline.stories.ts +1 -1
  301. package/dist/assets/components/timeline/timeline.types.ts +1 -1
  302. package/dist/assets/components/timeline/timeline.vue +1 -1
  303. package/dist/assets/components/toast/components/toast-item/toast-item.vue +1 -1
  304. package/dist/assets/components/toggle/toggle.stories.ts +1 -1
  305. package/dist/assets/components/toggle/toggle.types.ts +1 -1
  306. package/dist/assets/components/toggle/toggle.vue +1 -1
  307. package/dist/assets/components/tutorial/tutorial.stories.ts +1 -1
  308. package/dist/assets/components/typography/typography.stories.ts +1 -1
  309. package/dist/assets/components/typography/typography.types.ts +1 -1
  310. package/dist/assets/components/typography/typography.vue +1 -1
  311. package/dist/assets/components.json +1 -0
  312. package/dist/assets/composables/use-bento-base-filter/index.ts +1 -0
  313. package/dist/assets/composables/use-bento-base-filter/use-bento-base-filter.ts +1 -0
  314. package/dist/assets/composables/use-bento-base-filter/utils/index.ts +1 -0
  315. package/dist/assets/composables/use-bento-base-filter/utils/utils.ts +1 -0
  316. package/dist/assets/composables/use-bento-currency/index.ts +1 -0
  317. package/dist/assets/composables/use-bento-currency/use-bento-currency.stories.ts +1 -1
  318. package/dist/assets/composables/use-bento-currency/use-bento-currency.ts +1 -0
  319. package/dist/assets/composables/use-bento-delayed-hover/index.ts +1 -0
  320. package/dist/assets/composables/use-bento-delayed-hover/use-bento-delayed-hover.stories.ts +1 -1
  321. package/dist/assets/composables/use-bento-delayed-hover/use-bento-delayed-hover.ts +1 -0
  322. package/dist/assets/composables/use-bento-theme/index.ts +1 -0
  323. package/dist/assets/composables/use-bento-theme/install.ts +1 -1
  324. package/dist/assets/composables/use-bento-theme/install.types.ts +1 -1
  325. package/dist/assets/composables/use-bento-theme/use-bento-theme.ts +1 -0
  326. package/dist/assets/composables/use-bento-toast-controller/index.ts +1 -0
  327. package/dist/assets/composables/use-bento-toast-controller/toast-stack.ts +1 -0
  328. package/dist/assets/composables/use-bento-toast-controller/use-bento-toast-controller.ts +1 -0
  329. package/dist/assets/composables/use-click-outside/index.ts +1 -0
  330. package/dist/assets/composables/use-click-outside/use-click-outside.stories.ts +1 -1
  331. package/dist/assets/composables/use-click-outside/use-click-outside.ts +1 -0
  332. package/dist/assets/composables/use-form-validate/index.ts +1 -0
  333. package/dist/assets/composables/use-form-validate/use-form.ts +1 -0
  334. package/dist/assets/composables/use-form-validate/use-form.types.ts +1 -1
  335. package/dist/assets/composables.json +9 -0
  336. package/dist/assets/deprecations.md +139 -243
  337. package/dist/assets/directives/highlight/highlight.stories.ts +1 -1
  338. package/dist/assets/directives/keyboard-navigation/keyboard-navigation.stories.ts +1 -1
  339. package/dist/assets/directives/tooltip/tooltip.internal.types.ts +1 -0
  340. package/dist/assets/directives/tooltip/tooltip.stories.ts +1 -1
  341. package/dist/assets/directives/tooltip/tooltip.types.ts +1 -1
  342. package/dist/assets/icons.json +1 -0
  343. package/dist/assets/index.ts +1 -1
  344. package/dist/assets/install.ts +1 -1
  345. package/dist/assets/tailwind/README.md +3 -3
  346. package/dist/assets/templates/dashboard-template/components/dashboard-section/dashboard-section.stories.ts +1 -1
  347. package/dist/assets/templates/dashboard-template/dashboard-template.stories.ts +1 -1
  348. package/dist/assets/templates/data-grid-template/data-grid-template.stories.ts +1 -1
  349. package/dist/assets/usage.json +81 -80
  350. package/dist/assets/variables.css +152 -140
  351. package/dist/main.js +228 -34
  352. package/package.json +2 -2
  353. package/dist/assets/components/internal/base-button/base-button.types.ts +0 -1
  354. package/dist/assets/components/internal/base-button/base-button.vue +0 -1
  355. package/dist/assets/components/internal/button-actions-with-menu/button-actions-with-menu.stories.ts +0 -1
  356. package/dist/assets/components/internal/button-actions-with-menu/button-actions-with-menu.types.ts +0 -1
  357. package/dist/assets/components/internal/button-actions-with-menu/button-actions-with-menu.vue +0 -1
  358. package/dist/assets/components/internal/calendar/calendar.stories.ts +0 -1
  359. package/dist/assets/components/internal/calendar/calendar.types.ts +0 -1
  360. package/dist/assets/components/internal/calendar/calendar.vue +0 -1
  361. package/dist/assets/components/internal/calendar/components/calendar-month/calendar-month.stories.ts +0 -1
  362. package/dist/assets/components/internal/calendar/components/calendar-month/calendar-month.types.ts +0 -1
  363. package/dist/assets/components/internal/calendar/components/calendar-month/calendar-month.vue +0 -1
  364. package/dist/assets/components/internal/calendar/components/calendar-month/components/calendar-month-day/__test__/calendar-month-day-stub.vue +0 -1
  365. package/dist/assets/components/internal/calendar/components/calendar-month/components/calendar-month-day/calendar-month-day.stories.ts +0 -1
  366. package/dist/assets/components/internal/calendar/components/calendar-month/components/calendar-month-day/calendar-month-day.types.ts +0 -1
  367. package/dist/assets/components/internal/calendar/components/calendar-month/components/calendar-month-day/calendar-month-day.vue +0 -1
  368. package/dist/assets/components/internal/calendar/components/calendar-month/composables/granular-min-max-date.types.ts +0 -1
  369. package/dist/assets/components/internal/calendar/components/calendar-year/calendar-year.types.ts +0 -1
  370. package/dist/assets/components/internal/calendar/components/calendar-year/calendar-year.vue +0 -1
  371. package/dist/assets/components/internal/calendar/components/calendar-year/components/calendar-year-month/__test__/calendar-year-month-stub.vue +0 -1
  372. package/dist/assets/components/internal/calendar/components/calendar-year/components/calendar-year-month/calendar-year-month.types.ts +0 -1
  373. package/dist/assets/components/internal/calendar/components/calendar-year/components/calendar-year-month/calendar-year-month.vue +0 -1
  374. package/dist/assets/components/internal/calendar/components/calendar-year-selector/calendar-year-selector.types.ts +0 -1
  375. package/dist/assets/components/internal/calendar/components/calendar-year-selector/calendar-year-selector.vue +0 -1
  376. package/dist/assets/components/internal/calendar/composables/use-granularity-adjustments.types.ts +0 -1
  377. package/dist/assets/components/internal/calendar/composables/use-range-pane.types.ts +0 -1
  378. package/dist/assets/components/internal/checkbox-input/checkbox-input.stories.ts +0 -1
  379. package/dist/assets/components/internal/checkbox-input/checkbox-input.types.ts +0 -1
  380. package/dist/assets/components/internal/checkbox-input/checkbox-input.vue +0 -1
  381. package/dist/assets/components/internal/controls-group/controls-group.vue +0 -1
  382. package/dist/assets/components/internal/copy/copy.docs.mdx +0 -43
  383. package/dist/assets/components/internal/copy/copy.stories.ts +0 -1
  384. package/dist/assets/components/internal/copy/copy.types.ts +0 -1
  385. package/dist/assets/components/internal/copy/copy.vue +0 -1
  386. package/dist/assets/components/internal/decorative-checkbox/decorative-checkbox.vue +0 -1
  387. package/dist/assets/components/internal/dialog-page/dialog-page.types.ts +0 -1
  388. package/dist/assets/components/internal/dialog-page/dialog-page.vue +0 -1
  389. package/dist/assets/components/internal/error-message/error-message.vue +0 -1
  390. package/dist/assets/components/internal/field-label/field-label.vue +0 -1
  391. package/dist/assets/components/internal/fixed-scroller/fixed-scroller.docs.mdx +0 -21
  392. package/dist/assets/components/internal/fixed-scroller/fixed-scroller.stories.ts +0 -1
  393. package/dist/assets/components/internal/fixed-scroller/fixed-scroller.vue +0 -1
  394. package/dist/assets/components/internal/footer-actions/footer-actions.vue +0 -1
  395. package/dist/assets/components/internal/grid-layout/grid-layout.types.ts +0 -1
  396. package/dist/assets/components/internal/grid-layout/grid-layout.vue +0 -1
  397. package/dist/assets/components/internal/header-meta/header-meta.types.ts +0 -1
  398. package/dist/assets/components/internal/header-meta/header-meta.vue +0 -1
  399. package/dist/assets/components/internal/info-icon-with-popover/info-icon-with-popover.vue +0 -1
  400. package/dist/assets/components/internal/listbox/components/listbox-lazy-load/listbox-lazy-load.types.ts +0 -1
  401. package/dist/assets/components/internal/listbox/components/listbox-lazy-load/listbox-lazy-load.vue +0 -1
  402. package/dist/assets/components/internal/listbox/components/listbox-multi-select/components/listbox-multi-select-options/components/listbox-multi-select-category/listbox-multi-select-category.types.ts +0 -1
  403. package/dist/assets/components/internal/listbox/components/listbox-multi-select/components/listbox-multi-select-options/components/listbox-multi-select-category/listbox-multi-select-category.vue +0 -1
  404. package/dist/assets/components/internal/listbox/components/listbox-multi-select/components/listbox-multi-select-options/components/listbox-multi-select-nested-lazy-load/listbox-multi-select-nested-lazy-load.types.ts +0 -1
  405. package/dist/assets/components/internal/listbox/components/listbox-multi-select/components/listbox-multi-select-options/components/listbox-multi-select-nested-lazy-load/listbox-multi-select-nested-lazy-load.vue +0 -1
  406. package/dist/assets/components/internal/listbox/components/listbox-multi-select/components/listbox-multi-select-options/listbox-multi-select-options.types.ts +0 -1
  407. package/dist/assets/components/internal/listbox/components/listbox-multi-select/components/listbox-multi-select-options/listbox-multi-select-options.vue +0 -1
  408. package/dist/assets/components/internal/listbox/components/listbox-multi-select/listbox-multi-select.types.ts +0 -1
  409. package/dist/assets/components/internal/listbox/components/listbox-multi-select/listbox-multi-select.vue +0 -1
  410. package/dist/assets/components/internal/listbox/components/listbox-option/listbox-option.vue +0 -1
  411. package/dist/assets/components/internal/listbox/components/listbox-option-tag/listbox-option-tag.vue +0 -1
  412. package/dist/assets/components/internal/listbox/components/listbox-single-select/components/listbox-single-select-category/listbox-single-select-category.vue +0 -1
  413. package/dist/assets/components/internal/listbox/components/listbox-single-select/listbox-single-select.vue +0 -1
  414. package/dist/assets/components/internal/listbox/components/listbox-single-select-option/listbox-single-select-option.vue +0 -1
  415. package/dist/assets/components/internal/listbox/listbox.stories.ts +0 -1
  416. package/dist/assets/components/internal/listbox/listbox.types.ts +0 -1
  417. package/dist/assets/components/internal/listbox/listbox.vue +0 -1
  418. package/dist/assets/components/internal/radio-input/radio-input.stories.ts +0 -1
  419. package/dist/assets/components/internal/radio-input/radio-input.types.ts +0 -1
  420. package/dist/assets/components/internal/radio-input/radio-input.vue +0 -1
  421. package/dist/assets/components/internal/teleport/teleport.types.ts +0 -1
  422. package/dist/assets/components/internal/teleport/teleport.vue +0 -1
  423. package/dist/assets/components/internal/tooltip/tooltip.test.vue +0 -1
  424. package/dist/assets/components/internal/tooltip/tooltip.types.ts +0 -1
  425. package/dist/assets/components/internal/tooltip/tooltip.vue +0 -1
  426. package/dist/assets/composables/use-form-validate-zod-4/use-form.types.ts +0 -1
  427. package/dist/assets/composables/use-numeric-input/use-numeric-input.types.ts +0 -1
  428. package/dist/assets/composables/use-section-navigation-keyboard/use-section-navigation-keyboard.types.ts +0 -1
  429. package/dist/assets/composables/use-virtual-list/use-virtual-list.types.ts +0 -1
@@ -19,14 +19,14 @@ A checkbox group component allows to group together checkboxes that are related
19
19
 
20
20
  Use a checkbox group to:
21
21
 
22
- - Group checkboxes related to each other.
22
+ - Group checkboxes related to each other.
23
23
 
24
24
  ### Do not use
25
25
 
26
26
  Don't use a checkbox group if:
27
27
 
28
- - You only have one checkbox. In that case, use the `checkbox` component instead.
29
- - The checkboxes in the group are not related to each other - use singular checkboxes instead.
28
+ - You only have one checkbox. In that case, use the `checkbox` component instead.
29
+ - The checkboxes in the group are not related to each other - use singular checkboxes instead.
30
30
 
31
31
  ### Guidelines
32
32
 
@@ -40,9 +40,9 @@ If there is not enough space, the checkboxes that overflow the available space w
40
40
 
41
41
  It can take up the following values:
42
42
 
43
- - `'vertical'`: displays the checkboxes in the group with a vertical layout. It's the default option.
44
- - `'horizontal'`: displays the checkboxes in the group with a horizontal layout. If not enough space is available, the
45
- corresponding checkboxes will go on a new line.
43
+ - `'vertical'`: displays the checkboxes in the group with a vertical layout. It's the default option.
44
+ - `'horizontal'`: displays the checkboxes in the group with a horizontal layout. If not enough space is available, the
45
+ corresponding checkboxes will go on a new line.
46
46
 
47
47
  ## Modifiers
48
48
 
@@ -64,12 +64,7 @@ prop.
64
64
 
65
65
  ### Error
66
66
 
67
- There are two properties that control the error state of `checkbox`s within `checkbox-group`:
68
-
69
- - `errorMessage`: renders all checkboxes with an error state and displays an error message below
70
- - `hasError`: renders all checkboxes with an error state
71
-
72
- `hasError` is deprecated and will be removed in the near future, so please use `errorMessage`.
67
+ The `errorMessage` prop renders all checkboxes with an error state and displays an error message below.
73
68
 
74
69
  ### Hide Label
75
70
 
@@ -130,5 +125,5 @@ the page. A detailed list of keyboard interactions is provided in the table belo
130
125
 
131
126
  ## Resources
132
127
 
133
- - [Figma link](https://www.figma.com/file/uLabwF3243jdMDsNSP7U9I/Bento---Components?node-id=1934-27878&t=ir5bsJdP6TgVgXy0-0)
134
- - [WAI-ARIA guidelines for grouping controls](https://www.w3.org/WAI/tutorials/forms/grouping/)
128
+ - [Figma link](https://www.figma.com/file/uLabwF3243jdMDsNSP7U9I/Bento---Components?node-id=1934-27878&t=ir5bsJdP6TgVgXy0-0)
129
+ - [WAI-ARIA guidelines for grouping controls](https://www.w3.org/WAI/tutorials/forms/grouping/)
@@ -1 +1 @@
1
- import { action } from '@storybook/addon-actions'; import { storybookDocsParameter } from '@/utils/ts/storybook'; import { ref } from 'vue'; import { BentoCheckboxGroupVariant } from '@/components/checkbox/components/checkbox-group/checkbox-group.types'; import { BentoCheckboxEvent } from '@/components/checkbox/checkbox.types'; import { isVue2 } from 'vue-demi'; import { type Meta, type StoryObj } from '@storybook/vue'; import BentoCheckboxGroup from './checkbox-group.vue'; import { BentoTag } from '@/components/tag'; const GROUP_LABEL = 'Group label'; const DESCRIPTION = 'Optional description'; const CHECKBOX_DEFAULT_LABEL = 'Label text'; const CHECKBOX_DEFAULT_SUB_LABEL = 'Sub label text'; const ERROR_MESSAGE = 'Error message text'; const ITEMS = [ { value: 1, label: CHECKBOX_DEFAULT_LABEL }, { value: 2, label: `${CHECKBOX_DEFAULT_LABEL} 2`, description: CHECKBOX_DEFAULT_SUB_LABEL }, { value: 3, label: 'Readonly checkbox', readonly: true }, { value: 4, label: 'Error message checkbox', errorMessage: ERROR_MESSAGE }, ]; export default { title: 'Checkbox/Checkbox Group', component: BentoCheckboxGroup, argTypes: { variant: { options: Object.values(BentoCheckboxGroupVariant), mapping: BentoCheckboxGroupVariant, control: { type: 'select', }, }, items: { table: { type: { summary: 'BentoCheckboxGroupItems' }, }, }, disabled: { control: { type: 'boolean', }, }, hasError: { control: { type: 'boolean' }, table: { category: 'Deprecated' }, }, [BentoCheckboxEvent.UPDATE]: { name: BentoCheckboxEvent.UPDATE, defaultValue: '', description: 'Input event handler.', table: { type: { summary: '(newGroupValue: Array<number | string | null>) => void' }, }, control: { disable: true }, }, [BentoCheckboxEvent.INPUT]: { name: BentoCheckboxEvent.INPUT, defaultValue: '', description: 'Deprecated since version 2.0. Use `v-model` or `update:model-value` instead', table: { category: 'Deprecated', type: { summary: '(newGroupValue: Array<number | string | null>) => void' }, }, control: { disable: true }, }, }, } as Meta; type Story = StoryObj<typeof BentoCheckboxGroup>; const defaultCode = ` <template> <!-- With model-value --> <bento-checkbox-group :items="[ { value: 1, label: 'Label text' }, { value: 2, label: 'Label text 2', description: 'Sub label text' }, ]" :model-value="yourModelValueVariable" label="Group label" description="Optional description" @update:model-value="yourUpdateHandler" /> <!-- With v-model Vue2/Vue3 --> <bento-checkbox-group :items="[ { value: 1, label: 'Label text' }, { value: 2, label: 'Label text 2', description: 'Sub label text' }, ]" v-model="yourModelValueVariable" label="Group label" description="Optional description" /> </template> <script setup lang="ts"> import { BentoCheckboxGroup } from '@adyen/bento-vue2' const yourModelValueVariable = ref<Array<number>>([1]); const yourUpdateHandler = (newGroupValue: Array<number>) => { yourModelValueVariable.value = newGroupValue; } </script> `; export const Default: Story = { render: (_args, { argTypes }) => ({ components: { BentoCheckboxGroup }, props: Object.keys(argTypes), template: ` <div> <bento-checkbox-group v-bind="args" :model-value="selectedValue" @update:model-value="clickedAction" /> </div> `, setup(props) { const selectedValue = ref(undefined); const clickedAction = value => { selectedValue.value = value; action(BentoCheckboxEvent.UPDATE)(value); }; return { // Values selectedValue, args: isVue2 ? props : _args, // Events clickedAction, }; }, }), args: { items: ITEMS, variant: 'vertical', label: GROUP_LABEL, description: DESCRIPTION, }, parameters: storybookDocsParameter(defaultCode), }; export const Slots: Story = { render: (_args, { argTypes }) => ({ components: { BentoCheckboxGroup, BentoTag }, props: Object.keys(argTypes), template: ` <div> <bento-checkbox-group v-bind="args" :model-value="selectedValue" @update:model-value="clickedAction" > <template #content="{ value }"> <bento-tag :label="contentString(value)"/> </template> </bento-checkbox-group> </div> `, setup(props) { const selectedValue = ref([ITEMS[1].value]); const clickedAction = value => { selectedValue.value = value; action(BentoCheckboxEvent.UPDATE)(value); }; const contentString = value => `Slot for value ${value}`; return { // Values selectedValue, args: isVue2 ? props : _args, // Methods contentString, // Events clickedAction, }; }, }), args: { items: ITEMS, variant: 'vertical', label: GROUP_LABEL, description: DESCRIPTION, }, parameters: storybookDocsParameter(` <template> <!-- With model-value --> <bento-checkbox-group :items="[ { value: 1, label: 'Label text' }, { value: 2, label: 'Label text 2', description: 'Sub label text' }, ]" :model-value="yourModelValueVariable" label="Group label" description="Optional description" @update:model-value="yourUpdateHandler" > <template #content="{ value }"> <bento-tag :label="value" /> </template> </bento-checkbox-group> <!-- With v-model Vue2/Vue3 --> <bento-checkbox-group :items="[ { value: 1, label: 'Label text' }, { value: 2, label: 'Label text 2', description: 'Sub label text' }, ]" v-model="yourModelValueVariable" label="Group label" description="Optional description" > <template #content="{ value }"> <bento-tag :label="value" /> </template> </bento-checkbox-group> </template> <script setup lang="ts"> import { BentoCheckboxGroup } from '@adyen/bento-vue2' const yourModelValueVariable = ref<Array<number>>([1]); const yourUpdateHandler = (newGroupValue: Array<number>) => { yourModelValueVariable.value = newGroupValue; } </script> `), }; const withTagCode = ` <template> <!-- With model-value --> <bento-checkbox-group :items="[ { value: 1, label: 'Label text', tag: { label: 'Recommended' } }, { value: 2, label: 'Label text 2', description: 'Sub label text' }, ]" :model-value="yourModelValueVariable" label="Group label" description="Optional description" @update:model-value="yourUpdateHandler" /> <!-- With v-model Vue2/Vue3 --> <bento-checkbox-group :items="[ { value: 1, label: 'Label text', tag: { label: 'Recommended' }, { value: 2, label: 'Label text 2', description: 'Sub label text' }, ]" v-model="yourModelValueVariable" label="Group label" description="Optional description" /> </template> <script setup lang="ts"> import { BentoCheckboxGroup } from '@adyen/bento-vue2' const yourModelValueVariable = ref<Array<number>>([1]); const yourUpdateHandler = (newGroupValue: Array<number>) => { yourModelValueVariable.value = newGroupValue; } </script> `; export const WithTag: Story = { ...Default, args: { ...Default.args, items: [ { value: 1, label: CHECKBOX_DEFAULT_LABEL, tag: { label: 'Recommended' } }, { value: 2, label: `${CHECKBOX_DEFAULT_LABEL} 2`, description: CHECKBOX_DEFAULT_SUB_LABEL }, { value: 3, label: 'Readonly checkbox', readonly: true }, { value: 4, label: 'Error message checkbox', errorMessage: ERROR_MESSAGE }, ], }, parameters: storybookDocsParameter(withTagCode), };
1
+ import { action } from '@storybook/addon-actions'; import { storybookDocsParameter } from '@/utils/ts/storybook'; import { ref } from 'vue'; import { BentoCheckboxGroupVariant } from '@/components/checkbox/components/checkbox-group/checkbox-group.types'; import { BentoCheckboxEvent } from '@/components/checkbox/checkbox.types'; import { isVue2 } from 'vue-demi'; import { type Meta, type StoryObj } from '@storybook/vue'; import BentoCheckboxGroup from './checkbox-group.vue'; import { BentoTag } from '@/components/tag'; const CheckboxGroupDefault = "<template>\n <div>\n <!-- With model-value -->\n <bento-checkbox-group\n description=\"Optional description\"\n :items=\"items\"\n label=\"Group label\"\n :model-value=\"selectedValue\"\n @update:model-value=\"selectedValue = $event\"\n />\n\n <!-- With v-model in Vue 2 and Vue 3 -->\n <bento-checkbox-group\n v-model=\"selectedValue\"\n description=\"Optional description\"\n :items=\"items\"\n label=\"Group label\"\n />\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { ref } from 'vue';\n import { BentoCheckboxGroup, type BentoCheckboxGroupItems } from '@adyen/bento-vue2';\n\n const selectedValue = ref<Array<number | string | null>>([]);\n const items: BentoCheckboxGroupItems = [\n { value: 1, label: 'Label text' },\n { value: 2, label: 'Label text 2', description: 'Sub label text' },\n { value: 3, label: 'Readonly checkbox', readonly: true },\n { value: 4, label: 'Error message checkbox', errorMessage: 'Error message text' },\n ];\n</script>\n"; const CheckboxGroupSlots = "<template>\n <bento-checkbox-group v-model=\"selectedValue\" description=\"Optional description\" :items=\"items\" label=\"Group label\">\n <template #content=\"{ value }\">\n <bento-tag :label=\"`Slot for value ${value}`\" />\n </template>\n </bento-checkbox-group>\n</template>\n\n<script setup lang=\"ts\">\n import { ref } from 'vue';\n import { BentoCheckboxGroup, type BentoCheckboxGroupItems, BentoTag } from '@adyen/bento-vue2';\n\n const selectedValue = ref<Array<number | string | null>>([2]);\n const items: BentoCheckboxGroupItems = [\n { value: 1, label: 'Label text' },\n { value: 2, label: 'Label text 2', description: 'Sub label text' },\n { value: 3, label: 'Readonly checkbox', readonly: true },\n { value: 4, label: 'Error message checkbox', errorMessage: 'Error message text' },\n ];\n</script>\n"; const CheckboxGroupWithTag = "<template>\n <bento-checkbox-group\n v-model=\"selectedValue\"\n description=\"Optional description\"\n :items=\"items\"\n label=\"Group label\"\n />\n</template>\n\n<script setup lang=\"ts\">\n import { ref } from 'vue';\n import { BentoCheckboxGroup, type BentoCheckboxGroupItems } from '@adyen/bento-vue2';\n\n const selectedValue = ref<Array<number | string | null>>([]);\n const items: BentoCheckboxGroupItems = [\n { value: 1, label: 'Label text', tag: { label: 'Recommended' } },\n { value: 2, label: 'Label text 2', description: 'Sub label text' },\n { value: 3, label: 'Readonly checkbox', readonly: true },\n { value: 4, label: 'Error message checkbox', errorMessage: 'Error message text' },\n ];\n</script>\n"; const GROUP_LABEL = 'Group label'; const DESCRIPTION = 'Optional description'; const CHECKBOX_DEFAULT_LABEL = 'Label text'; const CHECKBOX_DEFAULT_SUB_LABEL = 'Sub label text'; const ERROR_MESSAGE = 'Error message text'; const ITEMS = [ { value: 1, label: CHECKBOX_DEFAULT_LABEL }, { value: 2, label: `${CHECKBOX_DEFAULT_LABEL} 2`, description: CHECKBOX_DEFAULT_SUB_LABEL }, { value: 3, label: 'Readonly checkbox', readonly: true }, { value: 4, label: 'Error message checkbox', errorMessage: ERROR_MESSAGE }, ]; export default { title: 'Checkbox/Checkbox Group', component: BentoCheckboxGroup, argTypes: { variant: { options: Object.values(BentoCheckboxGroupVariant), mapping: BentoCheckboxGroupVariant, control: { type: 'select', }, }, items: { table: { type: { summary: 'BentoCheckboxGroupItems' }, }, }, disabled: { control: { type: 'boolean', }, }, [BentoCheckboxEvent.UPDATE]: { name: BentoCheckboxEvent.UPDATE, defaultValue: '', description: 'Input event handler.', table: { type: { summary: '(newGroupValue: Array<number | string | null>) => void' }, }, control: { disable: true }, }, }, } as Meta; type Story = StoryObj<typeof BentoCheckboxGroup>; export const Default: Story = { render: (_args, { argTypes }) => ({ components: { BentoCheckboxGroup }, props: Object.keys(argTypes), template: ` <div> <bento-checkbox-group v-bind="args" :model-value="selectedValue" @update:model-value="clickedAction" /> </div> `, setup(props) { const selectedValue = ref(undefined); const clickedAction = value => { selectedValue.value = value; action(BentoCheckboxEvent.UPDATE)(value); }; return { // Values selectedValue, args: isVue2 ? props : _args, // Events clickedAction, }; }, }), args: { items: ITEMS, variant: 'vertical', label: GROUP_LABEL, description: DESCRIPTION, }, parameters: storybookDocsParameter(CheckboxGroupDefault), }; export const Slots: Story = { render: (_args, { argTypes }) => ({ components: { BentoCheckboxGroup, BentoTag }, props: Object.keys(argTypes), template: ` <div> <bento-checkbox-group v-bind="args" :model-value="selectedValue" @update:model-value="clickedAction" > <template #content="{ value }"> <bento-tag :label="contentString(value)"/> </template> </bento-checkbox-group> </div> `, setup(props) { const selectedValue = ref([ITEMS[1].value]); const clickedAction = value => { selectedValue.value = value; action(BentoCheckboxEvent.UPDATE)(value); }; const contentString = value => `Slot for value ${value}`; return { // Values selectedValue, args: isVue2 ? props : _args, // Methods contentString, // Events clickedAction, }; }, }), args: { items: ITEMS, variant: 'vertical', label: GROUP_LABEL, description: DESCRIPTION, }, parameters: storybookDocsParameter(CheckboxGroupSlots), }; export const WithTag: Story = { ...Default, args: { ...Default.args, items: [ { value: 1, label: CHECKBOX_DEFAULT_LABEL, tag: { label: 'Recommended' } }, { value: 2, label: `${CHECKBOX_DEFAULT_LABEL} 2`, description: CHECKBOX_DEFAULT_SUB_LABEL }, { value: 3, label: 'Readonly checkbox', readonly: true }, { value: 4, label: 'Error message checkbox', errorMessage: ERROR_MESSAGE }, ], }, parameters: storybookDocsParameter(CheckboxGroupWithTag), };
@@ -1 +1 @@
1
- import { type FormFieldEmits } from '../../../../types/form-field'; import type { BentoCheckboxTag } from '../../checkbox.types'; /** * @deprecated Since v2.0.0. Use string literal instead. */ export enum BentoCheckboxGroupVariant { HORIZONTAL = 'horizontal', VERTICAL = 'vertical', } export interface BentoCheckboxGroupItem { value: string | number; label: string; description?: string; disabled?: boolean; hasError?: boolean; errorMessage?: string; readonly?: boolean; tag?: BentoCheckboxTag; } export type BentoCheckboxGroupItems = Array<BentoCheckboxGroupItem>; export type BentoCheckboxGroupEmits = FormFieldEmits<any>;
1
+ import { type FormFieldEmits } from '../../../../types/form-field'; import type { BentoCheckboxTag } from '../../checkbox.types'; /** * @deprecated Since v3.0.0. Use string literal instead. */ export enum BentoCheckboxGroupVariant { HORIZONTAL = 'horizontal', VERTICAL = 'vertical', } export interface BentoCheckboxGroupItem { value: string | number; label: string; description?: string; disabled?: boolean; hasError?: boolean; errorMessage?: string; readonly?: boolean; tag?: BentoCheckboxTag; } export type BentoCheckboxGroupItems = Array<BentoCheckboxGroupItem>; export type BentoCheckboxGroupEmits = FormFieldEmits<any>;
@@ -1 +1 @@
1
- <template> <div class="b-checkbox-group"> <controls-group class="b-checkbox-group__checkboxes" :aria-describedby="shouldShowGroupErrorMessage ? errorId : ''" :aria-required="required" component-name="bento-checkbox-group" :class="conditionalClasses" :description="description" :disabled="disabled" :form="formId" :hide-label="hideLabel" :label="label" :optional="optional" :required="required" :tooltip-text="tooltipText" > <bento-checkbox v-for="item in items" :key="item.value" :model-value="inputValue" :value="item.value" :disabled="disabled || item.disabled" :has-error="shouldShowGroupError || item.hasError" :error-message="shouldShowGroupError ? null : item.errorMessage" :readonly="isReadOnly || item.readonly" :tag="item.tag" @update:model-value="onModelValueUpdate" > <template #default>{{ item.label }}</template> <template v-if="item.description" #description>{{ item.description }}</template> <template v-if="hasContentSlot('content')" #content> <slot name="content" v-bind="item"></slot> </template> </bento-checkbox> </controls-group> <error-message v-if="shouldShowGroupErrorMessage" :id="errorId" :error-message="errorMessage" class="b-checkbox-group__error-message" /> </div> </template> <script setup lang="ts"> import { computed, onMounted, type PropType, ref, toRef, useSlots, watch } from 'vue'; import { ControlsGroup } from '@/components/internal/controls-group'; import { ErrorMessage } from '@/components/internal/error-message'; import { type BentoCheckboxGroupEmits, type BentoCheckboxGroupItems, BentoCheckboxGroupVariant, } from './checkbox-group.types'; import BentoCheckbox from '@/components/checkbox/checkbox.vue'; import { generateUid } from '@/core/utils/ts'; import { deprecate } from '@/utils/ts/deprecate'; import { useFormLayoutFieldLoading } from '@/composables/use-form-layout-loading/use-form-layout-loading'; import { useFormFieldEmits } from '@/utils/ts/form-field/form-field'; const props = defineProps({ /** * Descriptive supporting text visbile underneath the label. */ description: { type: String, default: null }, /** * If set to true, renders all checkboxes in the group in a disabled state. */ disabled: { type: Boolean, default: false }, /** * Renders all checkboxes in an error state with an error message. */ errorMessage: { type: String, default: null }, /** * The form id the checkbox group is associated with. Defaults to null, as a checkbox group can also be used standalone. */ formId: { type: String, default: null }, /** * If set to true, renders all checkboxes in the group in an error state. * * @deprecated Since v2.0.0. Use `errorMessage` instead. */ hasError: { type: Boolean, default: false }, /** * Shows/hides the group label. */ hideLabel: { type: Boolean, default: null }, /** * The checkbox group's items. */ items: { type: Array as PropType<BentoCheckboxGroupItems>, required: true }, /** * The name associated with the group. Required for accessibility purposes. */ label: { type: String, required: true }, /** * Determines the initially selected value of the group. Corresponds to the BentoCheckboxButtonItem's value. * Defaults to no value selected. */ modelValue: { type: Array as PropType<Array<number | string | null>>, default: () => [] }, /** * Indicates the field is optional. */ optional: { type: Boolean, default: false }, /** * If set to true, renders all checkboxes in the group in a readonly state. */ readonly: { type: Boolean, default: false }, /** * Indicates the field is required. */ required: { type: Boolean, default: false }, /** * Tooltip message. */ tooltipText: { type: String, default: null }, /** * The checkbox group's layout. It can be vertical or horizontal. Defaults to vertical. */ variant: { type: String as PropType<BentoCheckboxGroupVariant | `${BentoCheckboxGroupVariant}`>, default: BentoCheckboxGroupVariant.VERTICAL, validator: (value: BentoCheckboxGroupVariant) => Object.values(BentoCheckboxGroupVariant).includes(value), }, }); const emit = defineEmits<BentoCheckboxGroupEmits>(); const slots = useSlots(); const errorId = generateUid('error'); const { isReadOnly } = useFormLayoutFieldLoading(toRef(props, 'readonly')); const { emitValue } = useFormFieldEmits(emit); const shouldShowGroupError = computed( () => !props.disabled && !isReadOnly.value && (!!props.errorMessage || props.hasError) ); const shouldShowGroupErrorMessage = computed(() => !props.disabled && !isReadOnly.value && !!props.errorMessage); const conditionalClasses = computed(() => ({ 'b-checkbox-group__checkboxes--horizontal': props.variant === BentoCheckboxGroupVariant.HORIZONTAL, })); // Slots logic // Temporary, use-has-slots composable doesn't currently work for // vue3 named scoped slots const hasContentSlot = (name: string) => !!slots[name]; const shouldShowSlotsError = computed(() => hasContentSlot('content') && props.variant !== 'vertical'); watch( shouldShowSlotsError, newValue => { if (newValue) { throw new Error('The content slot is only available for the vertical checkbox group layout'); } }, { immediate: true } ); const inputValue = ref(props.modelValue); watch( () => props.modelValue, () => { inputValue.value = props.modelValue; } ); const onModelValueUpdate = (value: any) => { inputValue.value = value; emitValue(value); }; onMounted(() => { if (props.hasError) { deprecate( 'BentoCheckboxGroup "hasError" property', `Use the BentoCheckboxGroup "errorMessage" property instead to indicate that there is a modifier error. Having the field as "undefined" will hide/remove the error. <bento-checkbox-group errorMessage="Error message text" />`, '2.0.0' ); } }); </script> <script lang="ts"> const COMPONENT_NAME = 'bento-checkbox-group'; /** * A checkbox group component should be used whenever it is necessary to group a set of checkboxes that are related together * This component conforms to the official WAI-ARIA guidelines for grouping controls: https://www.w3.org/WAI/tutorials/forms/grouping/ * * import { BentoCheckboxGroup } from '@adyen/bento-vue2/'; * * export default { * components: { BentoCheckboxGroup }, * template: ` * <bento-checkbox-group * label="Your group label" * :items="[ * { value: 1, label: 'Your label' }, * { value: 2, label: 'Another label', description: 'Your sub label' }, * ]" * /> * ` * }; */ export default { name: COMPONENT_NAME, model: { prop: 'modelValue' }, }; </script> <style lang="scss" scoped src="./checkbox-group.scss" />
1
+ <template> <div class="b-checkbox-group"> <controls-group class="b-checkbox-group__checkboxes" :aria-describedby="shouldShowGroupError ? errorId : ''" :aria-required="required" component-name="bento-checkbox-group" :class="conditionalClasses" :description="description" :disabled="disabled" :form="formId" :hide-label="hideLabel" :label="label" :optional="optional" :required="required" :tooltip-text="tooltipText" > <bento-checkbox v-for="item in items" :key="item.value" :model-value="inputValue" :value="item.value" :disabled="disabled || item.disabled" :has-error="shouldShowGroupError || item.hasError" :error-message="shouldShowGroupError ? null : item.errorMessage" :readonly="isReadOnly || item.readonly" :tag="item.tag" @update:model-value="onModelValueUpdate" > <template #default>{{ item.label }}</template> <template v-if="item.description" #description>{{ item.description }}</template> <template v-if="hasContentSlot('content')" #content> <slot name="content" v-bind="item"></slot> </template> </bento-checkbox> </controls-group> <error-message v-if="shouldShowGroupError" :id="errorId" :error-message="errorMessage" class="b-checkbox-group__error-message" /> </div> </template> <script setup lang="ts"> import { computed, type PropType, ref, toRef, useSlots, watch } from 'vue'; import { ControlsGroup } from '@/components/internal/controls-group'; import { ErrorMessage } from '@/components/internal/error-message'; import { type BentoCheckboxGroupEmits, type BentoCheckboxGroupItems, BentoCheckboxGroupVariant, } from './checkbox-group.types'; import BentoCheckbox from '@/components/checkbox/checkbox.vue'; import { generateUid } from '@/utils/ts/generate-uid'; import { useFormLayoutFieldLoading } from '@/composables/use-form-layout-loading/use-form-layout-loading'; import { useFormFieldEmits } from '@/utils/ts/form-field/form-field'; const props = defineProps({ /** * Descriptive supporting text visbile underneath the label. */ description: { type: String, default: null }, /** * If set to true, renders all checkboxes in the group in a disabled state. */ disabled: { type: Boolean, default: false }, /** * Renders all checkboxes in an error state with an error message. */ errorMessage: { type: String, default: null }, /** * The form id the checkbox group is associated with. Defaults to null, as a checkbox group can also be used standalone. */ formId: { type: String, default: null }, /** * Shows/hides the group label. */ hideLabel: { type: Boolean, default: null }, /** * The checkbox group's items. */ items: { type: Array as PropType<BentoCheckboxGroupItems>, required: true }, /** * The name associated with the group. Required for accessibility purposes. */ label: { type: String, required: true }, /** * Determines the initially selected value of the group. Corresponds to the BentoCheckboxButtonItem's value. * Defaults to no value selected. */ modelValue: { type: Array as PropType<Array<number | string | null>>, default: () => [] }, /** * Indicates the field is optional. */ optional: { type: Boolean, default: false }, /** * If set to true, renders all checkboxes in the group in a readonly state. */ readonly: { type: Boolean, default: false }, /** * Indicates the field is required. */ required: { type: Boolean, default: false }, /** * Tooltip message. */ tooltipText: { type: String, default: null }, /** * The checkbox group's layout. It can be vertical or horizontal. Defaults to vertical. */ variant: { type: String as PropType<BentoCheckboxGroupVariant | `${BentoCheckboxGroupVariant}`>, default: BentoCheckboxGroupVariant.VERTICAL, validator: (value: BentoCheckboxGroupVariant) => Object.values(BentoCheckboxGroupVariant).includes(value), }, }); const emit = defineEmits<BentoCheckboxGroupEmits>(); const slots = useSlots(); const errorId = generateUid('error'); const { isReadOnly } = useFormLayoutFieldLoading(toRef(props, 'readonly')); const { emitValue } = useFormFieldEmits(emit); const shouldShowGroupError = computed(() => !props.disabled && !isReadOnly.value && !!props.errorMessage); const conditionalClasses = computed(() => ({ 'b-checkbox-group__checkboxes--horizontal': props.variant === BentoCheckboxGroupVariant.HORIZONTAL, })); // Slots logic // Temporary, use-has-slots composable doesn't currently work for // vue3 named scoped slots const hasContentSlot = (name: string) => !!slots[name]; const shouldShowSlotsError = computed(() => hasContentSlot('content') && props.variant !== 'vertical'); watch( shouldShowSlotsError, newValue => { if (newValue) { throw new Error('The content slot is only available for the vertical checkbox group layout'); } }, { immediate: true } ); const inputValue = ref(props.modelValue); watch( () => props.modelValue, () => { inputValue.value = props.modelValue; } ); const onModelValueUpdate = (value: any) => { inputValue.value = value; emitValue(value); }; </script> <script lang="ts"> const COMPONENT_NAME = 'bento-checkbox-group'; /** * A checkbox group component should be used whenever it is necessary to group a set of checkboxes that are related together * This component conforms to the official WAI-ARIA guidelines for grouping controls: https://www.w3.org/WAI/tutorials/forms/grouping/ * * import { BentoCheckboxGroup } from '@adyen/bento-vue2/'; * * export default { * components: { BentoCheckboxGroup }, * template: ` * <bento-checkbox-group * label="Your group label" * :items="[ * { value: 1, label: 'Your label' }, * { value: 2, label: 'Another label', description: 'Your sub label' }, * ]" * /> * ` * }; */ export default { name: COMPONENT_NAME, model: { prop: 'modelValue', event: 'update:model-value' }, }; </script> <style lang="scss" scoped src="./checkbox-group.scss" />
@@ -1 +1 @@
1
- import { isVue2 } from 'vue-demi'; import { action } from '@storybook/addon-actions'; import { storybookDocsParameter } from '@/utils/ts/storybook'; import BentoChip from './chip.vue'; import type { Meta, StoryObj } from '@storybook/vue'; const meta: Meta = { title: 'Chip', component: BentoChip, }; export default meta; type Story = StoryObj<typeof BentoChip>; const defaultCode = ` <bento-chip label="Chip label" :character-limit="20" @click="removeChip" /> <script setup> const removeChip = () => { // whatever action you want to trigger when the user clicks the chip // should remove the chip } </script> `; export const Default: Story = { render: (_args, { argTypes }) => ({ components: { BentoChip }, props: Object.keys(argTypes), template: ` <bento-chip v-bind="args" @click="clickAction" /> `, setup(props) { return { // Values args: isVue2 ? props : _args, clickAction: action('click'), }; }, }), args: { label: 'Chip label', characterLimit: 20, condensed: false, disabled: false, readonly: false, error: false, }, parameters: storybookDocsParameter(defaultCode), };
1
+ import { isVue2 } from 'vue-demi'; import { action } from '@storybook/addon-actions'; import { storybookDocsParameter } from '@/utils/ts/storybook'; import { ref } from 'vue'; import BentoChip from './chip.vue'; import type { Meta, StoryObj } from '@storybook/vue'; const ChipDefault = "<template>\n <bento-chip v-if=\"isVisible\" :character-limit=\"20\" label=\"Chip label\" @click=\"removeChip\" />\n</template>\n\n<script setup lang=\"ts\">\n import { ref } from 'vue';\n import { BentoChip } from '@adyen/bento-vue2';\n\n const isVisible = ref(true);\n const removeChip = () => {\n // Trigger whichever action should remove the chip from your application state.\n isVisible.value = false;\n };\n</script>\n"; const meta: Meta = { title: 'Chip', component: BentoChip, }; export default meta; type Story = StoryObj<typeof BentoChip>; export const Default: Story = { render: (_args, { argTypes }) => ({ components: { BentoChip }, props: Object.keys(argTypes), template: ` <bento-chip v-if="isVisible" v-bind="args" @click="removeChip" /> `, setup(props) { const isVisible = ref(true); const removeChip = () => { action('click')(); isVisible.value = false; }; return { // Values args: isVue2 ? props : _args, isVisible, // Events removeChip, }; }, }), args: { label: 'Chip label', characterLimit: 20, condensed: false, disabled: false, readonly: false, error: false, }, parameters: storybookDocsParameter(ChipDefault), };
@@ -1 +1 @@
1
- <template> <base-button class="b-chip" :disabled="disabled" :class="conditionalClasses" @click="emit('click')"> <bento-typography el="span" :variant="computedTypographyVariant" class="b-chip__text"> {{ computedLabel }} </bento-typography> <template #iconRight><cross-small-icon :svg-title="t('remove')" class="b-chip__icon" /></template> </base-button> </template> <script setup lang="ts"> import { BaseButton } from '@/components/internal/base-button'; import { BentoTypography, type BentoTypographyVariant } from '@/components/typography'; import CrossSmallIcon from '@adyen/ui-assets-icons-16/vue/cross-small'; import { useI18n } from '@/utils/ts/i18n'; import { truncate } from '@/utils/ts/truncate'; import type { BentoChipProps } from './chip.types'; import messages from './messages.json'; import { computed } from 'vue'; type MessageSchema = (typeof messages)['en-US']; const props = withDefaults(defineProps<BentoChipProps>(), { disabled: false, readonly: false, error: false, condensed: false, characterLimit: null, }); const emit = defineEmits<{ /** * Emits when chip is clicked */ (e: 'click'): void; }>(); const { t } = useI18n<{ message: MessageSchema }>({ messages }); const computedLabel = computed(() => props.characterLimit ? truncate(props.label, props.characterLimit) : props.label ); const computedTypographyVariant = computed<`${BentoTypographyVariant}`>(() => props.condensed ? 'caption' : 'body' ); const conditionalClasses = computed(() => ({ 'b-chip--condensed': props.condensed, 'b-chip--readonly': props.readonly && !props.disabled, 'b-chip--error': props.error, })); </script> <script lang="ts"> /** * Chip is a dismissible tag-like component that can be used to display selected items, which may need to be removed by the user. * * @example * import { BentoChip } from '@adyen/bento-vue2'; * * export default { * components: { BentoChip }, * template: ` * <bento-chip * label="Label" * :character-limit="20" * condensed * @click="removeChip()" * * /> * ` * } */ export default { i18n: { messages } }; </script> <style lang="scss" scoped src="./chip.scss" />
1
+ <template> <base-button class="b-chip" :disabled="disabled" :class="conditionalClasses" @click="emit('click')"> <bento-typography el="span" :variant="computedTypographyVariant" class="b-chip__text"> {{ computedLabel }} </bento-typography> <template #iconRight><cross-small-icon :svg-title="t('remove')" class="b-chip__icon" /></template> </base-button> </template> <script setup lang="ts"> import { BaseButton } from '@/components/internal/base-button'; import { BentoTypography, type BentoTypographyVariant } from '@/components/typography'; import CrossSmallIcon from '@adyen/ui-assets-icons-16/vue/cross-small'; import { useI18n } from '@/utils/ts/i18n'; import { truncate } from '@/utils/ts/truncate'; import type { BentoChipProps } from './chip.types'; import messages from './messages.json'; import { computed } from 'vue'; type MessageSchema = (typeof messages)['en-US']; const props = withDefaults(defineProps<BentoChipProps>(), { disabled: false, readonly: false, error: false, condensed: false, characterLimit: null, }); const emit = defineEmits<{ /** * Emits when chip is clicked */ (e: 'click'): void; }>(); const { t } = useI18n<{ message: MessageSchema }>({ messages }); const computedLabel = computed(() => props.characterLimit ? truncate(props.label, props.characterLimit) : props.label ); const computedTypographyVariant = computed<`${BentoTypographyVariant}`>(() => props.condensed ? 'caption' : 'body' ); const conditionalClasses = computed(() => ({ 'b-chip--condensed': props.condensed, 'b-chip--readonly': props.readonly && !props.disabled, 'b-chip--error': props.error, })); </script> <script lang="ts"> /** * Chip is a dismissible tag-like component that can be used to display selected items, which may need to be removed by the user. * * @example * import { BentoChip } from '@adyen/bento-vue2'; * * export default { * components: { BentoChip }, * template: ` * <bento-chip * label="Label" * :character-limit="20" * condensed * @click="removeChip()" * * /> * ` * } */ export default { i18n: { messages }, name: 'bento-chip', }; </script> <style lang="scss" scoped src="./chip.scss" />
@@ -1 +1 @@
1
- import { action } from '@storybook/addon-actions'; import { BentoClickOutside } from '@/components/click-outside'; import { BentoClickOutsideDirective } from '@/directives/click-outside'; import { BentoTypography } from '@/components/typography'; import { BentoCard } from '@/components/card'; import { ref } from 'vue'; import { type Meta, type StoryObj } from '@storybook/vue'; import { isVue2 } from 'vue-demi'; import { storybookDocsParameter } from '@/utils/ts/storybook'; export default { title: 'Click outside', component: BentoClickOutside, argTypes: { // Events handler: { name: 'handler', defaultValue: '', description: 'Callback handler function to be called when a click outside the element is triggered.', table: { type: { summary: '(event: FocusEvent | PointerEvent) => void' } }, control: { disable: true }, }, }, } as Meta; type Story = StoryObj<typeof BentoClickOutside>; const DEFAULT_TITLE = 'This text is inside '; const defaultCode = ` <bento-click-outside @handler="clickOutsideHandlerMethod"> <div>Your content goes in here...</div> </bento-click-outside> `; export const ComponentDefault: Story = { render: (_args, { argTypes }) => ({ components: { BentoCard, BentoClickOutside, BentoTypography, }, props: Object.keys(argTypes), setup(props) { const totalClickOutsideCount = ref(0); const clickedAction = () => { totalClickOutsideCount.value += 1; return action('trigger'); }; return { // Values args: isVue2 ? props : _args, totalClickOutsideCount, // Events clickedAction, }; }, template: ` <div> <bento-click-outside @handler="clickedAction"> <bento-card> {{args.title}} </bento-card> </bento-click-outside> <bento-typography>Total click outside events triggered: {{totalClickOutsideCount}} </bento-typography> </div> `, }), args: { title: DEFAULT_TITLE, }, parameters: storybookDocsParameter(defaultCode), }; const directiveCode = ` <div v-bento-click-outside-directive="clickOutsideHandlerMethod"> <div>Your content goes in here...</div> </div> `; export const Directive: Story = { render: (_args, { argTypes }) => ({ components: { BentoCard, BentoTypography }, directives: { BentoClickOutsideDirective }, props: Object.keys(argTypes), setup(props) { const totalClickOutsideCount = ref(0); const clickedAction = () => { totalClickOutsideCount.value += 1; return action('trigger'); }; return { // Values totalClickOutsideCount, args: isVue2 ? props : _args, // Events clickedAction, }; }, template: ` <div> <div v-bento-click-outside-directive="clickedAction"> <bento-card> {{args.title}} </bento-card> </div> <bento-typography>Total click outside events triggered: {{totalClickOutsideCount}} </bento-typography> </div> `, }), args: { title: DEFAULT_TITLE, }, parameters: storybookDocsParameter(directiveCode), };
1
+ import { action } from '@storybook/addon-actions'; import { BentoClickOutside } from '@/components/click-outside'; import { BentoClickOutsideDirective } from '@/directives/click-outside'; import { BentoTypography } from '@/components/typography'; import { BentoCard } from '@/components/card'; import { ref } from 'vue'; import { type Meta, type StoryObj } from '@storybook/vue'; import { isVue2 } from 'vue-demi'; import { storybookDocsParameter } from '@/utils/ts/storybook'; const ClickOutsideComponentDefault = "<template>\n <div>\n <bento-click-outside @handler=\"clickedAction\">\n <bento-card>This text is inside</bento-card>\n </bento-click-outside>\n <bento-typography>Total click outside events triggered: {{ totalClickOutsideCount }}</bento-typography>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { ref } from 'vue';\n import { BentoCard, BentoClickOutside, BentoTypography } from '@adyen/bento-vue2';\n\n const totalClickOutsideCount = ref(0);\n const clickedAction = () => {\n totalClickOutsideCount.value += 1;\n };\n</script>\n"; const ClickOutsideDirective = "<template>\n <div>\n <div v-bento-click-outside-directive=\"clickedAction\">\n <bento-card>This text is inside</bento-card>\n </div>\n <bento-typography>Total click outside events triggered: {{ totalClickOutsideCount }}</bento-typography>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n import { ref } from 'vue';\n import {\n BentoCard,\n BentoTypography,\n BentoClickOutsideDirective as vBentoClickOutsideDirective,\n } from '@adyen/bento-vue2';\n\n const totalClickOutsideCount = ref(0);\n const clickedAction = () => {\n totalClickOutsideCount.value += 1;\n };\n</script>\n"; export default { title: 'Click outside', component: BentoClickOutside, argTypes: { // Events handler: { name: 'handler', defaultValue: '', description: 'Callback handler function to be called when a click outside the element is triggered.', table: { type: { summary: '(event: FocusEvent | PointerEvent) => void' } }, control: { disable: true }, }, }, } as Meta; type Story = StoryObj<typeof BentoClickOutside>; const DEFAULT_TITLE = 'This text is inside '; export const ComponentDefault: Story = { render: (_args, { argTypes }) => ({ components: { BentoCard, BentoClickOutside, BentoTypography, }, props: Object.keys(argTypes), setup(props) { const totalClickOutsideCount = ref(0); const clickedAction = () => { totalClickOutsideCount.value += 1; return action('trigger'); }; return { // Values args: isVue2 ? props : _args, totalClickOutsideCount, // Events clickedAction, }; }, template: ` <div> <bento-click-outside @handler="clickedAction"> <bento-card> {{args.title}} </bento-card> </bento-click-outside> <bento-typography>Total click outside events triggered: {{totalClickOutsideCount}} </bento-typography> </div> `, }), args: { title: DEFAULT_TITLE, }, parameters: storybookDocsParameter(ClickOutsideComponentDefault), }; export const Directive: Story = { render: (_args, { argTypes }) => ({ components: { BentoCard, BentoTypography }, directives: { BentoClickOutsideDirective }, props: Object.keys(argTypes), setup(props) { const totalClickOutsideCount = ref(0); const clickedAction = () => { totalClickOutsideCount.value += 1; return action('trigger'); }; return { // Values totalClickOutsideCount, args: isVue2 ? props : _args, // Events clickedAction, }; }, template: ` <div> <div v-bento-click-outside-directive="clickedAction"> <bento-card> {{args.title}} </bento-card> </div> <bento-typography>Total click outside events triggered: {{totalClickOutsideCount}} </bento-typography> </div> `, }), args: { title: DEFAULT_TITLE, }, parameters: storybookDocsParameter(ClickOutsideDirective), };
@@ -1 +1 @@
1
- /** * @deprecated Since v2.0.0. Use string literal instead. */ export enum BentoCodeSnippetVariant { INLINE = 'inline', SINGLELINE = 'singleline', MULTILINE = 'multiline', } /** * @deprecated Since v2.0.0. Use string literal instead. */ export enum BentoCodeSnippetSupportedLanguage { JSON = 'json', XML = 'xml', JAVA = 'java', JAVASCRIPT = 'javascript', PYTHON = 'python', CSV = 'csv', } export enum BentoCodeSnippetEvent { ACTION = 'action', CHANGE = 'change', } export interface BentoCodeSnippetProps { /** * Displays a button that when clicked will emit an action event * Leaves to the parent component the logic of what to do with it */ actionable?: boolean; /** * Displays a button that when clicked will emit a run event * Leaves to the parent component the logic of what to do with it */ actionableText?: string; /** * The code content */ content?: string; /** * Displays a button that can expand the codeblock into a modal to easily * view large blocks of code. */ expandable?: boolean; /** * Allows editing of the code-snippet content by the user */ editable?: boolean; /** * Language name for syntax highlighting rules */ lang?: BentoCodeSnippetSupportedLanguage | `${BentoCodeSnippetSupportedLanguage}`; /** * Label to show in the action-bar, describing the language */ langLabel?: string; /** * Toggles the loading indicator within the action bar */ loading?: boolean; /** * Defines the variant of code-snippet */ variant?: BentoCodeSnippetVariant | `${BentoCodeSnippetVariant}`; }
1
+ /** * @deprecated Since v3.0.0. Use string literal instead. */ export enum BentoCodeSnippetVariant { INLINE = 'inline', SINGLELINE = 'singleline', MULTILINE = 'multiline', } /** * @deprecated Since v3.0.0. Use string literal instead. */ export enum BentoCodeSnippetSupportedLanguage { JSON = 'json', XML = 'xml', JAVA = 'java', JAVASCRIPT = 'javascript', PYTHON = 'python', CSV = 'csv', } export enum BentoCodeSnippetEvent { ACTION = 'action', CHANGE = 'change', } export interface BentoCodeSnippetProps { /** * Displays a button that when clicked will emit an action event * Leaves to the parent component the logic of what to do with it */ actionable?: boolean; /** * Displays a button that when clicked will emit a run event * Leaves to the parent component the logic of what to do with it */ actionableText?: string; /** * The code content */ content?: string; /** * Displays a button that can expand the codeblock into a modal to easily * view large blocks of code. */ expandable?: boolean; /** * Allows editing of the code-snippet content by the user */ editable?: boolean; /** * Language name for syntax highlighting rules */ lang?: BentoCodeSnippetSupportedLanguage | `${BentoCodeSnippetSupportedLanguage}`; /** * Label to show in the action-bar, describing the language */ langLabel?: string; /** * Toggles the loading indicator within the action bar */ loading?: boolean; /** * Defines the variant of code-snippet */ variant?: BentoCodeSnippetVariant | `${BentoCodeSnippetVariant}`; }
@@ -1 +1 @@
1
- <template> <div class="b-code-snippet" :class="conditionalClasses"> <section v-if="!isInlineVariant" class="b-code-snippet__action-bar"> <div class="b-code-snippet__action-bar--start"> <bento-dropdown v-if="availableLanguages.length > 0" v-model="selectedLanguage" v-bind="$props" :disabled="availableLanguages.length === 1" :items="availableLanguages" class="b-code-snippet__language-picker" @input="handleChangeLanguage" /> <bento-typography el="span" stronger> {{ displayedLang }} </bento-typography> </div> <div class="b-code-snippet__action-bar--end"> <bento-loading-indicator v-if="loading" /> <copy v-if="currentContents !== null" class="b-structured-list__icon" :text="currentContents" /> <bento-button v-if="expandable" variant="tertiary" condensed :aria-label="t('expand')" @click="showModal = true" > <template #iconLeft> <expand-icon /> </template> </bento-button> <bento-button v-if="actionable" variant="primary" tertiary condensed @click="onActionClicked"> <template #iconLeft> <bento-typography el="span" class="b-code-snippet__action-button"> {{ runText }} </bento-typography> </template> </bento-button> </div> </section> <code v-if="content || editable" class="b-code-snippet__code-area"> <div ref="container" class="b-code-snippet__code-area-content" :class="codeAreaContentConditionalClasses" /> </code> <section v-else> <slot name="empty-state"> <!-- TODO: switch with empty-state component when ready --> <div class="b-code-snippet__empty-state">{{ t('nothingToDisplay') }}</div> </slot> </section> <base-modal v-if="expandable" class="b-code-snippet__modal" :hide-close-button="true" :custom-padding="'0px'" :is-dismissible="true" :is-open="showModal" size="large" @close-modal="showModal = false" > <template #content> <bento-code-snippet v-bind="{ ...$props, expandable: false }" /> </template> </base-modal> </div> </template> <script setup lang="ts"> import { computed, type HTMLAttributes, onMounted, ref, shallowRef, useAttrs, watch, watchEffect } from 'vue'; import { EditorView, highlightActiveLine, keymap, lineNumbers } from '@codemirror/view'; import { Compartment, EditorState } from '@codemirror/state'; import { history, indentWithTab } from '@codemirror/commands'; import { lightThemeHighlight } from './highlight'; import { getLangLoader, INDENT_SAME_AS_LINE_BEFORE } from './utils'; import { BentoDropdown } from '@/components/dropdown'; import { BentoButton } from '@/components/button'; import { BentoTypography } from '@/components/typography'; import { BentoLoadingIndicator } from '@/components/loading-indicator'; import { useI18n } from '@/utils/ts/i18n'; import { Copy } from '@/internal'; import { BentoCodeSnippetEvent, type BentoCodeSnippetProps, BentoCodeSnippetSupportedLanguage, BentoCodeSnippetVariant, } from './code-snippet.types'; import ExpandIcon from '@adyen/ui-assets-icons-16/vue/expand'; import BaseModal from '@/components/modal/components/base-modal/base-modal.vue'; import messages from './messages.json'; type MessageSchema = (typeof messages)['en-US']; const props = withDefaults(defineProps<BentoCodeSnippetProps>(), { actionable: false, actionableText: null, content: '', editable: false, expandable: false, lang: BentoCodeSnippetSupportedLanguage.JSON, langLabel: null, loading: false, variant: BentoCodeSnippetVariant.MULTILINE, }); const emit = defineEmits([BentoCodeSnippetEvent.ACTION, BentoCodeSnippetEvent.CHANGE]); const attrs = useAttrs(); const { t } = useI18n<{ message: MessageSchema }>({ messages }); // language const selectedLanguage = ref<string | null>(null); const availableLanguages = []; // TODO: implement // eslint-disable-next-line @typescript-eslint/no-empty-function const handleChangeLanguage = () => {}; const displayedLang = computed(() => props.langLabel ?? props.lang.toUpperCase()); const isInlineVariant = computed(() => props.variant === BentoCodeSnippetVariant.INLINE); const conditionalClasses = computed(() => ({ 'b-code-snippet--inline': isInlineVariant.value, 'b-code-snippet--scrollable': !isInlineVariant.value, })); const codeAreaContentConditionalClasses = computed(() => ({ 'b-code-snippet__code-area-content--editable': props.editable, })); const loadLang = getLangLoader(props.lang); const container = shallowRef<HTMLDivElement>(); const editor = shallowRef<EditorView>(); const languageConf = new Compartment(); const editorTheme = new Compartment(); const editorReadOnly = new Compartment(); const editorAttributes = new Compartment(); const currentContents = ref(null); const contentLength = ref(0); const runText = computed(() => props.actionableText || t('run')); onMounted(async () => { const language = await loadLang(); // alongside the updateListener plugin it acts as a watcher of changes to the editor state currentContents.value = props.content; const updateCurrentContents = ({ state }) => { currentContents.value = state.doc.toString(); }; const extensions = [ highlightActiveLine(), keymap.of([indentWithTab, INDENT_SAME_AS_LINE_BEFORE]), languageConf.of(language()), editorTheme.of(lightThemeHighlight(props.lang)), editorReadOnly.of(EditorState.readOnly.of(!props.editable)), editorAttributes.of( EditorView.contentAttributes.of({ 'aria-label': (attrs['aria-label'] as HTMLAttributes['aria-label']) ?? t('codeSnippet'), ...(!isInlineVariant.value && { tabindex: '0' }), }) ), EditorView.updateListener.of(content => updateCurrentContents(content)), ]; if (props.variant === 'multiline') { extensions.push([lineNumbers(), history()]); } const state = EditorState.create({ doc: props.content, extensions: [...extensions], }); contentLength.value = state.doc.length; editor.value = new EditorView({ state, parent: container.value, }); }); watch( () => props.content, () => { if (props.content !== currentContents.value) { const upcomingContentLength = props.content.length; editor.value.dispatch({ changes: { from: 0, to: contentLength.value, insert: props.content, }, }); contentLength.value = upcomingContentLength; } } ); const onActionClicked = () => { emit(BentoCodeSnippetEvent.ACTION, currentContents.value); }; watchEffect(() => { if (currentContents.value !== null) { emit(BentoCodeSnippetEvent.CHANGE, currentContents.value); } }); const showModal = ref(false); </script> <script lang="ts"> /** * A code-snippet is a container to display code in a readable way. * Come with added functionalities like syntax highlighting, editing and actioning the code * * @example * import { BentoCodeSnippet } from '@adyen/bento-vue2'; * * export default { * components: { BentoCodeSnippet }, * template: ` * <bento-code-snippet :variant="BentoCodeSnippetVariant.MULTILINE" content="{ example: 1234 }" /> * ` * } */ export default { i18n: { messages }, name: 'bento-code-snippet', }; </script> <style lang="scss" scoped src="./code-snippet.scss"></style>
1
+ <template> <div class="b-code-snippet" :class="conditionalClasses"> <section v-if="!isInlineVariant" class="b-code-snippet__action-bar"> <div class="b-code-snippet__action-bar--start"> <bento-dropdown v-if="availableLanguages.length > 0" v-model="selectedLanguage" v-bind="$props" :disabled="availableLanguages.length === 1" :items="availableLanguages" class="b-code-snippet__language-picker" /> <bento-typography el="span" stronger> {{ displayedLang }} </bento-typography> </div> <div class="b-code-snippet__action-bar--end"> <bento-loading-indicator v-if="loading" /> <copy v-if="currentContents !== null" class="b-structured-list__icon" :text="currentContents" /> <bento-button v-if="expandable" variant="tertiary" condensed :aria-label="t('expand')" @click="showModal = true" > <template #iconLeft> <expand-icon /> </template> </bento-button> <bento-button v-if="actionable" variant="primary" tertiary condensed @click="onActionClicked"> <template #iconLeft> <bento-typography el="span" class="b-code-snippet__action-button"> {{ runText }} </bento-typography> </template> </bento-button> </div> </section> <code v-if="content || editable" class="b-code-snippet__code-area"> <div ref="container" class="b-code-snippet__code-area-content" :class="codeAreaContentConditionalClasses" /> </code> <section v-else> <slot name="empty-state"> <!-- TODO: switch with empty-state component when ready --> <div class="b-code-snippet__empty-state">{{ t('nothingToDisplay') }}</div> </slot> </section> <base-modal v-if="expandable" class="b-code-snippet__modal" :hide-close-button="true" :custom-padding="'0px'" :is-dismissible="true" :is-open="showModal" size="large" @close-modal="showModal = false" > <template #content> <bento-code-snippet v-bind="{ ...$props, expandable: false }" /> </template> </base-modal> </div> </template> <script setup lang="ts"> import { computed, type HTMLAttributes, onMounted, ref, shallowRef, useAttrs, watch, watchEffect } from 'vue'; import { EditorView, highlightActiveLine, keymap, lineNumbers } from '@codemirror/view'; import { Compartment, EditorState } from '@codemirror/state'; import { history, indentWithTab } from '@codemirror/commands'; import { lightThemeHighlight } from './highlight'; import { getLangLoader, INDENT_SAME_AS_LINE_BEFORE } from './utils'; import { BentoDropdown } from '@/components/dropdown'; import { BentoButton } from '@/components/button'; import { BentoTypography } from '@/components/typography'; import { BentoLoadingIndicator } from '@/components/loading-indicator'; import { useI18n } from '@/utils/ts/i18n'; import { Copy } from '@/internal'; import { BentoCodeSnippetEvent, type BentoCodeSnippetProps, BentoCodeSnippetSupportedLanguage, BentoCodeSnippetVariant, } from './code-snippet.types'; import ExpandIcon from '@adyen/ui-assets-icons-16/vue/expand'; import BaseModal from '@/components/modal/components/base-modal/base-modal.vue'; import messages from './messages.json'; type MessageSchema = (typeof messages)['en-US']; const props = withDefaults(defineProps<BentoCodeSnippetProps>(), { actionable: false, actionableText: null, content: '', editable: false, expandable: false, lang: BentoCodeSnippetSupportedLanguage.JSON, langLabel: null, loading: false, variant: BentoCodeSnippetVariant.MULTILINE, }); const emit = defineEmits([BentoCodeSnippetEvent.ACTION, BentoCodeSnippetEvent.CHANGE]); const attrs = useAttrs(); const { t } = useI18n<{ message: MessageSchema }>({ messages }); // language const selectedLanguage = ref<string | null>(null); const availableLanguages = []; // TODO: implement const displayedLang = computed(() => props.langLabel ?? props.lang.toUpperCase()); const isInlineVariant = computed(() => props.variant === BentoCodeSnippetVariant.INLINE); const conditionalClasses = computed(() => ({ 'b-code-snippet--inline': isInlineVariant.value, 'b-code-snippet--scrollable': !isInlineVariant.value, })); const codeAreaContentConditionalClasses = computed(() => ({ 'b-code-snippet__code-area-content--editable': props.editable, })); const loadLang = getLangLoader(props.lang); const container = shallowRef<HTMLDivElement>(); const editor = shallowRef<EditorView>(); const languageConf = new Compartment(); const editorTheme = new Compartment(); const editorReadOnly = new Compartment(); const editorAttributes = new Compartment(); const currentContents = ref(null); const contentLength = ref(0); const runText = computed(() => props.actionableText || t('run')); onMounted(async () => { const language = await loadLang(); // alongside the updateListener plugin it acts as a watcher of changes to the editor state currentContents.value = props.content; const updateCurrentContents = ({ state }) => { currentContents.value = state.doc.toString(); }; const extensions = [ highlightActiveLine(), keymap.of([indentWithTab, INDENT_SAME_AS_LINE_BEFORE]), languageConf.of(language()), editorTheme.of(lightThemeHighlight(props.lang)), editorReadOnly.of(EditorState.readOnly.of(!props.editable)), editorAttributes.of( EditorView.contentAttributes.of({ 'aria-label': (attrs['aria-label'] as HTMLAttributes['aria-label']) ?? t('codeSnippet'), ...(!isInlineVariant.value && { tabindex: '0' }), }) ), EditorView.updateListener.of(content => updateCurrentContents(content)), ]; if (props.variant === 'multiline') { extensions.push([lineNumbers(), history()]); } const state = EditorState.create({ doc: props.content, extensions: [...extensions], }); contentLength.value = state.doc.length; editor.value = new EditorView({ state, parent: container.value, }); }); watch( () => props.content, () => { if (props.content !== currentContents.value) { const upcomingContentLength = props.content.length; editor.value.dispatch({ changes: { from: 0, to: contentLength.value, insert: props.content, }, }); contentLength.value = upcomingContentLength; } } ); const onActionClicked = () => { emit(BentoCodeSnippetEvent.ACTION, currentContents.value); }; watchEffect(() => { if (currentContents.value !== null) { emit(BentoCodeSnippetEvent.CHANGE, currentContents.value); } }); const showModal = ref(false); </script> <script lang="ts"> /** * A code-snippet is a container to display code in a readable way. * Come with added functionalities like syntax highlighting, editing and actioning the code * * @example * import { BentoCodeSnippet } from '@adyen/bento-vue2'; * * export default { * components: { BentoCodeSnippet }, * template: ` * <bento-code-snippet :variant="BentoCodeSnippetVariant.MULTILINE" content="{ example: 1234 }" /> * ` * } */ export default { i18n: { messages }, name: 'bento-code-snippet', }; </script> <style lang="scss" scoped src="./code-snippet.scss"></style>
@@ -1 +1 @@
1
- import { BentoCountryCode, BentoCountryVariant } from './country.types'; import { storybookDocsParameter } from '@/utils/ts/storybook'; import BentoCountry from './country.vue'; import { isVue2 } from 'vue-demi'; const COUNTRY_CODES_LIST = Object.values(BentoCountryCode); const ALPHABETICALLY_ORDERED_COUNTRY_CODES = COUNTRY_CODES_LIST.sort(); export default { title: 'Country', component: BentoCountry, argTypes: { code: { options: ALPHABETICALLY_ORDERED_COUNTRY_CODES, mapping: BentoCountryCode, control: { type: 'select', }, }, variant: { options: Object.values(BentoCountryVariant), mapping: BentoCountryVariant, control: { type: 'select', labels: { custom: 'DEPRECATED: custom', }, }, }, }, }; export const Default = (_args, { argTypes }) => ({ components: { BentoCountry }, props: Object.keys(argTypes), template: ` <bento-country v-bind="args"/> `, setup(props) { return { args: isVue2 ? props : _args, }; }, }); Default.args = { code: BentoCountryCode.NL, }; Default.parameters = storybookDocsParameter(` <bento-country :code="BentoCountryCode.NL"/> `);
1
+ import { BentoCountryCode, BentoCountryVariant } from './country.types'; import { storybookDocsParameter } from '@/utils/ts/storybook'; import BentoCountry from './country.vue'; import { isVue2 } from 'vue-demi'; import type { Meta, StoryObj } from '@storybook/vue'; const CountryDefault = "<template>\n <bento-country :code=\"BentoCountryCode.NL\" />\n</template>\n\n<script setup lang=\"ts\">\n import { BentoCountry, BentoCountryCode } from '@adyen/bento-vue2';\n</script>\n"; const COUNTRY_CODES_LIST = Object.values(BentoCountryCode); const ALPHABETICALLY_ORDERED_COUNTRY_CODES = COUNTRY_CODES_LIST.sort(); const meta: Meta = { title: 'Country', component: BentoCountry, argTypes: { code: { options: ALPHABETICALLY_ORDERED_COUNTRY_CODES, mapping: BentoCountryCode, control: { type: 'select', }, }, variant: { options: Object.values(BentoCountryVariant), mapping: BentoCountryVariant, control: { type: 'select', }, }, }, }; export default meta; type Story = StoryObj<typeof BentoCountry>; export const Default: Story = { render: (_args, { argTypes }) => ({ components: { BentoCountry }, props: Object.keys(argTypes), template: ` <bento-country v-bind="args"/> `, setup(props) { return { args: isVue2 ? props : _args, }; }, }), args: { code: BentoCountryCode.NL, }, parameters: storybookDocsParameter(CountryDefault), };
@@ -1 +1 @@
1
- /** * @deprecated Since v2.0.0. Use string literal instead. */ export enum BentoCountryVariant { ISO = 'iso', NAME = 'name', PHONE_CODE = 'phone_code', CAPITAL = 'capital', /** deprecated Use any of the other BentoCountry variants instead OR BentoTypography component for custom text */ CUSTOM = 'custom', } export enum BentoCountryCode { BD = 'BD', BE = 'BE', BF = 'BF', BG = 'BG', BA = 'BA', BB = 'BB', WF = 'WF', BL = 'BL', BM = 'BM', BN = 'BN', BO = 'BO', BH = 'BH', BI = 'BI', BJ = 'BJ', BT = 'BT', JM = 'JM', BV = 'BV', BW = 'BW', WS = 'WS', BQ = 'BQ', BR = 'BR', BS = 'BS', JE = 'JE', BY = 'BY', BZ = 'BZ', RU = 'RU', RW = 'RW', RS = 'RS', TL = 'TL', RE = 'RE', TM = 'TM', TJ = 'TJ', RO = 'RO', TK = 'TK', GW = 'GW', GU = 'GU', GT = 'GT', GS = 'GS', GR = 'GR', GQ = 'GQ', GP = 'GP', JP = 'JP', GY = 'GY', GG = 'GG', GF = 'GF', GE = 'GE', GD = 'GD', GB = 'GB', GA = 'GA', SV = 'SV', GN = 'GN', GM = 'GM', GL = 'GL', GI = 'GI', GH = 'GH', OM = 'OM', TN = 'TN', JO = 'JO', HR = 'HR', HT = 'HT', HU = 'HU', HK = 'HK', HN = 'HN', HM = 'HM', VE = 'VE', PR = 'PR', PS = 'PS', PW = 'PW', PT = 'PT', SJ = 'SJ', PY = 'PY', IQ = 'IQ', PA = 'PA', PF = 'PF', PG = 'PG', PE = 'PE', PK = 'PK', PH = 'PH', PN = 'PN', PL = 'PL', PM = 'PM', ZM = 'ZM', EH = 'EH', EE = 'EE', EG = 'EG', ZA = 'ZA', EC = 'EC', IT = 'IT', VN = 'VN', SB = 'SB', ET = 'ET', SO = 'SO', ZW = 'ZW', SA = 'SA', ES = 'ES', ER = 'ER', ME = 'ME', MD = 'MD', MG = 'MG', MF = 'MF', MA = 'MA', MC = 'MC', UZ = 'UZ', MM = 'MM', ML = 'ML', MO = 'MO', MN = 'MN', MH = 'MH', MK = 'MK', MU = 'MU', MT = 'MT', MW = 'MW', MV = 'MV', MQ = 'MQ', MP = 'MP', MS = 'MS', MR = 'MR', IM = 'IM', UG = 'UG', TZ = 'TZ', MY = 'MY', MX = 'MX', IL = 'IL', FR = 'FR', IO = 'IO', SH = 'SH', FI = 'FI', FJ = 'FJ', FK = 'FK', FM = 'FM', FO = 'FO', NI = 'NI', NL = 'NL', NO = 'NO', NA = 'NA', VU = 'VU', NC = 'NC', NE = 'NE', NF = 'NF', NG = 'NG', NZ = 'NZ', NP = 'NP', NR = 'NR', NU = 'NU', CK = 'CK', XK = 'XK', CI = 'CI', CH = 'CH', CO = 'CO', CN = 'CN', CM = 'CM', CL = 'CL', CC = 'CC', CA = 'CA', CG = 'CG', CF = 'CF', CD = 'CD', CZ = 'CZ', CY = 'CY', CX = 'CX', CR = 'CR', CW = 'CW', CV = 'CV', CU = 'CU', SZ = 'SZ', SY = 'SY', SX = 'SX', KG = 'KG', KE = 'KE', SS = 'SS', SR = 'SR', KI = 'KI', KH = 'KH', KN = 'KN', KM = 'KM', ST = 'ST', SK = 'SK', KR = 'KR', SI = 'SI', KP = 'KP', KW = 'KW', SN = 'SN', SM = 'SM', SL = 'SL', SC = 'SC', KZ = 'KZ', KY = 'KY', SG = 'SG', SE = 'SE', SD = 'SD', DO = 'DO', DM = 'DM', DJ = 'DJ', DK = 'DK', VG = 'VG', DE = 'DE', YE = 'YE', DZ = 'DZ', US = 'US', UY = 'UY', YT = 'YT', UM = 'UM', LB = 'LB', LC = 'LC', LA = 'LA', TV = 'TV', TW = 'TW', TT = 'TT', TR = 'TR', LK = 'LK', LI = 'LI', LV = 'LV', TO = 'TO', LT = 'LT', LU = 'LU', LR = 'LR', LS = 'LS', TH = 'TH', TF = 'TF', TG = 'TG', TD = 'TD', TC = 'TC', LY = 'LY', VA = 'VA', VC = 'VC', AE = 'AE', AD = 'AD', AG = 'AG', AF = 'AF', AI = 'AI', VI = 'VI', IS = 'IS', IR = 'IR', AM = 'AM', AL = 'AL', AO = 'AO', AQ = 'AQ', AS = 'AS', AR = 'AR', AU = 'AU', AT = 'AT', AW = 'AW', IN = 'IN', AX = 'AX', AZ = 'AZ', IE = 'IE', ID = 'ID', UA = 'UA', QA = 'QA', MZ = 'MZ', UNKNOWN = 'ZZ', } export interface BentoCountryProps { /** * Two character country code ([ISO 3166-1 alpha-2 format](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2)). */ code?: BentoCountryCode | `${BentoCountryCode}`; /** * Custom label text. */ label?: string; /** * Which label variant to display. * @values iso, name, phone_code, capital */ variant?: BentoCountryVariant | `${BentoCountryVariant}`; }
1
+ /** * @deprecated Since v3.0.0. Use string literal instead. */ export enum BentoCountryVariant { ISO = 'iso', NAME = 'name', PHONE_CODE = 'phone_code', CAPITAL = 'capital', } export enum BentoCountryCode { BD = 'BD', BE = 'BE', BF = 'BF', BG = 'BG', BA = 'BA', BB = 'BB', WF = 'WF', BL = 'BL', BM = 'BM', BN = 'BN', BO = 'BO', BH = 'BH', BI = 'BI', BJ = 'BJ', BT = 'BT', JM = 'JM', BV = 'BV', BW = 'BW', WS = 'WS', BQ = 'BQ', BR = 'BR', BS = 'BS', JE = 'JE', BY = 'BY', BZ = 'BZ', RU = 'RU', RW = 'RW', RS = 'RS', TL = 'TL', RE = 'RE', TM = 'TM', TJ = 'TJ', RO = 'RO', TK = 'TK', GW = 'GW', GU = 'GU', GT = 'GT', GS = 'GS', GR = 'GR', GQ = 'GQ', GP = 'GP', JP = 'JP', GY = 'GY', GG = 'GG', GF = 'GF', GE = 'GE', GD = 'GD', GB = 'GB', GA = 'GA', SV = 'SV', GN = 'GN', GM = 'GM', GL = 'GL', GI = 'GI', GH = 'GH', OM = 'OM', TN = 'TN', JO = 'JO', HR = 'HR', HT = 'HT', HU = 'HU', HK = 'HK', HN = 'HN', HM = 'HM', VE = 'VE', PR = 'PR', PS = 'PS', PW = 'PW', PT = 'PT', SJ = 'SJ', PY = 'PY', IQ = 'IQ', PA = 'PA', PF = 'PF', PG = 'PG', PE = 'PE', PK = 'PK', PH = 'PH', PN = 'PN', PL = 'PL', PM = 'PM', ZM = 'ZM', EH = 'EH', EE = 'EE', EG = 'EG', ZA = 'ZA', EC = 'EC', IT = 'IT', VN = 'VN', SB = 'SB', ET = 'ET', SO = 'SO', ZW = 'ZW', SA = 'SA', ES = 'ES', ER = 'ER', ME = 'ME', MD = 'MD', MG = 'MG', MF = 'MF', MA = 'MA', MC = 'MC', UZ = 'UZ', MM = 'MM', ML = 'ML', MO = 'MO', MN = 'MN', MH = 'MH', MK = 'MK', MU = 'MU', MT = 'MT', MW = 'MW', MV = 'MV', MQ = 'MQ', MP = 'MP', MS = 'MS', MR = 'MR', IM = 'IM', UG = 'UG', TZ = 'TZ', MY = 'MY', MX = 'MX', IL = 'IL', FR = 'FR', IO = 'IO', SH = 'SH', FI = 'FI', FJ = 'FJ', FK = 'FK', FM = 'FM', FO = 'FO', NI = 'NI', NL = 'NL', NO = 'NO', NA = 'NA', VU = 'VU', NC = 'NC', NE = 'NE', NF = 'NF', NG = 'NG', NZ = 'NZ', NP = 'NP', NR = 'NR', NU = 'NU', CK = 'CK', XK = 'XK', CI = 'CI', CH = 'CH', CO = 'CO', CN = 'CN', CM = 'CM', CL = 'CL', CC = 'CC', CA = 'CA', CG = 'CG', CF = 'CF', CD = 'CD', CZ = 'CZ', CY = 'CY', CX = 'CX', CR = 'CR', CW = 'CW', CV = 'CV', CU = 'CU', SZ = 'SZ', SY = 'SY', SX = 'SX', KG = 'KG', KE = 'KE', SS = 'SS', SR = 'SR', KI = 'KI', KH = 'KH', KN = 'KN', KM = 'KM', ST = 'ST', SK = 'SK', KR = 'KR', SI = 'SI', KP = 'KP', KW = 'KW', SN = 'SN', SM = 'SM', SL = 'SL', SC = 'SC', KZ = 'KZ', KY = 'KY', SG = 'SG', SE = 'SE', SD = 'SD', DO = 'DO', DM = 'DM', DJ = 'DJ', DK = 'DK', VG = 'VG', DE = 'DE', YE = 'YE', DZ = 'DZ', US = 'US', UY = 'UY', YT = 'YT', UM = 'UM', LB = 'LB', LC = 'LC', LA = 'LA', TV = 'TV', TW = 'TW', TT = 'TT', TR = 'TR', LK = 'LK', LI = 'LI', LV = 'LV', TO = 'TO', LT = 'LT', LU = 'LU', LR = 'LR', LS = 'LS', TH = 'TH', TF = 'TF', TG = 'TG', TD = 'TD', TC = 'TC', LY = 'LY', VA = 'VA', VC = 'VC', AE = 'AE', AD = 'AD', AG = 'AG', AF = 'AF', AI = 'AI', VI = 'VI', IS = 'IS', IR = 'IR', AM = 'AM', AL = 'AL', AO = 'AO', AQ = 'AQ', AS = 'AS', AR = 'AR', AU = 'AU', AT = 'AT', AW = 'AW', IN = 'IN', AX = 'AX', AZ = 'AZ', IE = 'IE', ID = 'ID', UA = 'UA', QA = 'QA', MZ = 'MZ', UNKNOWN = 'ZZ', } export interface BentoCountryProps { /** * Two character country code ([ISO 3166-1 alpha-2 format](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2)). */ code?: BentoCountryCode | `${BentoCountryCode}`; /** * Which label variant to display. * @values iso, name, phone_code, capital */ variant?: BentoCountryVariant | `${BentoCountryVariant}`; }
@@ -1 +1 @@
1
- <template> <div class="b-country"> <div class="b-country__label"> <span v-if="isSummaryGridLayout">{{ countryLabel }}</span> <bento-typography v-else el="span">{{ countryLabel }}</bento-typography> </div> </div> </template> <script setup lang="ts"> import { inject, ref, toRefs, watch } from 'vue'; import { BentoTypography } from '@/components/typography'; import { useCountryCapital, useCountryName, useCountryPhoneCode } from './composables'; import { BentoCountryCode, type BentoCountryProps, BentoCountryVariant } from './country.types'; import { useI18n } from '@/utils/ts/i18n'; import { deprecate } from '@/utils/ts/deprecate'; import { type BentoSummaryGridLayout } from '@/components/summary-grid/summary-grid.types'; import { SUMMARY_GRID_LAYOUT_INJECTION_KEY } from '@/components/summary-grid/summary-grid.keys'; const props = withDefaults(defineProps<BentoCountryProps>(), { code: BentoCountryCode.UNKNOWN, label: undefined, variant: BentoCountryVariant.NAME, }); const { code, variant, label: customLabel } = toRefs(props); const { locale } = useI18n(undefined, true); const countryName = useCountryName(code, locale); const countryLabel = ref(''); const getLabel = () => { switch (variant.value) { case BentoCountryVariant.ISO: return code.value; case BentoCountryVariant.PHONE_CODE: return `${code.value} (${useCountryPhoneCode(code).value})`; case BentoCountryVariant.CAPITAL: // TODO: do we need an API OR get a longer translations list??? // Need to be able TRANSLATE as well as map... return `${useCountryCapital(code, locale).value} (${countryName.value})`; case BentoCountryVariant.CUSTOM: return customLabel.value; case BentoCountryVariant.NAME: default: return countryName.value; } }; // Update label if variant prop changes watch( [variant, locale, code], () => { countryLabel.value = getLabel(); }, { immediate: true } ); if (variant.value === 'custom' || props.label) { deprecate( 'BentoCountry "custom" variant and "label" prop', 'Use any of the other BentoCountry variants instead OR BentoTypography component for custom text', '2.0.0' ); } /* == Summary-grid styles == */ const registerPaymentMethodInSummaryGrid: BentoSummaryGridLayout = inject( SUMMARY_GRID_LAYOUT_INJECTION_KEY, () => ({ isSummaryGridLayout: false, }) ); const { isSummaryGridLayout } = registerPaymentMethodInSummaryGrid(); </script> <script lang="ts"> /** * A component to display a country's label. * The label comes in four variates: iso code, country name, phone number code or capital city. * * @usage * import { BentoCountry, BentoCountryCode } from '@adyen/bento-vue2'; * * export default { * components: { BentoCountry }, * template: ` * <bento-country :code="BentoCountryCode.NL" /> * ` * } */ export default { name: 'bento-country', }; </script> <style lang="scss" scoped src="./country.scss" />
1
+ <template> <div class="b-country"> <div class="b-country__label"> <span v-if="isSummaryGridLayout">{{ countryLabel }}</span> <bento-typography v-else el="span">{{ countryLabel }}</bento-typography> </div> </div> </template> <script setup lang="ts"> import { inject, ref, toRefs, watch } from 'vue'; import { BentoTypography } from '@/components/typography'; import { useCountryCapital, useCountryName, useCountryPhoneCode } from './composables'; import { BentoCountryCode, type BentoCountryProps, BentoCountryVariant } from './country.types'; import { useI18n } from '@/utils/ts/i18n'; import { type BentoSummaryGridLayout } from '@/components/summary-grid/summary-grid.types'; import { SUMMARY_GRID_LAYOUT_INJECTION_KEY } from '@/components/summary-grid/summary-grid.keys'; const props = withDefaults(defineProps<BentoCountryProps>(), { code: BentoCountryCode.UNKNOWN, variant: BentoCountryVariant.NAME, }); const { code, variant } = toRefs(props); const { locale } = useI18n(undefined, true); const countryName = useCountryName(code, locale); const countryLabel = ref(''); const getLabel = () => { switch (variant.value) { case BentoCountryVariant.ISO: return code.value; case BentoCountryVariant.PHONE_CODE: return `${code.value} (${useCountryPhoneCode(code).value})`; case BentoCountryVariant.CAPITAL: // TODO: do we need an API OR get a longer translations list??? // Need to be able TRANSLATE as well as map... return `${useCountryCapital(code, locale).value} (${countryName.value})`; case BentoCountryVariant.NAME: default: return countryName.value; } }; // Update label if variant prop changes watch( [variant, locale, code], () => { countryLabel.value = getLabel(); }, { immediate: true } ); /* == Summary-grid styles == */ const registerPaymentMethodInSummaryGrid: BentoSummaryGridLayout = inject( SUMMARY_GRID_LAYOUT_INJECTION_KEY, () => ({ isSummaryGridLayout: false, }) ); const { isSummaryGridLayout } = registerPaymentMethodInSummaryGrid(); </script> <script lang="ts"> /** * A component to display a country's label. * The label comes in four variates: iso code, country name, phone number code or capital city. * * @usage * import { BentoCountry, BentoCountryCode } from '@adyen/bento-vue2'; * * export default { * components: { BentoCountry }, * template: ` * <bento-country :code="BentoCountryCode.NL" /> * ` * } */ export default { name: 'bento-country', }; </script> <style lang="scss" scoped src="./country.scss" />
@@ -1 +1 @@
1
- import { storybookDocsParameter } from '@/utils/ts/storybook'; import { BentoCurrencyISOCode, type BentoCurrencyProps } from '@/components/currency/currency.types'; import { isVue2 } from 'vue-demi'; import { type Meta, type StoryObj } from '@storybook/vue'; import BentoCurrency from './currency.vue'; export default { title: 'Currency', component: BentoCurrency, argTypes: { default: { name: 'default (deprecated)', defaultValue: '', description: 'Amount value. Use `value` property instead', table: { type: { summary: 'VNode[]' }, }, control: { type: 'text', disable: true, }, }, currency: { options: Object.values(BentoCurrencyISOCode), mapping: BentoCurrencyISOCode, control: { type: 'select', }, }, currencySign: { options: ['standard', 'accounting'], mapping: BentoCurrencyISOCode, control: { type: 'select', }, }, }, } as Meta; type Story = StoryObj<typeof BentoCurrency>; const DEFAULT_CURRENCY_PROPS: BentoCurrencyProps = { currency: BentoCurrencyISOCode.EUR, currencySign: 'standard', majorUnits: false, value: 123423, }; const DefaultTemplate: Story = { render: (_args, { argTypes }) => ({ components: { BentoCurrency }, props: Object.keys(argTypes), template: ` <bento-currency v-bind="args" /> `, setup(props) { return { args: isVue2 ? props : _args, }; }, }), }; const defaultCode = ` <bento-currency :currency="BentoCurrencyISOCode.EUR" :value="${DEFAULT_CURRENCY_PROPS.value}" :major-units="false" /> `; export const Default = { ...DefaultTemplate, args: { ...DEFAULT_CURRENCY_PROPS, }, parameters: storybookDocsParameter(defaultCode), }; const majorUnitsCode = ` <bento-currency :currency="BentoCurrencyISOCode.EUR" :value="${DEFAULT_CURRENCY_PROPS.value}" major-units /> `; export const MajorUnits = { ...DefaultTemplate, args: { ...DEFAULT_CURRENCY_PROPS, majorUnits: true, }, parameters: storybookDocsParameter(majorUnitsCode), };
1
+ import { storybookDocsParameter } from '@/utils/ts/storybook'; import { BentoCurrencyISOCode, type BentoCurrencyProps } from '@/components/currency/currency.types'; import { isVue2 } from 'vue-demi'; import { type Meta, type StoryObj } from '@storybook/vue'; import BentoCurrency from './currency.vue'; const CurrencyDefault = "<template>\n <bento-currency :currency=\"BentoCurrencyISOCode.EUR\" :major-units=\"false\" :value=\"123423\" />\n</template>\n\n<script setup lang=\"ts\">\n import { BentoCurrency, BentoCurrencyISOCode } from '@adyen/bento-vue2';\n</script>\n"; const CurrencyMajorUnits = "<template>\n <bento-currency :currency=\"BentoCurrencyISOCode.EUR\" major-units :value=\"123423\" />\n</template>\n\n<script setup lang=\"ts\">\n import { BentoCurrency, BentoCurrencyISOCode } from '@adyen/bento-vue2';\n</script>\n"; export default { title: 'Currency', component: BentoCurrency, argTypes: { default: { name: 'default (deprecated)', defaultValue: '', description: 'Amount value. Use `value` property instead', table: { type: { summary: 'VNode[]' }, }, control: { type: 'text', disable: true, }, }, currency: { options: Object.values(BentoCurrencyISOCode), mapping: BentoCurrencyISOCode, control: { type: 'select', }, }, currencySign: { options: ['standard', 'accounting'], mapping: BentoCurrencyISOCode, control: { type: 'select', }, }, }, } as Meta; type Story = StoryObj<typeof BentoCurrency>; const DEFAULT_CURRENCY_PROPS: BentoCurrencyProps = { currency: BentoCurrencyISOCode.EUR, currencySign: 'standard', majorUnits: false, value: 123423, }; const DefaultTemplate: Story = { render: (_args, { argTypes }) => ({ components: { BentoCurrency }, props: Object.keys(argTypes), template: ` <bento-currency v-bind="args" /> `, setup(props) { return { args: isVue2 ? props : _args, }; }, }), }; export const Default = { ...DefaultTemplate, args: { ...DEFAULT_CURRENCY_PROPS, }, parameters: storybookDocsParameter(CurrencyDefault), }; export const MajorUnits = { ...DefaultTemplate, args: { ...DEFAULT_CURRENCY_PROPS, majorUnits: true, }, parameters: storybookDocsParameter(CurrencyMajorUnits), };
@@ -1 +1 @@
1
- <template> <div class="b-currency" :aria-label="formattedCurrencyParts.formattedCurrency"> <bento-typography v-if="!disableTypography" class="b-currency__amount" el="span" variant="body" strong> <bento-typography el="span" :strongest="strongerAmount">{{ formattedCurrencyParts.currencyNumber }}</bento-typography> <span>{{ formattedCurrencyCode }}</span> </bento-typography> <template v-else>{{ formattedCurrencyParts.formattedCurrency }}</template> </div> </template> <script setup lang="ts"> import { computed, onMounted, useSlots } from 'vue'; import { BentoTypography } from '@/components/typography'; import { useBentoCurrency } from '@/composables/use-bento-currency/use-bento-currency'; import { deprecate } from '@/utils/ts/deprecate'; import { getSlotText } from '@/utils/ts/get-slot-text'; import { BentoCurrencyISOCode, type BentoCurrencyProps } from './currency.types'; const slots = useSlots(); const props = withDefaults(defineProps<BentoCurrencyProps>(), { currency: BentoCurrencyISOCode.EUR, disableTypography: false, majorUnits: false, value: undefined, currencySign: 'standard', }); const { formatCurrencyParts } = useBentoCurrency(); const formattedCurrencyParts = computed(() => { const rawCurrencyValue = props.value ?? getSlotText(slots)('default'); return formatCurrencyParts(rawCurrencyValue, { currency: props.currency, currencySign: props.currencySign, majorUnits: props.majorUnits, }); }); const formattedCurrencyCode = computed(() => `\u00A0${formattedCurrencyParts.value.currencyCode}`); onMounted(() => { if (getSlotText(slots)('default')) { deprecate( 'BentoCurrency "default" slot', `The use of "default" slot in "BentoCurrency" is no longer supported as it causes issues with dynamic content. Use the "value" property instead. <bento-currency :value="12345.67" currency="USD" major-units="false" />`, '2.0.0' ); } }); </script> <script lang="ts"> /** * A Currency component is used to display a formatted currency value. * * @example * import { BentoCurrency, BentoCurrencyISOCode } from '@adyen/bento-vue2'; * * export default { * components: { BentoCurrency }, * template: ` * <bento-currency * :currency="BentoCurrencyISOCode.USD" * :value="76.33" * /> * ` * } */ export default { name: 'bento-currency', i18n: {}, // required to enable E2E to run as they do not have vue-i18n set up }; </script> <style lang="scss" scoped src="./currency.scss" />
1
+ <template> <div class="b-currency" :aria-label="formattedCurrencyParts.formattedCurrency"> <bento-typography v-if="!disableTypography" class="b-currency__amount" el="span" variant="body" strong> <bento-typography el="span" :strongest="strongerAmount">{{ formattedCurrencyParts.currencyNumber }}</bento-typography> <span>{{ formattedCurrencyCode }}</span> </bento-typography> <template v-else>{{ formattedCurrencyParts.formattedCurrency }}</template> </div> </template> <script setup lang="ts"> import { computed, onMounted, useSlots } from 'vue'; import { BentoTypography } from '@/components/typography'; import { useBentoCurrency } from '@/composables/use-bento-currency/use-bento-currency'; import { deprecate } from '@/utils/ts/deprecate'; import { getSlotText } from '@/utils/ts/get-slot-text'; import { BentoCurrencyISOCode, type BentoCurrencyProps } from './currency.types'; const slots = useSlots(); const props = withDefaults(defineProps<BentoCurrencyProps>(), { currency: BentoCurrencyISOCode.EUR, disableTypography: false, majorUnits: false, value: undefined, currencySign: 'standard', }); const { formatCurrencyParts } = useBentoCurrency(); const formattedCurrencyParts = computed(() => { const rawCurrencyValue = props.value ?? getSlotText(slots)('default'); return formatCurrencyParts(rawCurrencyValue, { currency: props.currency, currencySign: props.currencySign, majorUnits: props.majorUnits, }); }); const formattedCurrencyCode = computed(() => `\u00A0${formattedCurrencyParts.value.currencyCode}`); onMounted(() => { if (getSlotText(slots)('default')) { deprecate( 'BentoCurrency "default" slot', `The use of "default" slot in "BentoCurrency" is no longer supported as it causes issues with dynamic content. Use the "value" property instead. <bento-currency :value="12345.67" currency="USD" major-units="false" />`, '3.0.0' ); } }); </script> <script lang="ts"> /** * A Currency component is used to display a formatted currency value. * * @example * import { BentoCurrency, BentoCurrencyISOCode } from '@adyen/bento-vue2'; * * export default { * components: { BentoCurrency }, * template: ` * <bento-currency * :currency="BentoCurrencyISOCode.USD" * :value="76.33" * /> * ` * } */ export default { name: 'bento-currency', i18n: {}, // required to enable E2E to run as they do not have vue-i18n set up }; </script> <style lang="scss" scoped src="./currency.scss" />
@@ -1 +1 @@
1
- import { isVue2 } from 'vue-demi'; import type { Meta, StoryObj } from '@storybook/vue'; import { storybookDocsParameter } from '@/utils/ts/storybook'; import { BentoLink } from '@/components/link'; import { BentoPopoverPositions } from '@/components/popover'; import { BentoTooltipPosition } from '@/directives'; import { BentoTypography } from '@/components/typography'; import BentoDashedUnderline from './dashed-underline.vue'; const TELEPORT_DEFAULT = { disabled: true, }; const meta: Meta = { title: 'Dashed underline', component: BentoDashedUnderline, argTypes: { // Enums tooltipPosition: { options: Object.values(BentoTooltipPosition), mapping: BentoTooltipPosition, control: { type: 'select', }, }, popoverPosition: { options: Object.values(BentoPopoverPositions), mapping: BentoPopoverPositions, control: { type: 'select', }, }, // Slots default: { defaultValue: 'annotated text', description: 'Dashed underline content', table: { type: { summary: 'VNode[]' }, }, control: { type: 'text' }, }, }, }; export default meta; type Story = StoryObj<typeof BentoDashedUnderline>; const withTooltipCode = ` <bento-dashed-underline tooltip-text="Some extra info">annotated text</bento-dashed-underline> `; export const WithTooltip: Story = { render: (_args, { argTypes }) => ({ components: { BentoTypography, BentoDashedUnderline }, props: Object.keys(argTypes), template: ` <bento-typography> This is an example of some <bento-dashed-underline v-bind="args">{{args.default}}</bento-dashed-underline>. </bento-typography> `, setup(props) { return { // Values args: isVue2 ? props : _args, }; }, }), args: { default: 'annotated text with tooltip', tooltipText: 'Some extra info', }, parameters: storybookDocsParameter(withTooltipCode), }; const withPopoverCode = ` <bento-dashed-underline> annotated text <template #popover-content> Some extra info. <bento-link>Learn more here</bento-link> </template> </bento-dashed-underline> `; export const WithPopover: Story = { render: (_args, { argTypes }) => ({ components: { BentoTypography, BentoDashedUnderline, BentoLink }, props: Object.keys(argTypes), template: ` <bento-typography> This is an example of some <bento-dashed-underline v-bind="args"> {{ args.default }} <template v-if="!args.popoverText" #popover-content> Some extra info. <bento-link to="https://www.adyen.com/" external> Learn more here </bento-link> </template> </bento-dashed-underline> </bento-typography> `, setup(props) { return { // Values args: isVue2 ? props : _args, }; }, }), args: { default: 'annotated text with popover', teleport: { ...TELEPORT_DEFAULT }, }, parameters: storybookDocsParameter(withPopoverCode), };
1
+ import { isVue2 } from 'vue-demi'; import type { Meta, StoryObj } from '@storybook/vue'; import { storybookDocsParameter } from '@/utils/ts/storybook'; import { BentoLink } from '@/components/link'; import { BentoPopoverPositions } from '@/components/popover'; import { BentoTooltipPosition } from '@/directives'; import { BentoTypography } from '@/components/typography'; import BentoDashedUnderline from './dashed-underline.vue'; const DashedUnderlineWithPopover = "<template>\n <bento-typography>\n This is an example of some\n <bento-dashed-underline>\n annotated text with popover\n <template #popover-content>\n Some extra info.\n <bento-link external to=\"https://www.adyen.com/\"> Learn more here </bento-link>\n </template> </bento-dashed-underline\n >.\n </bento-typography>\n</template>\n\n<script setup lang=\"ts\">\n import { BentoDashedUnderline, BentoLink, BentoTypography } from '@adyen/bento-vue2';\n</script>\n"; const DashedUnderlineWithTooltip = "<template>\n <bento-typography>\n This is an example of some\n <bento-dashed-underline tooltip-text=\"Some extra info\"> annotated text with tooltip </bento-dashed-underline>.\n </bento-typography>\n</template>\n\n<script setup lang=\"ts\">\n import { BentoDashedUnderline, BentoTypography } from '@adyen/bento-vue2';\n</script>\n"; const TELEPORT_DEFAULT = { disabled: true, }; const meta: Meta = { title: 'Dashed underline', component: BentoDashedUnderline, argTypes: { // Enums tooltipPosition: { options: Object.values(BentoTooltipPosition), mapping: BentoTooltipPosition, control: { type: 'select', }, }, popoverPosition: { options: Object.values(BentoPopoverPositions), mapping: BentoPopoverPositions, control: { type: 'select', }, }, // Slots default: { defaultValue: 'annotated text', description: 'Dashed underline content', table: { type: { summary: 'VNode[]' }, }, control: { type: 'text' }, }, }, }; export default meta; type Story = StoryObj<typeof BentoDashedUnderline>; export const WithTooltip: Story = { render: (_args, { argTypes }) => ({ components: { BentoTypography, BentoDashedUnderline }, props: Object.keys(argTypes), template: ` <bento-typography> This is an example of some <bento-dashed-underline v-bind="args">{{args.default}}</bento-dashed-underline>. </bento-typography> `, setup(props) { return { // Values args: isVue2 ? props : _args, }; }, }), args: { default: 'annotated text with tooltip', tooltipText: 'Some extra info', }, parameters: storybookDocsParameter(DashedUnderlineWithTooltip), }; export const WithPopover: Story = { render: (_args, { argTypes }) => ({ components: { BentoTypography, BentoDashedUnderline, BentoLink }, props: Object.keys(argTypes), template: ` <bento-typography> This is an example of some <bento-dashed-underline v-bind="args"> {{ args.default }} <template v-if="!args.popoverText" #popover-content> Some extra info. <bento-link to="https://www.adyen.com/" external> Learn more here </bento-link> </template> </bento-dashed-underline> </bento-typography> `, setup(props) { return { // Values args: isVue2 ? props : _args, }; }, }), args: { default: 'annotated text with popover', teleport: { ...TELEPORT_DEFAULT }, }, parameters: storybookDocsParameter(DashedUnderlineWithPopover), };
@@ -1 +1 @@
1
- import type { BentoButtonActionObject } from '@/components/button/components/button-actions/button-actions.types'; import type { BentoMenuItem } from '@/components/menu/components/menu-item/menu-item.types'; import type { BentoDatagridDataItem } from '@/components/data-grid/components/data-grid-row/data-grid-row.types'; import type { OmitStrict } from '@/types/omit-strict'; import { type BentoTooltipPosition } from '@/directives/tooltip/tooltip.types'; export type BentoColumnCellActionVariant = 'copy' | 'edit' | 'open' | 'more'; export type BentoColumnCellActionEvent = (rowDataItem: BentoDatagridDataItem, columnKey: string) => void; export type BentoColumnCellActionMenuItem = { /** * @deprecated Since v2.0.0. Use `event` instead. */ handler?: BentoMenuItem['handler']; event?: BentoColumnCellActionEvent; } & OmitStrict<BentoMenuItem, 'handler'>; export type BentoColumnCellAction = OmitStrict< BentoButtonActionObject, 'variant' | 'event' | 'title' | 'icon' | 'state' > & { title?: string; event?: BentoColumnCellActionEvent; tooltipText?: string; tooltipPosition?: BentoTooltipPosition | `${BentoTooltipPosition}`; // Variant button properties isShort?: true; variant?: BentoColumnCellActionVariant; // Menu button properties menuData?: Array<BentoColumnCellActionMenuItem>; // Copy button properties getCopyData?: (rowDataItem: BentoDatagridDataItem, columnKey: string) => string; }; export type BentoColumnCellActions = Array<BentoColumnCellAction>; export type BentoColumnCellActionsByCellDataFn = ( rowDataItem: BentoDatagridDataItem, columnKey: string ) => BentoColumnCellActions; export type BentoColumnCellActionsProp = BentoColumnCellActions | BentoColumnCellActionsByCellDataFn; export type BentoDataGridRowActionsFn = (rowDataItem: BentoDatagridDataItem) => BentoColumnCellActions; export type BentoDataGridRowActionsProp = BentoColumnCellActions | BentoDataGridRowActionsFn;
1
+ import type { BentoButtonActionObject } from '@/components/button/components/button-actions/button-actions.types'; import type { BentoMenuItem } from '@/components/menu/components/menu-item/menu-item.types'; import type { BentoDatagridDataItem } from '@/components/data-grid/components/data-grid-row/data-grid-row.types'; import type { OmitStrict } from '@/types/omit-strict'; import { type BentoTooltipPosition } from '@/directives/tooltip/tooltip.types'; export type BentoColumnCellActionVariant = 'copy' | 'edit' | 'open' | 'more'; export type BentoColumnCellActionEvent = (rowDataItem: BentoDatagridDataItem, columnKey: string) => void; export type BentoColumnCellActionMenuItem = { event?: BentoColumnCellActionEvent; } & OmitStrict<BentoMenuItem, 'handler'>; export type BentoColumnCellAction = OmitStrict< BentoButtonActionObject, 'variant' | 'event' | 'title' | 'icon' | 'state' > & { title?: string; event?: BentoColumnCellActionEvent; tooltipText?: string; tooltipPosition?: BentoTooltipPosition | `${BentoTooltipPosition}`; // Variant button properties isShort?: true; variant?: BentoColumnCellActionVariant; // Menu button properties menuData?: Array<BentoColumnCellActionMenuItem>; // Copy button properties getCopyData?: (rowDataItem: BentoDatagridDataItem, columnKey: string) => string; }; export type BentoColumnCellActions = Array<BentoColumnCellAction>; export type BentoColumnCellActionsByCellDataFn = ( rowDataItem: BentoDatagridDataItem, columnKey: string ) => BentoColumnCellActions; export type BentoColumnCellActionsProp = BentoColumnCellActions | BentoColumnCellActionsByCellDataFn; export type BentoDataGridRowActionsFn = (rowDataItem: BentoDatagridDataItem) => BentoColumnCellActions; export type BentoDataGridRowActionsProp = BentoColumnCellActions | BentoDataGridRowActionsFn;
@@ -1 +1 @@
1
- <template> <Transition name="b-data-grid-cell-actions__animation" appear> <div class="b-data-grid-cell-actions"> <div v-if="showGradientElement && !isTouchDevice" class="b-data-grid-cell-actions__background-gradient" :class="conditionalCellActionsBackgroundGradientClasses" ></div> <div class="b-data-grid-cell-actions__actions" :class="conditionalCellActionsClasses" role="group"> <div v-for="(button, index) in computedCellActions" :key="index" class="b-data-grid-cell-actions__action" > <bento-menu v-if="button.menuData" v-bento-tooltip-directive:[button.tooltipPosition]="button.tooltipText" :data="transformMenuEvents(button.menuData)" :button="{ condensed: true, variant: 'secondary', disabled: button.disabled, }" :disable-arrow-down-opening-menu="disableArrowDownOpeningMenu" :teleport="teleportMenu" @open="emit('menu-open')" @close="emit('menu-close')" @menu-item-click="emit('menu-item-click')" > <template v-if="shouldShowMenuIconLeft(button)" #iconLeft> <options-vertical-icon v-if="button?.variant === 'more'" :svg-title="getButtonTitle(button, true)" /> <component :is="button.iconLeft" v-else :svg-title="getButtonTitle(button, true)" /> </template> <template v-if="!button?.isShort" #default> {{ getButtonTitle(button) }} </template> </bento-menu> <copy v-else-if="button.variant === 'copy'" :text="getCopyText(button)" :button-text="getButtonTitle(button)" :button="{ condensed: true, variant: 'secondary', }" /> <bento-button v-else v-bento-tooltip-directive:[button.tooltipPosition]="button.tooltipText" condensed variant="secondary" :critical="button.critical" :disabled="button.disabled" :link="button.link" v-on="generateButtonEvents(button)" > <template v-if="button.iconLeft || button.variant === 'edit'" #iconLeft> <edit1-icon v-if="button?.variant === 'edit'" :svg-title="getButtonTitle(button, true)" /> <component :is="button.iconLeft" v-else :svg-title="button.title" /> </template> <template v-if="!button?.isShort" #default> {{ getButtonTitle(button) }} </template> <template v-if="button.iconRight || button.variant === 'open'" #iconRight> <external-link-icon v-if="button?.variant === 'open'" :svg-title="getButtonTitle(button, true)" /> <component :is="button.iconRight" v-else :svg-title="button.title" /> </template> </bento-button> </div> </div> </div> </Transition> </template> <script setup lang="ts"> import { computed, inject, type PropType, ref, type Ref } from 'vue'; import { BentoButton } from '@/components/button'; import { BentoMenu, type BentoMenuItem } from '@/components/menu'; import { Copy } from '@/internal/copy'; import { BentoTooltipDirective as vBentoTooltipDirective } from '@/directives/tooltip'; import { printDevelopmentWarning } from '@/utils/ts/print-development-warning'; import { type BentoDatagridDataItem } from '@/components/data-grid/data-grid.types'; import { DATA_GRID_TOUCH_DEVICE } from '@/components/data-grid/data-grid.keys'; import Edit1Icon from '@adyen/ui-assets-icons-16/vue/edit-1'; import ExternalLinkIcon from '@adyen/ui-assets-icons-16/vue/external-link'; import OptionsVerticalIcon from '@adyen/ui-assets-icons-16/vue/options-vertical'; // Types import type { BentoColumnCellAction, BentoColumnCellActionMenuItem, BentoColumnCellActions, BentoColumnCellActionsByCellDataFn, BentoColumnCellActionsProp, BentoDataGridRowActionsProp, } from './data-grid-cell-actions.types'; // Translations import messages from './messages.json'; import { useI18n } from '@/utils/ts/i18n'; type MessageSchema = (typeof messages)['en-US']; const { t } = useI18n<{ message: MessageSchema }>({ messages }); const props = defineProps({ /** * Column definitions using 'key' to relate to data object. */ cellActions: { type: [Array, Function] as PropType<BentoColumnCellActionsProp | BentoDataGridRowActionsProp>, required: true, validator: (value: BentoColumnCellActions) => value?.length <= 2, }, /** * The column field key. */ columnKey: { type: String, default: undefined, }, /** * Disables any opening of the cell actions menus using the down arrow key. */ disableArrowDownOpeningMenu: { type: Boolean, default: false, }, /** * Set to true if the datagrid has been scrolled and the right side has overflowing space. */ hasRightOverflow: { type: Boolean, default: false, }, /** * Set to true if the row has a darker background when zebra rows is enabled. */ hasZebraBackground: { type: Boolean, default: false, }, /** * Set to true if the row is selected. */ isSelected: { type: Boolean, default: false, }, /** * Set to true if the row is highlighted. */ isHighlighted: { type: Boolean, default: false, }, /** * Set if set to true will teleport the action menu component */ teleportMenu: { type: Boolean, default: false, }, /** * The row data item object. */ rowDataItem: { type: Object as PropType<BentoDatagridDataItem>, required: true, }, }); const emit = defineEmits<{ /** * Emits when a cell actions menu is opened */ (e: 'menu-open'): void; /** * Emits when a cell actions menu is closed */ (e: 'menu-close'): void; /** * Emits when a cell actions menu button closes due to a menu item click */ (e: 'menu-item-click'): void; }>(); const isTouchDevice: Ref<boolean> = inject(DATA_GRID_TOUCH_DEVICE, ref(false)); // Helper to get text for menu items, always returning a string const getMenuItemText = (action: BentoColumnCellAction | BentoColumnCellActionMenuItem) => { // If it's already a menu item with a text property, use it if ('text' in action && action.text !== undefined) { return action.text; } // Otherwise, derive from variant or title switch ((action as BentoColumnCellAction).variant) { case 'copy': return t('copy'); case 'edit': return t('edit'); case 'open': return t('open'); case 'more': return t('more'); default: return (action as BentoColumnCellAction).title; } }; const getMenuItemIcon = (action: BentoColumnCellAction) => { switch (action.variant) { case 'copy': return Copy; case 'edit': return Edit1Icon; case 'open': return ExternalLinkIcon; default: return undefined; } }; const isRowActions = computed(() => props.columnKey === undefined); const conditionalCellActionsBackgroundGradientClasses = computed(() => ({ 'b-data-grid-cell-actions__background-gradient--with-row-actions-and-overflow': isRowActions.value && props.hasRightOverflow, 'b-data-grid-cell-actions__background-gradient--zebra': props.hasZebraBackground, 'b-data-grid-cell-actions__background-gradient--highlighted': props.isHighlighted, 'b-data-grid-cell-actions__background-gradient--selected': props.isSelected, })); const conditionalCellActionsClasses = computed(() => ({ 'b-data-grid-cell-actions__actions--with-row-actions': isRowActions.value, 'b-data-grid-cell-actions__actions--zebra': props.hasZebraBackground, 'b-data-grid-cell-actions__actions--highlighted': props.isHighlighted, 'b-data-grid-cell-actions__actions--selected': props.isSelected, 'b-data-grid-cell-actions__actions--zebra-hover': !isRowActions.value && props.hasZebraBackground, 'b-data-grid-cell-actions__actions--highlighted-hover': !isRowActions.value && props.isHighlighted, 'b-data-grid-cell-actions__actions--selected-hover': !isRowActions.value && props.isSelected, })); const showGradientElement = computed(() => !isRowActions.value || (isRowActions.value && props.hasRightOverflow)); /** * Checks if the passed object is a cell actions function that returns an cell actions array. * @param cellActions - a cell actions array or function */ function isBentoColumnCellActionsByCellValueDataFn( cellActions: BentoColumnCellActionsProp ): cellActions is BentoColumnCellActionsByCellDataFn { return typeof cellActions === 'function'; } const computedCellActions = computed(() => { const cellActions = isBentoColumnCellActionsByCellValueDataFn(props.cellActions) ? props.cellActions?.(props.rowDataItem, props.columnKey) : props.cellActions; if (isTouchDevice.value && !isRowActions.value && cellActions) { const flattenedMenuItems: Array<BentoColumnCellActionMenuItem> = []; cellActions.forEach(action => { if (action.menuData) { action.menuData.forEach(subMenuItem => { flattenedMenuItems.push(subMenuItem); }); } else { flattenedMenuItems.push({ text: getMenuItemText(action), event: action.event, critical: action.critical, disabled: action.disabled, icon: getMenuItemIcon(action), }); } }); return [ { variant: 'more', isShort: true, iconLeft: OptionsVerticalIcon, menuData: transformMenuEvents(flattenedMenuItems), }, ] as BentoColumnCellActions; } // Do not allow users to provide more than 2 cell action buttons if (!isTouchDevice.value && cellActions?.length > 2) { printDevelopmentWarning( 'WARNING: BentoDataGrid Cell actions can only have a maximum of 2 actions, if you need more consider using the menuData property instead.' ); } return cellActions?.slice(0, 2); }); const getButtonTitle = computed(() => (button: BentoColumnCellAction, isForSvgTitle?: boolean) => { if ((!isForSvgTitle && button.isShort) || (isForSvgTitle && !button.isShort)) { return undefined; } switch (button.variant) { case 'copy': return t('copy'); case 'edit': return t('edit'); case 'open': return t('open'); case 'more': return t('more'); default: return button.title; } }); const generateButtonEvents = (button: BentoColumnCellAction) => button?.event !== undefined ? { click: (event: MouseEvent) => { event.stopPropagation(); button.event(props.rowDataItem, props.columnKey); }, } : {}; const generateMenuEvents = (menuDataItem: BentoColumnCellActionMenuItem): BentoMenuItem => ({ ...menuDataItem, handler: () => { if (menuDataItem?.handler && typeof menuDataItem.handler === 'function') { menuDataItem?.handler(); } if (menuDataItem?.event && typeof menuDataItem.event === 'function') { menuDataItem?.event(props.rowDataItem, props.columnKey); } }, }); const transformMenuEvents = (menuData: Array<BentoColumnCellActionMenuItem>) => menuData.map(menuDataItem => { const transformedMenuData = menuDataItem; if (transformedMenuData?.items) { transformedMenuData.items = transformMenuEvents(transformedMenuData.items); } return { ...generateMenuEvents(transformedMenuData) }; }); const getCopyText = (button: BentoColumnCellAction) => button?.getCopyData !== undefined ? button.getCopyData(props.rowDataItem, props.columnKey) : props.columnKey ? (props.rowDataItem?.[props.columnKey]?.toString() as string) : ''; const shouldShowMenuIconLeft = (button: BentoColumnCellAction) => button.iconLeft || button?.variant === 'more'; </script> <script lang="ts"> /** * Internal component to display the data-grid actions. * There are 4 different pre-defined buttons that can be used by using the `variant` property. * * The component renders buttons or a menu depending on the actions provided. * * @example * <data-grid-cell-actions * :cell-actions="[ * { variant: 'edit', event: () => {} }, * { * variant: 'more', * isShort: true, * menuData: [ * { * text: 'Cancel payment', * handler: () => {}), * critical: true, * }, * { * text: 'Transfer payment', * handler: () => {}, * }, * { * text: 'Delete payment', * handler: () => {}, * disabled: true, * }, * ], * }, * ]" * column-key="payment" * :row-data-item="rowData" * /> */ export default { i18n: { messages }, name: 'data-grid-cell-actions', }; </script> <style lang="scss" scoped src="./data-grid-cell-actions.scss" />
1
+ <template> <Transition name="b-data-grid-cell-actions__animation" appear> <div class="b-data-grid-cell-actions"> <div v-if="showGradientElement && !isTouchDevice" class="b-data-grid-cell-actions__background-gradient" :class="conditionalCellActionsBackgroundGradientClasses" ></div> <div class="b-data-grid-cell-actions__actions" :class="conditionalCellActionsClasses" role="group"> <div v-for="(button, index) in computedCellActions" :key="index" class="b-data-grid-cell-actions__action" > <bento-menu v-if="button.menuData" v-bento-tooltip-directive:[button.tooltipPosition]="button.tooltipText" :data="transformMenuEvents(button.menuData)" :button="{ condensed: true, variant: 'secondary', disabled: button.disabled, 'aria-label': getButtonTitle(button, true), }" :disable-arrow-down-opening-menu="disableArrowDownOpeningMenu" :teleport="teleportMenu" @open="emit('menu-open')" @close="emit('menu-close')" @menu-item-click="emit('menu-item-click')" > <template v-if="shouldShowMenuIconLeft(button)" #iconLeft> <options-vertical-icon v-if="button?.variant === 'more'" :aria-hidden="true" /> <component :is="button.iconLeft" v-else :aria-hidden="true" /> </template> <template v-if="!button?.isShort" #default> {{ getButtonTitle(button) }} </template> </bento-menu> <copy v-else-if="button.variant === 'copy'" :text="getCopyText(button)" :button-text="getButtonTitle(button)" :button="{ condensed: true, variant: 'secondary', }" /> <bento-button v-else v-bento-tooltip-directive:[button.tooltipPosition]="button.tooltipText" condensed variant="secondary" :critical="button.critical" :disabled="button.disabled" :link="button.link" v-on="generateButtonEvents(button)" > <template v-if="button.iconLeft || button.variant === 'edit'" #iconLeft> <edit1-icon v-if="button?.variant === 'edit'" :svg-title="getButtonTitle(button, true)" /> <component :is="button.iconLeft" v-else :svg-title="button.title" /> </template> <template v-if="!button?.isShort" #default> {{ getButtonTitle(button) }} </template> <template v-if="button.iconRight || button.variant === 'open'" #iconRight> <external-link-icon v-if="button?.variant === 'open'" :svg-title="getButtonTitle(button, true)" /> <component :is="button.iconRight" v-else :svg-title="button.title" /> </template> </bento-button> </div> </div> </div> </Transition> </template> <script setup lang="ts"> import { computed, inject, type PropType, ref, type Ref } from 'vue'; import { BentoButton } from '@/components/button'; import { BentoMenu, type BentoMenuItem } from '@/components/menu'; import { Copy } from '@/internal/copy'; import { BentoTooltipDirective as vBentoTooltipDirective } from '@/directives/tooltip'; import { printDevelopmentWarning } from '@/utils/ts/print-development-warning'; import { type BentoDatagridDataItem } from '@/components/data-grid/data-grid.types'; import { DATA_GRID_TOUCH_DEVICE } from '@/components/data-grid/data-grid.keys'; import Edit1Icon from '@adyen/ui-assets-icons-16/vue/edit-1'; import ExternalLinkIcon from '@adyen/ui-assets-icons-16/vue/external-link'; import OptionsVerticalIcon from '@adyen/ui-assets-icons-16/vue/options-vertical'; // Types import type { BentoColumnCellAction, BentoColumnCellActionMenuItem, BentoColumnCellActions, BentoColumnCellActionsByCellDataFn, BentoColumnCellActionsProp, BentoDataGridRowActionsProp, } from './data-grid-cell-actions.types'; // Translations import messages from './messages.json'; import { useI18n } from '@/utils/ts/i18n'; type MessageSchema = (typeof messages)['en-US']; const { t } = useI18n<{ message: MessageSchema }>({ messages }); const props = defineProps({ /** * Column definitions using 'key' to relate to data object. */ cellActions: { type: [Array, Function] as PropType<BentoColumnCellActionsProp | BentoDataGridRowActionsProp>, required: true, validator: (value: BentoColumnCellActions) => value?.length <= 2, }, /** * The column field key. */ columnKey: { type: String, default: undefined, }, /** * Disables any opening of the cell actions menus using the down arrow key. */ disableArrowDownOpeningMenu: { type: Boolean, default: false, }, /** * Set to true if the datagrid has been scrolled and the right side has overflowing space. */ hasRightOverflow: { type: Boolean, default: false, }, /** * Set to true if the row has a darker background when zebra rows is enabled. */ hasZebraBackground: { type: Boolean, default: false, }, /** * Set to true if the row is selected. */ isSelected: { type: Boolean, default: false, }, /** * Set to true if the row is highlighted. */ isHighlighted: { type: Boolean, default: false, }, /** * Set if set to true will teleport the action menu component */ teleportMenu: { type: Boolean, default: false, }, /** * The row data item object. */ rowDataItem: { type: Object as PropType<BentoDatagridDataItem>, required: true, }, }); const emit = defineEmits<{ /** * Emits when a cell actions menu is opened */ (e: 'menu-open'): void; /** * Emits when a cell actions menu is closed */ (e: 'menu-close'): void; /** * Emits when a cell actions menu button closes due to a menu item click */ (e: 'menu-item-click'): void; }>(); const isTouchDevice: Ref<boolean> = inject(DATA_GRID_TOUCH_DEVICE, ref(false)); // Helper to get text for menu items, always returning a string const getMenuItemText = (action: BentoColumnCellAction | BentoColumnCellActionMenuItem) => { // If it's already a menu item with a text property, use it if ('text' in action && action.text !== undefined) { return action.text; } // Otherwise, derive from variant or title switch ((action as BentoColumnCellAction).variant) { case 'copy': return t('copy'); case 'edit': return t('edit'); case 'open': return t('open'); case 'more': return t('more'); default: return (action as BentoColumnCellAction).title; } }; const getMenuItemIcon = (action: BentoColumnCellAction) => { switch (action.variant) { case 'copy': return Copy; case 'edit': return Edit1Icon; case 'open': return ExternalLinkIcon; default: return undefined; } }; const isRowActions = computed(() => props.columnKey === undefined); const conditionalCellActionsBackgroundGradientClasses = computed(() => ({ 'b-data-grid-cell-actions__background-gradient--with-row-actions-and-overflow': isRowActions.value && props.hasRightOverflow, 'b-data-grid-cell-actions__background-gradient--zebra': props.hasZebraBackground, 'b-data-grid-cell-actions__background-gradient--highlighted': props.isHighlighted, 'b-data-grid-cell-actions__background-gradient--selected': props.isSelected, })); const conditionalCellActionsClasses = computed(() => ({ 'b-data-grid-cell-actions__actions--with-row-actions': isRowActions.value, 'b-data-grid-cell-actions__actions--zebra': props.hasZebraBackground, 'b-data-grid-cell-actions__actions--highlighted': props.isHighlighted, 'b-data-grid-cell-actions__actions--selected': props.isSelected, 'b-data-grid-cell-actions__actions--zebra-hover': !isRowActions.value && props.hasZebraBackground, 'b-data-grid-cell-actions__actions--highlighted-hover': !isRowActions.value && props.isHighlighted, 'b-data-grid-cell-actions__actions--selected-hover': !isRowActions.value && props.isSelected, })); const showGradientElement = computed(() => !isRowActions.value || (isRowActions.value && props.hasRightOverflow)); /** * Checks if the passed object is a cell actions function that returns an cell actions array. * @param cellActions - a cell actions array or function */ function isBentoColumnCellActionsByCellValueDataFn( cellActions: BentoColumnCellActionsProp ): cellActions is BentoColumnCellActionsByCellDataFn { return typeof cellActions === 'function'; } const computedCellActions = computed(() => { const cellActions = isBentoColumnCellActionsByCellValueDataFn(props.cellActions) ? props.cellActions?.(props.rowDataItem, props.columnKey) : props.cellActions; if (isTouchDevice.value && !isRowActions.value && cellActions) { const flattenedMenuItems: Array<BentoColumnCellActionMenuItem> = []; cellActions.forEach(action => { if (action.menuData) { action.menuData.forEach(subMenuItem => { flattenedMenuItems.push(subMenuItem); }); } else { flattenedMenuItems.push({ text: getMenuItemText(action), event: action.event, critical: action.critical, disabled: action.disabled, icon: getMenuItemIcon(action), }); } }); return [ { variant: 'more', isShort: true, iconLeft: OptionsVerticalIcon, menuData: transformMenuEvents(flattenedMenuItems), }, ] as BentoColumnCellActions; } // Do not allow users to provide more than 2 cell action buttons if (!isTouchDevice.value && cellActions?.length > 2) { printDevelopmentWarning( 'WARNING: BentoDataGrid Cell actions can only have a maximum of 2 actions, if you need more consider using the menuData property instead.' ); } return cellActions?.slice(0, 2); }); const getButtonTitle = computed(() => (button: BentoColumnCellAction, isForSvgTitle?: boolean) => { if ((!isForSvgTitle && button.isShort) || (isForSvgTitle && !button.isShort)) { return undefined; } switch (button.variant) { case 'copy': return t('copy'); case 'edit': return t('edit'); case 'open': return t('open'); case 'more': return t('more'); default: return button.title; } }); const generateButtonEvents = (button: BentoColumnCellAction) => button?.event !== undefined ? { click: (event: MouseEvent) => { event.stopPropagation(); button.event(props.rowDataItem, props.columnKey); }, } : {}; const generateMenuEvents = (menuDataItem: BentoColumnCellActionMenuItem): BentoMenuItem => ({ ...menuDataItem, handler: () => { if (menuDataItem?.event && typeof menuDataItem.event === 'function') { menuDataItem?.event(props.rowDataItem, props.columnKey); } }, }); const transformMenuEvents = (menuData: Array<BentoColumnCellActionMenuItem>) => menuData.map(menuDataItem => { const transformedMenuData = menuDataItem; if (transformedMenuData?.items) { transformedMenuData.items = transformMenuEvents(transformedMenuData.items); } return { ...generateMenuEvents(transformedMenuData) }; }); const getCopyText = (button: BentoColumnCellAction) => button?.getCopyData !== undefined ? button.getCopyData(props.rowDataItem, props.columnKey) : props.columnKey ? (props.rowDataItem?.[props.columnKey]?.toString() as string) : ''; const shouldShowMenuIconLeft = (button: BentoColumnCellAction) => button.iconLeft || button?.variant === 'more'; </script> <script lang="ts"> /** * Internal component to display the data-grid actions. * There are 4 different pre-defined buttons that can be used by using the `variant` property. * * The component renders buttons or a menu depending on the actions provided. * * @example * <data-grid-cell-actions * :cell-actions="[ * { variant: 'edit', event: () => {} }, * { * variant: 'more', * isShort: true, * menuData: [ * { * text: 'Cancel payment', * event: () => {}, * critical: true, * }, * { * text: 'Transfer payment', * event: () => {}, * }, * { * text: 'Delete payment', * event: () => {}, * disabled: true, * }, * ], * }, * ]" * column-key="payment" * :row-data-item="rowData" * /> */ export default { i18n: { messages }, name: 'data-grid-cell-actions', }; </script> <style lang="scss" scoped src="./data-grid-cell-actions.scss" />
@@ -1 +1 @@
1
- <!-- TODO: Remove aria props from search-bar as these name clashes with JSX type /vue/types/jsx.d.ts --> <!-- eslint-disable vue/attribute-hyphenation --> <template> <div v-bento-click-outside-directive="onClickOutside" class="b-data-grid-config-settings"> <div class="b-data-grid-config-settings__button-and-separator"> <div ref="configSettingsButtonRef" class="b-data-grid-config-settings__button-container"> <bento-toggle-button :aria-controls="isConfigSettingsPanelOpen ? popoverId : null" variant="tertiary" condensed :toggled="isConfigSettingsPanelOpen" @click="setConfigSettingsPanelVisibility(!isConfigSettingsPanelOpen)" > <template #iconLeft> <bento-settings-icon :svg-title="t('toggleConfigSettingsPanelVisibility')" /> </template> </bento-toggle-button> </div> </div> <bento-popover v-if="configSettingsButtonRef" :id="popoverId" :open="isConfigSettingsPanelOpen" class="b-data-grid-config-settings__panel" :aria-label="t('configSettingsPanel')" :target-element="configSettingsButtonRef" position="bottom-end" > <div class="b-data-grid-config-settings__panel-header"> <bento-typography el="span" strongest> {{ t('displayOptions') }} </bento-typography> <bento-button variant="tertiary" @click="setConfigSettingsPanelVisibility(false)"> <template #iconLeft> <bento-cross-icon :svg-title="t('closeConfigSettingsPanel')" /> </template> </bento-button> </div> <div class="b-data-grid-config-settings__appearance"> <bento-typography class="b-data-grid-config-settings__appearance-title" el="span" stronger> {{ t('appearance') }} </bento-typography> <div class="b-data-grid-config-settings__appearance-button"> <bento-toggle label-position="after" :aria-label="t('condensedToggle')" :value="condensed" @input="emitCondensedToggle" > {{ t('condensed') }} </bento-toggle> </div> <div class="b-data-grid-config-settings__appearance-button"> <bento-toggle label-position="after" :aria-label="t('zebraRowsToggle')" :value="zebraRows" @input="emitZebraRowsToggle" > {{ t('zebraRows') }} </bento-toggle> </div> </div> <div class="b-data-grid-config-settings__column-visibility-settings"> <div class="b-data-grid-config-settings__column-visibility-header"> <bento-typography class="b-data-grid-config-settings__column-visibility-title" el="span" stronger> {{ t('columns') }} </bento-typography> <bento-button v-if="!isColumnVisibilityFilterShown" ref="searchButtonRef" variant="tertiary" @click="toggleColumnFilter" > <template #iconLeft><bento-search-icon /> </template>{{ t('search') }}</bento-button > <bento-button v-else variant="tertiary" @click="toggleColumnFilter"> <template #iconLeft> <bento-cross-icon /> </template> {{ t('closeSearch') }} </bento-button> </div> <div v-if="isColumnVisibilityFilterShown" class="b-data-grid-config-settings__column-visibility-search"> <bento-search-bar ref="searchBarRef" :value="searchTerm" :input-field-aria-label="t('columnVisibilitySearchFilter').toString()" @input="searchTerm = $event" @clear="clearAction" @escape-pressed="toggleColumnFilter" /> </div> <div v-else class="b-data-grid-config-settings__column-visibility-show-all"> <bento-toggle label-position="after" :value="allColumnsVisbilityToggleState" @input="toggleAllColumnVisibility" > {{ t('showAllColumns', { numberOfColumns: columns.length }) }} </bento-toggle> </div> <div class="b-data-grid-config-settings__column-visibility-toggles"> <div v-for="column of filteredColumnVisibilityColumns" :key="column.field"> <bento-data-grid-config-settings-config-row v-if="column.field !== DATAGRID_ACTIONS_COLUMN_FIELD_NAME" :column="column" :is-column-visibility-toggle-disabled="isColumnVisibilityToggleDisabled(column)" @visible-column="emitVisibleColumns" @updated-column="emitFrozenColumns" /> </div> <bento-typography v-if="filteredColumnVisibilityColumns.length === 0" el="span" class="b-data-grid-config-settings__column-visibility-empty-search-message" > {{ t('noColumnsMatch') }} </bento-typography> </div> </div> </bento-popover> </div> </template> <script lang="ts"> import { computed, defineComponent, nextTick, type PropType, ref, toRef } from 'vue'; import { BentoPopover } from '@/components/popover'; import { BentoButton, BentoToggleButton } from '@/components/button'; import { BentoTypography } from '@/components/typography'; import { BentoToggle } from '@/components/toggle'; import { type BentoColumn } from '../../data-grid.types'; import BentoSearchBar from '@/components/search-bar/search-bar.vue'; import { BentoClickOutsideDirective } from '@/directives'; import { DatagridConfigSettingsEvent } from './data-grid-config-settings.types'; import { useSearchBarFilter } from '@/components/search-bar'; import { generateUid } from '@/core/utils/ts'; import { DATAGRID_ACTIONS_COLUMN_FIELD_NAME } from '../../composables'; import { useI18n } from '@/utils/ts/i18n'; import BentoSettingsIcon from '@adyen/ui-assets-icons-16/vue/settings'; import BentoCrossIcon from '@adyen/ui-assets-icons-16/vue/cross'; import BentoSearchIcon from '@adyen/ui-assets-icons-16/vue/search'; import BentoDataGridConfigSettingsConfigRow from './components/data-grid-config-settings-column-row/data-grid-config-settings-column-row.vue'; import messages from './messages.json'; type MessageSchema = (typeof messages)['en-US']; export default defineComponent({ i18n: { messages }, name: 'bento-data-grid', components: { BentoButton, BentoCrossIcon, BentoPopover, BentoSettingsIcon, BentoToggleButton, BentoDataGridConfigSettingsConfigRow, BentoSearchBar, BentoSearchIcon, BentoToggle, BentoTypography, }, directives: { BentoClickOutsideDirective }, props: { /** * Column definitions */ columns: { type: Array as PropType<Array<BentoColumn>>, required: true, }, /** * Sets the row cells to the condensed padding state. */ condensed: { type: Boolean, default: false, }, /** * Sets a different background color for even rows. */ zebraRows: { type: Boolean, default: false, }, }, emits: [ DatagridConfigSettingsEvent.UPDATE_CONDENSED, DatagridConfigSettingsEvent.UPDATE_COLUMNS, DatagridConfigSettingsEvent.UPDATE_ZEBRA_ROWS, ], setup(props, { emit }) { const { t } = useI18n<{ message: MessageSchema }>({ messages }); const configSettingsButtonRef = ref(null); const popoverId = generateUid('data-grid-config-settings-popover'); const searchBarRef = ref(null); const isConfigSettingsPanelOpen = ref<boolean>(false); const allColumnsVisbilityToggleState = ref<boolean>(true); const searchButtonRef = ref(null); const searchTerm = ref<string>(''); const columnsRef = toRef(props, 'columns'); const isColumnVisibilityFilterShown = ref<boolean>(false); // Column Visibility Filtering const filteredColumnVisibilityColumns = useSearchBarFilter<BentoColumn>(searchTerm, columnsRef); const clearAction = () => { searchTerm.value = ''; }; const areAllNonMandatoryColumnsHidden = computed( () => !props.columns.some(col => col.visible === false && !col.mandatory) ); const toggleColumnFilter = () => { clearAction(); isColumnVisibilityFilterShown.value = !isColumnVisibilityFilterShown.value; if (isColumnVisibilityFilterShown.value) { nextTick(() => searchBarRef.value.$refs.bentoInputField?.focusInput()); } else { nextTick(() => searchButtonRef?.value?.$el?.focus()); } allColumnsVisbilityToggleState.value = areAllNonMandatoryColumnsHidden.value; }; // Column visibility const isColumnVisibilityToggleDisabled = (column: BentoColumn) => column.mandatory ?? false; const emitVisibleColumns = (updatedColumn: BentoColumn) => { const updatedColumns = props.columns.map(col => ({ ...col, visible: updatedColumn.field === col.field ? updatedColumn.visible : col.visible, })); emit(DatagridConfigSettingsEvent.UPDATE_COLUMNS, updatedColumns); }; const toggleAllColumnVisibility = (toggleState: boolean) => { if (toggleState) { // Show all columns emit( DatagridConfigSettingsEvent.UPDATE_COLUMNS, props.columns.map(col => ({ ...col, visible: true })) ); } else { // Hide all columns except for mandatory columns emit( DatagridConfigSettingsEvent.UPDATE_COLUMNS, props.columns.map(col => ({ ...col, visible: col?.mandatory === true })) ); } }; // Column freeze // TODO to convert this function to 'emitUpdatedColumns', that will emit both: visible and frozen columns const emitFrozenColumns = (updatedColumn: BentoColumn) => { const updatedColumns = props.columns.map(col => ({ ...col, frozen: updatedColumn.field === col.field ? !!updatedColumn?.frozen : !!col?.frozen, })); emit(DatagridConfigSettingsEvent.UPDATE_COLUMNS, updatedColumns); }; // Panel visibility const setConfigSettingsPanelVisibility = (isVisible: boolean) => { isConfigSettingsPanelOpen.value = isVisible; allColumnsVisbilityToggleState.value = areAllNonMandatoryColumnsHidden.value; }; const onClickOutside = () => setConfigSettingsPanelVisibility(false); // Condensed view const emitCondensedToggle = (isCondensedView: boolean) => emit(DatagridConfigSettingsEvent.UPDATE_CONDENSED, isCondensedView); const emitZebraRowsToggle = (isZebraRows: boolean) => emit(DatagridConfigSettingsEvent.UPDATE_ZEBRA_ROWS, isZebraRows); return { // Values configSettingsButtonRef, popoverId, isConfigSettingsPanelOpen, allColumnsVisbilityToggleState, filteredColumnVisibilityColumns, searchTerm, isColumnVisibilityFilterShown, searchBarRef, searchButtonRef, DATAGRID_ACTIONS_COLUMN_FIELD_NAME, // Methods setConfigSettingsPanelVisibility, emitCondensedToggle, toggleAllColumnVisibility, clearAction, toggleColumnFilter, emitVisibleColumns, emitFrozenColumns, onClickOutside, isColumnVisibilityToggleDisabled, emitZebraRowsToggle, // Translations t, }; }, }); </script> <style lang="scss" scoped src="./data-grid-config-settings.scss" />
1
+ <!-- TODO: Remove aria props from search-bar as these name clashes with JSX type /vue/types/jsx.d.ts --> <!-- eslint-disable vue/attribute-hyphenation --> <template> <div v-bento-click-outside-directive="onClickOutside" class="b-data-grid-config-settings"> <div class="b-data-grid-config-settings__button-and-separator"> <div ref="configSettingsButtonRef" class="b-data-grid-config-settings__button-container"> <bento-toggle-button :aria-controls="isConfigSettingsPanelOpen ? popoverId : null" variant="tertiary" condensed :toggled="isConfigSettingsPanelOpen" @click="setConfigSettingsPanelVisibility(!isConfigSettingsPanelOpen)" > <template #iconLeft> <bento-settings-icon :svg-title="t('toggleConfigSettingsPanelVisibility')" /> </template> </bento-toggle-button> </div> </div> <bento-popover v-if="configSettingsButtonRef" :id="popoverId" :open="isConfigSettingsPanelOpen" class="b-data-grid-config-settings__panel" :aria-label="t('configSettingsPanel')" :target-element="configSettingsButtonRef" position="bottom-end" > <div class="b-data-grid-config-settings__panel-header"> <bento-typography el="span" strongest> {{ t('displayOptions') }} </bento-typography> <bento-button variant="tertiary" @click="setConfigSettingsPanelVisibility(false)"> <template #iconLeft> <bento-cross-icon :svg-title="t('closeConfigSettingsPanel')" /> </template> </bento-button> </div> <div class="b-data-grid-config-settings__appearance"> <bento-typography class="b-data-grid-config-settings__appearance-title" el="span" stronger> {{ t('appearance') }} </bento-typography> <div class="b-data-grid-config-settings__appearance-button"> <bento-toggle label-position="after" :aria-label="t('condensedToggle')" :value="condensed" @input="emitCondensedToggle" > {{ t('condensed') }} </bento-toggle> </div> <div class="b-data-grid-config-settings__appearance-button"> <bento-toggle label-position="after" :aria-label="t('zebraRowsToggle')" :value="zebraRows" @input="emitZebraRowsToggle" > {{ t('zebraRows') }} </bento-toggle> </div> </div> <div class="b-data-grid-config-settings__column-visibility-settings"> <div class="b-data-grid-config-settings__column-visibility-header"> <bento-typography class="b-data-grid-config-settings__column-visibility-title" el="span" stronger> {{ t('columns') }} </bento-typography> <bento-button v-if="!isColumnVisibilityFilterShown" ref="searchButtonRef" variant="tertiary" @click="toggleColumnFilter" > <template #iconLeft><bento-search-icon /> </template>{{ t('search') }}</bento-button > <bento-button v-else variant="tertiary" @click="toggleColumnFilter"> <template #iconLeft> <bento-cross-icon /> </template> {{ t('closeSearch') }} </bento-button> </div> <div v-if="isColumnVisibilityFilterShown" class="b-data-grid-config-settings__column-visibility-search"> <bento-search-bar ref="searchBarRef" :value="searchTerm" :input-field-aria-label="t('columnVisibilitySearchFilter').toString()" @input="searchTerm = $event" @clear="clearAction" @escape-pressed="toggleColumnFilter" /> </div> <div v-else class="b-data-grid-config-settings__column-visibility-show-all"> <bento-toggle label-position="after" :value="allColumnsVisbilityToggleState" @input="toggleAllColumnVisibility" > {{ t('showAllColumns', { numberOfColumns: columns.length }) }} </bento-toggle> </div> <div class="b-data-grid-config-settings__column-visibility-toggles"> <div v-for="column of filteredColumnVisibilityColumns" :key="column.field"> <bento-data-grid-config-settings-config-row v-if="column.field !== DATAGRID_ACTIONS_COLUMN_FIELD_NAME" :column="column" :is-column-visibility-toggle-disabled="isColumnVisibilityToggleDisabled(column)" @visible-column="emitVisibleColumns" @updated-column="emitFrozenColumns" /> </div> <bento-typography v-if="filteredColumnVisibilityColumns.length === 0" el="span" class="b-data-grid-config-settings__column-visibility-empty-search-message" > {{ t('noColumnsMatch') }} </bento-typography> </div> </div> </bento-popover> </div> </template> <script lang="ts"> import { computed, defineComponent, nextTick, type PropType, ref, toRef } from 'vue'; import { BentoPopover } from '@/components/popover'; import { BentoButton, BentoToggleButton } from '@/components/button'; import { BentoTypography } from '@/components/typography'; import { BentoToggle } from '@/components/toggle'; import { type BentoColumn } from '../../data-grid.types'; import BentoSearchBar from '@/components/search-bar/search-bar.vue'; import { BentoClickOutsideDirective } from '@/directives'; import { DatagridConfigSettingsEvent } from './data-grid-config-settings.types'; import { useSearchBarFilter } from '@/components/search-bar'; import { generateUid } from '@/utils/ts/generate-uid'; import { DATAGRID_ACTIONS_COLUMN_FIELD_NAME } from '../../composables'; import { useI18n } from '@/utils/ts/i18n'; import BentoSettingsIcon from '@adyen/ui-assets-icons-16/vue/settings'; import BentoCrossIcon from '@adyen/ui-assets-icons-16/vue/cross'; import BentoSearchIcon from '@adyen/ui-assets-icons-16/vue/search'; import BentoDataGridConfigSettingsConfigRow from './components/data-grid-config-settings-column-row/data-grid-config-settings-column-row.vue'; import messages from './messages.json'; type MessageSchema = (typeof messages)['en-US']; export default defineComponent({ i18n: { messages }, name: 'bento-data-grid', components: { BentoButton, BentoCrossIcon, BentoPopover, BentoSettingsIcon, BentoToggleButton, BentoDataGridConfigSettingsConfigRow, BentoSearchBar, BentoSearchIcon, BentoToggle, BentoTypography, }, directives: { BentoClickOutsideDirective }, props: { /** * Column definitions */ columns: { type: Array as PropType<Array<BentoColumn>>, required: true, }, /** * Sets the row cells to the condensed padding state. */ condensed: { type: Boolean, default: false, }, /** * Sets a different background color for even rows. */ zebraRows: { type: Boolean, default: false, }, }, emits: [ DatagridConfigSettingsEvent.UPDATE_CONDENSED, DatagridConfigSettingsEvent.UPDATE_COLUMNS, DatagridConfigSettingsEvent.UPDATE_ZEBRA_ROWS, ], setup(props, { emit }) { const { t } = useI18n<{ message: MessageSchema }>({ messages }); const configSettingsButtonRef = ref(null); const popoverId = generateUid('data-grid-config-settings-popover'); const searchBarRef = ref(null); const isConfigSettingsPanelOpen = ref<boolean>(false); const allColumnsVisbilityToggleState = ref<boolean>(true); const searchButtonRef = ref(null); const searchTerm = ref<string>(''); const columnsRef = toRef(props, 'columns'); const isColumnVisibilityFilterShown = ref<boolean>(false); // Column Visibility Filtering const filteredColumnVisibilityColumns = useSearchBarFilter<BentoColumn>(searchTerm, columnsRef); const clearAction = () => { searchTerm.value = ''; }; const areAllNonMandatoryColumnsHidden = computed( () => !props.columns.some(col => col.visible === false && !col.mandatory) ); const toggleColumnFilter = () => { clearAction(); isColumnVisibilityFilterShown.value = !isColumnVisibilityFilterShown.value; if (isColumnVisibilityFilterShown.value) { nextTick(() => searchBarRef.value.$refs.bentoInputField?.focusInput()); } else { nextTick(() => searchButtonRef?.value?.$el?.focus()); } allColumnsVisbilityToggleState.value = areAllNonMandatoryColumnsHidden.value; }; // Column visibility const isColumnVisibilityToggleDisabled = (column: BentoColumn) => column.mandatory ?? false; const emitVisibleColumns = (updatedColumn: BentoColumn) => { const updatedColumns = props.columns.map(col => ({ ...col, visible: updatedColumn.field === col.field ? updatedColumn.visible : col.visible, })); emit(DatagridConfigSettingsEvent.UPDATE_COLUMNS, updatedColumns); }; const toggleAllColumnVisibility = (toggleState: boolean) => { if (toggleState) { // Show all columns emit( DatagridConfigSettingsEvent.UPDATE_COLUMNS, props.columns.map(col => ({ ...col, visible: true })) ); } else { // Hide all columns except for mandatory columns emit( DatagridConfigSettingsEvent.UPDATE_COLUMNS, props.columns.map(col => ({ ...col, visible: col?.mandatory === true })) ); } }; // Column freeze // TODO to convert this function to 'emitUpdatedColumns', that will emit both: visible and frozen columns const emitFrozenColumns = (updatedColumn: BentoColumn) => { const updatedColumns = props.columns.map(col => ({ ...col, frozen: updatedColumn.field === col.field ? !!updatedColumn?.frozen : !!col?.frozen, })); emit(DatagridConfigSettingsEvent.UPDATE_COLUMNS, updatedColumns); }; // Panel visibility const setConfigSettingsPanelVisibility = (isVisible: boolean) => { isConfigSettingsPanelOpen.value = isVisible; allColumnsVisbilityToggleState.value = areAllNonMandatoryColumnsHidden.value; }; const onClickOutside = () => setConfigSettingsPanelVisibility(false); // Condensed view const emitCondensedToggle = (isCondensedView: boolean) => emit(DatagridConfigSettingsEvent.UPDATE_CONDENSED, isCondensedView); const emitZebraRowsToggle = (isZebraRows: boolean) => emit(DatagridConfigSettingsEvent.UPDATE_ZEBRA_ROWS, isZebraRows); return { // Values configSettingsButtonRef, popoverId, isConfigSettingsPanelOpen, allColumnsVisbilityToggleState, filteredColumnVisibilityColumns, searchTerm, isColumnVisibilityFilterShown, searchBarRef, searchButtonRef, DATAGRID_ACTIONS_COLUMN_FIELD_NAME, // Methods setConfigSettingsPanelVisibility, emitCondensedToggle, toggleAllColumnVisibility, clearAction, toggleColumnFilter, emitVisibleColumns, emitFrozenColumns, onClickOutside, isColumnVisibilityToggleDisabled, emitZebraRowsToggle, // Translations t, }; }, }); </script> <style lang="scss" scoped src="./data-grid-config-settings.scss" />