@adyen/bento-mcp 0.1.4 → 0.3.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 (198) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/README.md +50 -5
  3. package/SKILL.md +188 -0
  4. package/bin/add-skill.js +46 -0
  5. package/dist/assets/components/accordion/accordion.types.ts +1 -0
  6. package/dist/assets/components/action-bar/action-bar.types.ts +1 -0
  7. package/dist/assets/components/ai-tag/ai-tag.types.ts +1 -0
  8. package/dist/assets/components/alert/alert.types.ts +1 -0
  9. package/dist/assets/components/anchor-scroller/anchor-scroller.types.ts +1 -0
  10. package/dist/assets/components/anchor-scroller/components/anchor-scroller-list/anchor-scroller-list.types.ts +1 -0
  11. package/dist/assets/components/avatar/components/avatar-image/avatar-image.types.ts +1 -0
  12. package/dist/assets/components/button/button.types.ts +1 -0
  13. package/dist/assets/components/button/components/ai-button/ai-button.types.ts +1 -0
  14. package/dist/assets/components/button/components/button-actions/button-actions.types.ts +1 -0
  15. package/dist/assets/components/button/components/loading-button/loading-button.types.ts +1 -0
  16. package/dist/assets/components/button/components/toggle-button/toggle.types.ts +1 -0
  17. package/dist/assets/components/card/card.types.ts +1 -0
  18. package/dist/assets/components/checkbox/checkbox.types.ts +1 -0
  19. package/dist/assets/components/checkbox/components/checkbox-group/checkbox-group.types.ts +1 -0
  20. package/dist/assets/components/chip/chip.types.ts +1 -0
  21. package/dist/assets/components/code-snippet/code-snippet.types.ts +1 -0
  22. package/dist/assets/components/country/country.types.ts +1 -0
  23. package/dist/assets/components/currency/currency.types.ts +1 -0
  24. package/dist/assets/components/dashed-underline/dashed-underline.types.ts +1 -0
  25. package/dist/assets/components/data-grid/components/data-grid-cell/data-grid-cell.types.ts +1 -0
  26. package/dist/assets/components/data-grid/components/data-grid-cell/data-grid-cell.vue +1 -1
  27. package/dist/assets/components/data-grid/components/data-grid-cell-actions/data-grid-cell-actions.types.ts +1 -0
  28. package/dist/assets/components/data-grid/components/data-grid-columns/data-grid-columns.types.ts +1 -0
  29. package/dist/assets/components/data-grid/components/data-grid-columns/data-grid-columns.vue +1 -1
  30. package/dist/assets/components/data-grid/components/data-grid-config-settings/data-grid-config-settings.types.ts +1 -0
  31. package/dist/assets/components/data-grid/components/data-grid-row/data-grid-row.types.ts +1 -0
  32. package/dist/assets/components/data-grid/components/data-grid-row/data-grid-row.vue +1 -1
  33. package/dist/assets/components/data-grid/components/data-grid-static-icon/data-grid-static-icon.types.ts +1 -0
  34. package/dist/assets/components/data-grid/components/data-grid-summary-cell/data-grid-summary-cell.types.ts +1 -0
  35. package/dist/assets/components/data-grid/components/data-grid-tag-with-text-cell/data-grid-tag-with-text-cell.types.ts +1 -0
  36. package/dist/assets/components/data-grid/components/data-grid-trend-cell/data-grid-trend-cell.types.ts +1 -0
  37. package/dist/assets/components/data-grid/composables/use-calculate-column-width/use-calculate-column-width.types.ts +1 -0
  38. package/dist/assets/components/data-grid/composables/use-column-hovering/use-column-hovering.types.ts +1 -0
  39. package/dist/assets/components/data-grid/composables/use-config-settings/use-config.settings.types.ts +1 -0
  40. package/dist/assets/components/data-grid/composables/use-keyboard-navigator/use-keyboard-navigator.types.ts +1 -0
  41. package/dist/assets/components/data-grid/data-grid.types.ts +1 -0
  42. package/dist/assets/components/data-grid/data-grid.vue +1 -1
  43. package/dist/assets/components/date/date.types.ts +1 -0
  44. package/dist/assets/components/date-picker/composables/use-date-picker-single-calendar-text.types.ts +1 -0
  45. package/dist/assets/components/date-picker/date-picker.types.ts +1 -0
  46. package/dist/assets/components/date-range-picker/components/date-range-picker-calendar/date-range-picker-calendar.types.ts +1 -0
  47. package/dist/assets/components/date-range-picker/components/date-range-picker-calendar/date-range-picker-calendar.vue +1 -1
  48. package/dist/assets/components/date-range-picker/composables/use-date-range-picker-calendar-text.types.ts +1 -0
  49. package/dist/assets/components/date-range-picker/composables/use-granularity-memory.types.ts +1 -0
  50. package/dist/assets/components/date-range-picker/date-range-picker.types.ts +1 -0
  51. package/dist/assets/components/divider/divider.types.ts +1 -0
  52. package/dist/assets/components/draggable-handle/draggable-handle.types.ts +1 -0
  53. package/dist/assets/components/dropdown/components/dropdown-base-textbox/dropdown-base-textbox.types.ts +1 -0
  54. package/dist/assets/components/dropdown/components/variants/dropdown-avatar/dropdown-avatar.types.ts +1 -0
  55. package/dist/assets/components/dropdown/components/variants/dropdown-country/dropdown-country.types.ts +1 -0
  56. package/dist/assets/components/dropdown/components/variants/dropdown-currency/dropdown-currency.types.ts +1 -0
  57. package/dist/assets/components/dropdown/components/variants/dropdown-payment-method/dropdown-payment-method.types.ts +1 -0
  58. package/dist/assets/components/dropdown/components/variants/dropdown-tag/dropdown-tag.types.ts +1 -0
  59. package/dist/assets/components/dropdown/composables/use-display-value.types.ts +1 -0
  60. package/dist/assets/components/dropdown/composables/use-keyboard-navigation.types.ts +1 -0
  61. package/dist/assets/components/dropdown/dropdown.types.ts +1 -0
  62. package/dist/assets/components/empty-state/empty-state.types.ts +1 -0
  63. package/dist/assets/components/file-uploader/components/file-uploader-file-card/file-uploader-file-card.types.ts +1 -0
  64. package/dist/assets/components/file-uploader/components/file-uploader-restrictions/file-uploader-restrictions.types.ts +1 -0
  65. package/dist/assets/components/file-uploader/composables/use-drag-drop-state/use-drag-drop-state.types.ts +1 -0
  66. package/dist/assets/components/file-uploader/file-uploader.types.ts +1 -0
  67. package/dist/assets/components/filter-bar/components/all-filters-modal/all-filters-modal.types.ts +1 -0
  68. package/dist/assets/components/filter-bar/components/all-filters-modal/all-filters-modal.vue +1 -1
  69. package/dist/assets/components/filter-bar/components/base-filter/base-filter.types.ts +1 -0
  70. package/dist/assets/components/filter-bar/components/checkbox-group-filter/checkbox-group-filter.types.ts +1 -0
  71. package/dist/assets/components/filter-bar/components/filter-bar-button-group/filter-bar-button-group.types.ts +1 -0
  72. package/dist/assets/components/filter-bar/components/input-filter/input-filter.types.ts +1 -0
  73. package/dist/assets/components/filter-bar/components/radio-group-filter/radio-group-filter.types.ts +1 -0
  74. package/dist/assets/components/filter-bar/components/toggle-filter/toggle-filter.types.ts +1 -0
  75. package/dist/assets/components/filter-bar/filter-bar.types.ts +1 -0
  76. package/dist/assets/components/focus-trap/focus-trap.types.ts +1 -0
  77. package/dist/assets/components/form-layout/components/form-layout-field-tip/form-layout-tip.types.ts +1 -0
  78. package/dist/assets/components/form-layout/components/form-layout-group/form-layout-group.types.ts +1 -0
  79. package/dist/assets/components/form-layout/form-layout.types.ts +1 -0
  80. package/dist/assets/components/header/header.types.ts +1 -0
  81. package/dist/assets/components/header-with-views/components/header-with-views-all-views/header-with-views-all-views.types.ts +1 -0
  82. package/dist/assets/components/header-with-views/components/header-with-views-item-edit-form/header-with-views-edit-form.types.ts +1 -0
  83. package/dist/assets/components/header-with-views/header-with-views.types.ts +1 -0
  84. package/dist/assets/components/image/image.types.ts +1 -0
  85. package/dist/assets/components/info-icon/info-icon.types.ts +1 -0
  86. package/dist/assets/components/input-field/input-field.types.ts +1 -0
  87. package/dist/assets/components/input-field-password/input-field-password.types.ts +1 -0
  88. package/dist/assets/components/input-field-phone-number/input-field-phone-number.types.ts +1 -0
  89. package/dist/assets/components/input-time/input-time.docs.mdx +52 -0
  90. package/dist/assets/components/input-time/input-time.stories.ts +1 -0
  91. package/dist/assets/components/input-time/input-time.types.ts +1 -0
  92. package/dist/assets/components/input-time/input-time.vue +1 -0
  93. package/dist/assets/components/inspector/inspector.types.ts +1 -0
  94. package/dist/assets/components/internal/base-button/base-button.types.ts +1 -0
  95. package/dist/assets/components/internal/button-actions-with-menu/button-actions-with-menu.types.ts +1 -0
  96. package/dist/assets/components/internal/calendar/calendar.types.ts +1 -0
  97. package/dist/assets/components/internal/calendar/components/calendar-month/calendar-month.types.ts +1 -0
  98. package/dist/assets/components/internal/calendar/components/calendar-month/components/calendar-month-day/calendar-month-day.types.ts +1 -0
  99. package/dist/assets/components/internal/calendar/components/calendar-month/composables/granular-min-max-date.types.ts +1 -0
  100. package/dist/assets/components/internal/calendar/components/calendar-year/calendar-year.types.ts +1 -0
  101. package/dist/assets/components/internal/calendar/components/calendar-year/components/calendar-year-month/calendar-year-month.types.ts +1 -0
  102. package/dist/assets/components/internal/calendar/composables/use-granularity-adjustments.types.ts +1 -0
  103. package/dist/assets/components/internal/checkbox-input/checkbox-input.types.ts +1 -0
  104. package/dist/assets/components/internal/copy/copy.types.ts +1 -0
  105. package/dist/assets/components/internal/dialog-page/dialog-page.types.ts +1 -0
  106. package/dist/assets/components/internal/grid-layout/grid-layout.types.ts +1 -0
  107. package/dist/assets/components/internal/header-meta/header-meta.types.ts +1 -0
  108. 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 +1 -0
  109. package/dist/assets/components/internal/listbox/components/listbox-multi-select/components/listbox-multi-select-options/listbox-multi-select-options.types.ts +1 -0
  110. package/dist/assets/components/internal/listbox/components/listbox-multi-select/listbox-multi-select.types.ts +1 -0
  111. package/dist/assets/components/internal/listbox/listbox.types.ts +1 -0
  112. package/dist/assets/components/internal/radio-input/radio-input.types.ts +1 -0
  113. package/dist/assets/components/internal/teleport/teleport.types.ts +1 -0
  114. package/dist/assets/components/internal/tooltip/tooltip.types.ts +1 -0
  115. package/dist/assets/components/layout/layout.types.ts +1 -0
  116. package/dist/assets/components/link/link.types.ts +1 -0
  117. package/dist/assets/components/list/components/list-item/list-item.stories.ts +1 -0
  118. package/dist/assets/components/list/components/list-item/list-item.types.ts +1 -0
  119. package/dist/assets/components/list/components/list-item/list-item.vue +1 -0
  120. package/dist/assets/components/list/list.docs.mdx +97 -0
  121. package/dist/assets/components/list/list.stories.ts +1 -0
  122. package/dist/assets/components/list/list.types.ts +1 -0
  123. package/dist/assets/components/list/list.vue +1 -0
  124. package/dist/assets/components/loading-indicator/loading-indicator.types.ts +1 -0
  125. package/dist/assets/components/menu/components/menu-item/menu-item.types.ts +1 -0
  126. package/dist/assets/components/menu/menu.types.ts +1 -0
  127. package/dist/assets/components/modal/components/modal-page/modal-page.types.ts +1 -0
  128. package/dist/assets/components/modal/modal.types.ts +1 -0
  129. package/dist/assets/components/pagination/pagination.types.ts +1 -0
  130. package/dist/assets/components/payment-method/payment-method.types.ts +1 -0
  131. package/dist/assets/components/popover/popover.types.ts +1 -0
  132. package/dist/assets/components/popper-container/popper-container.types.ts +1 -0
  133. package/dist/assets/components/promo-banner/promo-banner.types.ts +1 -0
  134. package/dist/assets/components/radio-group/components/radio-button/radio-button.types.ts +1 -0
  135. package/dist/assets/components/radio-group/radio-group.types.ts +1 -0
  136. package/dist/assets/components/rich-text-editor/components/rich-text-editor-content-area/rich-text-editor-content-area.types.ts +1 -0
  137. package/dist/assets/components/rich-text-editor/components/rich-text-editor-renderer/components/rich-text-editor-code-block/rich-text-editor-code-block.types.ts +1 -0
  138. package/dist/assets/components/rich-text-editor/components/rich-text-editor-renderer/components/rich-text-editor-inline-code/rich-text-editor-inline-code.types.ts +1 -0
  139. package/dist/assets/components/rich-text-editor/components/rich-text-editor-renderer/components/rich-text-editor-link/rich-text-editor-link.types.ts +1 -0
  140. package/dist/assets/components/rich-text-editor/components/rich-text-editor-renderer/components/rich-text-editor-list-item/rich-text-editor-list-item.types.ts +1 -0
  141. package/dist/assets/components/rich-text-editor/components/rich-text-editor-renderer/rich-text-editor-renderer.types.ts +1 -0
  142. package/dist/assets/components/rich-text-editor/rich-text-editor.types.ts +1 -0
  143. package/dist/assets/components/search-bar/search-bar.types.ts +1 -0
  144. package/dist/assets/components/secondary-nav/components/secondary-nav-category/secondary-nav-category.vue +1 -1
  145. package/dist/assets/components/secondary-nav/components/secondary-nav-item/secondary-nav-item.vue +1 -1
  146. package/dist/assets/components/secondary-nav/secondary-nav.docs.mdx +32 -2
  147. package/dist/assets/components/secondary-nav/secondary-nav.stories.ts +1 -1
  148. package/dist/assets/components/secondary-nav/secondary-nav.types.ts +1 -0
  149. package/dist/assets/components/secondary-nav/secondary-nav.vue +1 -1
  150. package/dist/assets/components/segmented-control/segmented-control.types.ts +1 -0
  151. package/dist/assets/components/selection-card/components/selection-card-group/selection-card-group.types.ts +1 -0
  152. package/dist/assets/components/selection-card/selection-card.types.ts +1 -0
  153. package/dist/assets/components/sidepanel/sidepanel.types.ts +1 -0
  154. package/dist/assets/components/status/status.types.ts +1 -0
  155. package/dist/assets/components/stepper/stepper.types.ts +1 -0
  156. package/dist/assets/components/structured-list/structured-list.types.ts +1 -0
  157. package/dist/assets/components/summary-grid/components/summary-grid-item/summary-grid-item.types.ts +1 -0
  158. package/dist/assets/components/summary-grid/components/summary-grid-item-amount/summary-grid-item-amount.types.ts +1 -0
  159. package/dist/assets/components/summary-grid/components/summary-grid-item-custom/summary-grid-item-custom.types.ts +1 -0
  160. package/dist/assets/components/summary-grid/components/summary-grid-item-numeric/summary-grid-item-numeric.types.ts +1 -0
  161. package/dist/assets/components/summary-grid/components/summary-grid-item-percentage/summary-grid-item-percentage.types.ts +1 -0
  162. package/dist/assets/components/summary-grid/components/summary-grid-item-text/summary-grid-item-text.types.ts +1 -0
  163. package/dist/assets/components/summary-grid/summary-grid.types.ts +1 -0
  164. package/dist/assets/components/tabs/components/tab.types.ts +1 -0
  165. package/dist/assets/components/tabs/tabs.types.ts +1 -0
  166. package/dist/assets/components/tag/tag.types.ts +1 -0
  167. package/dist/assets/components/textarea/textarea.types.ts +1 -0
  168. package/dist/assets/components/timeline/components/timeline-item/timeline-item.vue +1 -1
  169. package/dist/assets/components/timeline/timeline.stories.ts +1 -1
  170. package/dist/assets/components/timeline/timeline.types.ts +1 -0
  171. package/dist/assets/components/toast/components/toast-shadow-stack/toast-shadow-stack.types.ts +1 -0
  172. package/dist/assets/components/toggle/toggle.types.ts +1 -0
  173. package/dist/assets/components/tutorial/tutorial.types.ts +1 -0
  174. package/dist/assets/components/typography/typography.types.ts +1 -0
  175. package/dist/assets/components.json +102 -0
  176. package/dist/assets/composables/use-bento-theme/install.ts +1 -0
  177. package/dist/assets/composables/use-bento-theme/install.types.ts +1 -0
  178. package/dist/assets/composables/use-bento-theme/use-bento-theme.types.ts +1 -0
  179. package/dist/assets/composables/use-bento-toast-controller/install.ts +1 -0
  180. package/dist/assets/composables/use-bento-toast-controller/use-bento-toast-controller.types.ts +1 -0
  181. package/dist/assets/composables/use-form-validate/use-form.types.ts +1 -0
  182. package/dist/assets/composables/use-form-validate-zod-4/use-form.types.ts +1 -0
  183. package/dist/assets/composables/use-virtual-list/use-virtual-list.types.ts +1 -0
  184. package/dist/assets/deprecations.md +330 -0
  185. package/dist/assets/directives/keyboard-navigation/keyboard-navigation.types.ts +1 -0
  186. package/dist/assets/directives/tooltip/tooltip.types.ts +1 -0
  187. package/dist/assets/icons.json +415 -0
  188. package/dist/assets/index.ts +1 -1
  189. package/dist/assets/install.ts +1 -0
  190. package/dist/assets/tailwind/README.md +89 -0
  191. package/dist/assets/templates/dashboard-template/dashboard-template.types.ts +1 -0
  192. package/dist/assets/templates/data-grid-template/data-grid-template.stories.ts +1 -1
  193. package/dist/assets/templates/data-grid-template/data-grid-template.types.ts +1 -0
  194. package/dist/assets/utility-classes.md +92 -0
  195. package/dist/assets/utils/ts/currency/currency.types.ts +1 -0
  196. package/dist/assets/variables.css +309 -0
  197. package/dist/main.js +395 -29
  198. package/package.json +15 -6
@@ -14,7 +14,7 @@ understand and navigate through various information.
14
14
 
15
15
  Use a SecondaryNav if:
16
16
 
17
- - You need to organize information in a way that offers users structural guidance for complex pages like settings.
17
+ - You need to organize information in a way that offers users structural guidance for complex pages like settings.
18
18
 
19
19
  ## Variations
20
20
 
@@ -22,6 +22,36 @@ Use a SecondaryNav if:
22
22
 
23
23
  <Canvas of={SecondaryNavStories.WithCategories} />
24
24
 
25
+ ### With sub-items
26
+
27
+ Sub-items can be used to add an extra navigation level. Depending on the use case, items sith sub-items may link to
28
+ their own pages or just be used to organise items further.
29
+
30
+ <Canvas of={SecondaryNavStories.WithSubItems} />
31
+
32
+ #### Parent items without a page
33
+
34
+ By default (`allowExpandableItemNavigation` is `false`), clicking anywhere on a parent item expands or collapses its
35
+ sub-items. The parent item itself is not selectable and does not emit a `change` event.
36
+
37
+ #### Parent items with a page
38
+
39
+ When `allowExpandableItemNavigation` is `true`, parent items link to their own pages. Clicking the item label navigates
40
+ to that page and emits a `change` event, while the chevron button exclusively controls expanding and collapsing
41
+ sub-items.
42
+
43
+ ## Behavior
44
+
45
+ ### Desktop
46
+
47
+ - For items with sub-items, expanding/collapsing is controlled by the caret button.
48
+ - If `value` points to a sub-item, parent items auto-expand so the selected item is visible.
49
+
50
+ ### Mobile
51
+
52
+ - On mobile, `bento-secondary-nav` renders a `bento-dropdown`.
53
+ - Categories are shown as static category labels and nested items are shown with visual indentation.
54
+
25
55
  ## Accessibility
26
56
 
27
57
  ### Keyboard interaction
@@ -37,4 +67,4 @@ page. The following keys trigger the following actions:
37
67
 
38
68
  ## Resources
39
69
 
40
- - [Figma link](https://www.figma.com/design/uLabwF3243jdMDsNSP7U9I/Bento---Components?node-id=25227-18624&t=2F6m9PIJUQlVcUJj-0)
70
+ - [Figma link](https://www.figma.com/design/uLabwF3243jdMDsNSP7U9I/Bento---Components?node-id=25227-18624&t=2F6m9PIJUQlVcUJj-0)
@@ -1 +1 @@
1
- import { action } from '@storybook/addon-actions'; import { isVue2 } from 'vue-demi'; import { storybookDocsParameter } from '@/utils/ts/storybook'; import BentoSecondaryNav from './secondary-nav.vue'; import type { Meta, StoryObj } from '@storybook/vue'; import { type BentoSecondaryNavItems } from '@/components/secondary-nav/secondary-nav.types'; const meta: Meta = { title: 'Secondary Nav', component: BentoSecondaryNav, }; export default meta; type Story = StoryObj<typeof BentoSecondaryNav>; const DEFAULT_ITEMS: BentoSecondaryNavItems = [ { label: 'Option 1', value: 'option_1', }, { label: 'Option 2', value: 'option_2', }, { label: 'Option 3', value: 'option_3', }, ]; const ITEMS_WITH_CATEGORIES: BentoSecondaryNavItems = [ { label: 'Category 1', items: [ { label: 'Option 1', value: 'option_1', }, { label: 'Option 2', value: 'option_2', }, ], }, { label: 'Category 2', items: [ { label: 'Option 3', value: 'option_3', }, { label: 'Option 4', value: 'option_4', }, { label: 'Option 5', value: 'option_5', }, ], }, ]; const DEFAULT_STORY_CODE_SAMPLE = ` <template> <bento-secondary-nav :items="items" :value="activeItem" @change="onChange" /> <template> <script lang="ts" setup> const items = [ { label: 'Option 1', value: 'option_1', }, { label: 'Option 2', value: 'option_2', }, { label: 'Option 3', value: 'option_3', }, ]; const activeItem = ref(items[0].value); const onChange = (newActiveItem: string) => { activeItem.value = newActiveItem; }; </script> `; export const Default: Story = { render: (_args, { argTypes }) => ({ components: { BentoSecondaryNav, }, props: Object.keys(argTypes), template: ` <bento-secondary-nav v-bind="args" @change="clickedAction" /> `, setup(props) { const clickedAction = value => action('change')(value); return { // Values args: isVue2 ? props : _args, // Events clickedAction, }; }, }), args: { items: DEFAULT_ITEMS, value: 'option_1', }, parameters: storybookDocsParameter(DEFAULT_STORY_CODE_SAMPLE), }; const WITH_CATEGORIES_STORY_CODE_SAMPLE = ` <template> <bento-secondary-nav :items="items" :value="activeItem" @change="onChange" /> <template> <script lang="ts" setup> const items = [ { label: 'Category 1', items: [ { label: 'Option 1', value: 'option_1', }, { label: 'Option 2', value: 'option_2', }, ], }, { label: 'Category 2', items: [ { label: 'Option 3', value: 'option_3', }, { label: 'Option 4', value: 'option_4', }, { label: 'Option 5', value: 'option_5', }, ], }, ]; const activeItem = ref(items[0].value); const onChange = (newActiveItem: string) => { activeItem.value = newActiveItem; }; </script> `; export const WithCategories: Story = { render: (_args, { argTypes }) => ({ components: { BentoSecondaryNav, }, props: Object.keys(argTypes), template: ` <bento-secondary-nav v-bind="args" @change="clickedAction" /> `, setup(props) { const clickedAction = value => action('change')(value); return { // Values args: isVue2 ? props : _args, // Events clickedAction, }; }, }), args: { items: ITEMS_WITH_CATEGORIES, }, parameters: storybookDocsParameter(WITH_CATEGORIES_STORY_CODE_SAMPLE), };
1
+ import { action } from '@storybook/addon-actions'; import { isVue2 } from 'vue-demi'; import { storybookDocsParameter } from '@/utils/ts/storybook'; import BentoSecondaryNav from './secondary-nav.vue'; import WithSubItemsCodeSample from './__tests__/secondary-nav-with-sub-items.vue?raw'; import type { Meta, StoryObj } from '@storybook/vue'; import { type BentoSecondaryNavItems } from '@/components/secondary-nav/secondary-nav.types'; const meta: Meta = { title: 'Secondary Nav', component: BentoSecondaryNav, }; export default meta; type Story = StoryObj<typeof BentoSecondaryNav>; const DEFAULT_ITEMS: BentoSecondaryNavItems = [ { label: 'Option 1', value: 'option_1', }, { label: 'Option 2', value: 'option_2', }, { label: 'Option 3', value: 'option_3', }, ]; const ITEMS_WITH_CATEGORIES: BentoSecondaryNavItems = [ { label: 'Category 1', items: [ { label: 'Option 1', value: 'option_1', }, { label: 'Option 2', value: 'option_2', }, ], }, { label: 'Category 2', items: [ { label: 'Option 3', value: 'option_3', }, { label: 'Option 4', value: 'option_4', }, { label: 'Option 5', value: 'option_5', }, ], }, ]; const ITEMS_WITH_SUB_ITEMS: BentoSecondaryNavItems = ITEMS_WITH_CATEGORIES.map(category => ({ ...category, items: category.items.map(item => { if (item.value === 'option_2') { return { ...item, items: [ { label: 'Option 2.1', value: 'option_2_1', }, { label: 'Option 2.2', value: 'option_2_2', }, ], }; } if (item.value === 'option_4') { return { ...item, items: [ { label: 'Option 4.1', value: 'option_4_1', }, { label: 'Option 4.2', value: 'option_4_2', }, ], }; } return item; }), })); const DEFAULT_STORY_CODE_SAMPLE = ` <template> <bento-secondary-nav :items="items" :value="activeItem" @change="onChange" /> <template> <script lang="ts" setup> const items = [ { label: 'Option 1', value: 'option_1', }, { label: 'Option 2', value: 'option_2', }, { label: 'Option 3', value: 'option_3', }, ]; const activeItem = ref(items[0].value); const onChange = (newActiveItem: string) => { activeItem.value = newActiveItem; }; </script> `; export const Default: Story = { render: (_args, { argTypes }) => ({ components: { BentoSecondaryNav, }, props: Object.keys(argTypes), template: ` <bento-secondary-nav v-bind="args" @change="clickedAction" /> `, setup(props) { const clickedAction = value => action('change')(value); return { // Values args: isVue2 ? props : _args, // Events clickedAction, }; }, }), args: { items: DEFAULT_ITEMS, value: 'option_1', }, parameters: storybookDocsParameter(DEFAULT_STORY_CODE_SAMPLE), }; const WITH_CATEGORIES_STORY_CODE_SAMPLE = ` <template> <bento-secondary-nav :items="items" :value="activeItem" @change="onChange" /> <template> <script lang="ts" setup> const items = [ { label: 'Category 1', items: [ { label: 'Option 1', value: 'option_1', }, { label: 'Option 2', value: 'option_2', }, ], }, { label: 'Category 2', items: [ { label: 'Option 3', value: 'option_3', }, { label: 'Option 4', value: 'option_4', }, { label: 'Option 5', value: 'option_5', }, ], }, ]; const activeItem = ref(items[0].value); const onChange = (newActiveItem: string) => { activeItem.value = newActiveItem; }; </script> `; export const WithCategories: Story = { render: (_args, { argTypes }) => ({ components: { BentoSecondaryNav, }, props: Object.keys(argTypes), template: ` <bento-secondary-nav v-bind="args" @change="clickedAction" /> `, setup(props) { const clickedAction = value => action('change')(value); return { // Values args: isVue2 ? props : _args, // Events clickedAction, }; }, }), args: { items: ITEMS_WITH_CATEGORIES, }, parameters: storybookDocsParameter(WITH_CATEGORIES_STORY_CODE_SAMPLE), }; export const WithSubItems: Story = { render: (_args, { argTypes }) => ({ components: { BentoSecondaryNav, }, props: Object.keys(argTypes), template: ` <bento-secondary-nav v-bind="args" @change="clickedAction" /> `, setup(props) { const clickedAction = value => action('change')(value); return { args: isVue2 ? props : _args, clickedAction, }; }, }), args: { value: 'option_2_1', items: ITEMS_WITH_SUB_ITEMS, }, parameters: storybookDocsParameter(WithSubItemsCodeSample), };
@@ -0,0 +1 @@
1
+ import type { Ref } from 'vue'; export interface BentoSecondaryNavState { activeItemValue: Ref<string>; updateActiveItemValue: (id: string) => void; allowExpandableItemNavigation: Ref<boolean>; } export interface BentoSecondaryNavItemsItem { label: string; value: string; items?: Array<BentoSecondaryNavItemsItem>; } export interface BentoSecondaryNavItemsCategory { label: string; items: Array<BentoSecondaryNavItemsItem>; } export type BentoSecondaryNavItems = Array<BentoSecondaryNavItemsItem | BentoSecondaryNavItemsCategory>;
@@ -1 +1 @@
1
- <template> <nav class="b-secondary-nav"> <bento-dropdown v-if="isMobile" :aria-label="t('mobileDropdownAriaLabel')" :items="dropdownItems" :static-categories="hasCategories" :model-value="activeItemValue" @update:model-value="updateActiveItemValue" /> <ul v-else class="b-secondary-nav__list"> <li v-for="item in items" :key="item.label"> <secondary-nav-category v-if="'items' in item" :label="item.label" :items="item.items" /> <secondary-nav-item v-else :label="item.label" :value="item.value" /> </li> </ul> </nav> </template> <script setup lang="ts"> import { computed, provide, readonly, ref, watch } from 'vue'; import { SecondaryNavItem } from './components/secondary-nav-item'; import { SecondaryNavCategory } from './components/secondary-nav-category'; import { SECONDARY_NAV_STATE } from './secondary-nav.keys'; import { type BentoSecondaryNavItems, type BentoSecondaryNavState } from './secondary-nav.types'; import { BentoDropdown } from '@/components/dropdown'; import { useBreakpoints } from '@vueuse/core'; import { useI18n } from '@/utils/ts/i18n'; import { type BentoListboxOptions } from '@/types/listbox'; import { BMediaQuerySMax } from '@adyen/bento-design-tokens/dist/js/bento/es6'; import messages from './messages.json'; type MessageSchema = (typeof messages)['en-US']; const { t } = useI18n<{ message: MessageSchema }>({ messages }); const breakpoints = useBreakpoints({ s: BMediaQuerySMax, }); const isMobile = breakpoints.smallerOrEqual('s'); const props = defineProps<{ /** * An array containing all the items on the nav. The array can have either {@see BentoSecondaryNavItemsCategory }, * which is used to group different items or {@see BentoSecondaryNavItemsItem } if you don't need to group them. */ items: BentoSecondaryNavItems; /** * The value of the selected item. * If nothing is passed, it defaults to the first item value in items. */ value?: string; }>(); const emit = defineEmits<{ /** * Emmited when the current selected item changes */ (e: 'change', category: string): void; }>(); const hasCategories = computed(() => props.items.some(item => Object.hasOwn(item, 'items'))); const dropdownItems = computed(() => props.items as BentoListboxOptions); const activeItemValueFallback = computed(() => { const firstDropdownItem = (dropdownItems.value as BentoSecondaryNavItems)[0]; if ('items' in firstDropdownItem) { return firstDropdownItem.items[0].value; } else { return firstDropdownItem.value; } }); const activeItemValue = ref(props.value ?? activeItemValueFallback.value); const updateActiveItemValue = (value: string) => { activeItemValue.value = value; emit('change', value); }; // The component's state is inject on `secondary-nav-item` to determine the // current active item and to change its value const state: BentoSecondaryNavState = { activeItemValue: readonly(activeItemValue), updateActiveItemValue, }; watch( () => props.value, value => { activeItemValue.value = value; } ); provide(SECONDARY_NAV_STATE, state); </script> <script lang="ts"> /** * Secondary Nav offers users a structured way to access information. * It also provides a clear hierarchy for users to understand and navigate through various information. * * @example * import { BentoSecondaryNav } from '@adyen/bento-vue2'; * * export default { * components: { BentoSecondaryNav }, * template: ` * <bento-secondary-nav :value="value" :items="items" /> * `, * setup() { * const value = ref(2) // Active item value * const items: BentoSecondaryNavItemInfo[] = [ * { label: 'Option 1', value: 1 }, * { label: 'Option 2', value: 2 }, * ]; * return { items, value }; * } * } */ export default { i18n: { messages }, }; </script> <style lang="scss" scoped src="./secondary-nav.scss" />
1
+ <template> <nav class="b-secondary-nav"> <bento-dropdown v-if="isMobile" :aria-label="t('mobileDropdownAriaLabel')" :items="mobileDropdownItems" :static-categories="hasCategories" :model-value="activeItemValue" :is-option-disabled="isMobileOptionDisabled" @update:model-value="updateActiveItemValue" > <template #display-value="{ label }"> <bento-typography el="span"> {{ label }} </bento-typography> </template> <template #default="{ label, data }"> <bento-typography el="span" :class="{ 'b-secondary-nav__nested-option': !!data?.level }"> {{ label }} </bento-typography> </template> </bento-dropdown> <ul v-else class="b-secondary-nav__list"> <li v-for="item in items" :key="item.label"> <secondary-nav-category v-if="'items' in item && !('value' in item)" :label="item.label" :items="item.items" /> <secondary-nav-item v-else :label="item.label" :value="item.value" :items="item.items" /> </li> </ul> </nav> </template> <script setup lang="ts"> import { computed, provide, readonly, ref, toRef, watch } from 'vue'; import { SecondaryNavItem } from './components/secondary-nav-item'; import { SecondaryNavCategory } from './components/secondary-nav-category'; import { SECONDARY_NAV_STATE } from './secondary-nav.keys'; import { type BentoSecondaryNavItems, type BentoSecondaryNavItemsCategory, type BentoSecondaryNavItemsItem, type BentoSecondaryNavState, } from './secondary-nav.types'; import { BentoDropdown } from '@/components/dropdown'; import { BentoTypography } from '@/components/typography'; import { useBreakpoints } from '@vueuse/core'; import { useI18n } from '@/utils/ts/i18n'; import { type BentoListboxOptionItem, type BentoListboxOptions } from '@/types/listbox'; import { BMediaQuerySMax } from '@adyen/bento-design-tokens/dist/js/bento/es6'; import messages from './messages.json'; type MessageSchema = (typeof messages)['en-US']; const { t } = useI18n<{ message: MessageSchema }>({ messages }); const breakpoints = useBreakpoints({ s: BMediaQuerySMax, }); const isMobile = breakpoints.smallerOrEqual('s'); const props = defineProps<{ /** * An array containing all the items on the nav. The array can have either {@see BentoSecondaryNavItemsCategory }, * which is used to group different items or {@see BentoSecondaryNavItemsItem } if you don't need to group them. */ items: BentoSecondaryNavItems; /** * The value of the selected item. * If nothing is passed, it defaults to the first item value in items. */ value?: string; /** * When true, items that contain subitems are also clickable and can be selected. * When false, those items only act as expand/collapse toggles. */ allowExpandableItemNavigation?: boolean; }>(); const emit = defineEmits<{ /** * Emmited when the current selected item changes */ (e: 'change', category: string): void; }>(); const isCategory = (item: BentoSecondaryNavItems[number]): item is BentoSecondaryNavItemsCategory => 'items' in item && !('value' in item); const mapNestedItems = (items: Array<BentoSecondaryNavItemsItem>, level = 0): BentoListboxOptions => items.flatMap((item): BentoListboxOptions => { const currentItem: BentoListboxOptionItem = { label: item.label, value: item.value, data: { level, hasSubItems: !!item.items?.length }, }; if (item.items?.length) { return [currentItem, ...mapNestedItems(item.items, level + 1)]; } return [currentItem]; }); const isMobileOptionDisabled = (option: BentoListboxOptionItem): boolean => !props.allowExpandableItemNavigation && (option.data as { hasSubItems?: boolean })?.hasSubItems; const hasCategories = computed(() => props.items.some(item => isCategory(item))); const mobileDropdownItems = computed<BentoListboxOptions>(() => { return props.items.flatMap(item => { if (isCategory(item)) { return [ { label: item.label, value: `category-${item.label}`, items: mapNestedItems(item.items), } satisfies BentoListboxOptionItem, ]; } if (item.items?.length) { return mapNestedItems([item]); } return [ { label: item.label, value: item.value, data: { level: 0 }, } satisfies BentoListboxOptionItem, ]; }); }); const flattenNestedItems = (items: Array<BentoSecondaryNavItemsItem>): Array<BentoSecondaryNavItemsItem> => items.flatMap(item => [item, ...(item.items?.length ? flattenNestedItems(item.items) : [])]); const findFirstSelectableNestedItemValue = (items: Array<BentoSecondaryNavItemsItem>): string => flattenNestedItems(items).find(item => props.allowExpandableItemNavigation || !item.items?.length)?.value ?? ''; const activeItemValueFallback = computed(() => { if (!props.items.length) { return ''; } return findFirstSelectableNestedItemValue( props.items.flatMap(item => isCategory(item) ? flattenNestedItems(item.items) : flattenNestedItems([item]) ) ); }); const activeItemValue = ref(props.value ?? activeItemValueFallback.value); const updateActiveItemValue = (value: string) => { activeItemValue.value = value; emit('change', value); }; // The component's state is inject on `secondary-nav-item` to determine the // current active item and to change its value const state: BentoSecondaryNavState = { activeItemValue: readonly(activeItemValue), updateActiveItemValue, allowExpandableItemNavigation: toRef(props, 'allowExpandableItemNavigation'), }; watch( () => props.value, value => { if (value !== undefined) { activeItemValue.value = value; } } ); provide(SECONDARY_NAV_STATE, state); </script> <script lang="ts"> /** * Secondary Nav offers users a structured way to access information. * It also provides a clear hierarchy for users to understand and navigate through various information. * * @example * import { BentoSecondaryNav } from '@adyen/bento-vue2'; * * export default { * components: { BentoSecondaryNav }, * template: ` * <bento-secondary-nav :value="value" :items="items" /> * `, * setup() { * const value = ref(2) // Active item value * const items: BentoSecondaryNavItemInfo[] = [ * { label: 'Option 1', value: 1 }, * { label: 'Option 2', value: 2 }, * ]; * return { items, value }; * } * } */ export default { i18n: { messages }, }; </script> <style lang="scss" scoped src="./secondary-nav.scss" />
@@ -0,0 +1 @@
1
+ export type BentoSegmentedControlValue = string | number; export interface BentoSegmentedControlProps { /** * Accessible name describing the segmented control. * @deprecated from version 2.0.0. Use the aria-label attribute instead. */ ariaLabel?: string; /** * If set to true, renders the component full width. */ fullWidth?: boolean; /** * Items that will populate the segmented control. */ items: Array<BentoSegmentedControlItem>; /** * Determines the selected value of the group. Corresponds to the BentoSegmentedControlItem's value. */ modelValue?: BentoSegmentedControlValue; /** * If set to true, wraps the items in the segmented control to show their content whenever these don't fit in the available space anymore. */ wrap?: boolean; } export interface BentoSegmentedControlItem { label: string; value: string | number; disabled?: boolean; } /** * @deprecated from version 2.0.0. Use "@update:model-value" or "v-model" instead */ export enum BentoSegmentedControlEvent { UPDATE = 'update:model-value', }
@@ -0,0 +1 @@
1
+ import { type GridLayoutColumnWidth } from '@/internal'; import type { BentoSelectionCardItem, BentoSelectionCardModelValue } from '@/components/selection-card'; import { type FormField, type FormFieldEmits } from '../../../../types/form-field'; export type BentoSelectionCardGroupVariant = 'checkbox' | 'radio'; export type BentoSelectionCardGroupLayout = 'horizontal' | 'vertical'; export type BentoSelectionCardGroupItemsPerRow = GridLayoutColumnWidth; export type BentoSelectionCardGroupEmits = FormFieldEmits<BentoSelectionCardModelValue>; export interface BentoSelectionCardGroupProps extends FormField { /** * The form id the selection card group is associated with. Defaults to null, as a selection card group can also be * used standalone. * @default null */ formId?: string; /** * Shows/hides the group label. * @default null */ hideLabel?: boolean; /** * The selection card group's layout. It can be vertical or horizontal. Defaults to vertical. * @values horizontal, vertical * @default vertical */ layout?: BentoSelectionCardGroupLayout; /** * The selection card group's items. */ items: Array<BentoSelectionCardItem>; /** * Sets the responsive number of items rendered in each row. * @default undefined */ itemsPerRow?: BentoSelectionCardGroupItemsPerRow; /** * Determines the initially selected value of the group. Corresponds to the BentoSelectionCardItem's value. * @default null */ modelValue?: BentoSelectionCardModelValue; /** * Renders the cards with a checkbox or a radio input. Selection logic will also apply in accordance. * @values checkbox, radio * @default checkbox */ variant?: BentoSelectionCardGroupVariant; }
@@ -0,0 +1 @@
1
+ import { type RadioInputValue } from '@/components/internal/radio-input'; import { type BentoCheckboxType } from '../checkbox/checkbox.types'; import { type VueNodeElement } from '@/types/elements'; export enum BentoSelectionCardState { DISABLED = 'disabled', READONLY = 'readonly', ERROR = 'error', } export type BentoSelectionCardValue = string | number; export type BentoSelectionCardModelValue = BentoCheckboxType | RadioInputValue; export interface BentoSelectionCardItem { content?: string | object; description?: string; disabled?: boolean; dynamicContent?: string | object; fullyClickable?: boolean; hasError?: boolean; icon?: VueNodeElement; readonly?: boolean; subtitle?: string; title: string; value: BentoSelectionCardValue; }
@@ -0,0 +1 @@
1
+ export enum BentoSidepanelEvent { UPDATE_ACTIVE_PAGE = 'update:active-page', UPDATE_IS_OPEN = 'update:is-open', }
@@ -0,0 +1 @@
1
+ /** * @deprecated for usage with properties since version 2.0. Use the string literal instead. */ export enum BentoStatusVariant { BLUE = 'blue', GREEN = 'green', GREY = 'grey', ORANGE = 'orange', RED = 'red', YELLOW = 'yellow', } export interface BentoStatusProps { /** * Defines the type and color of the Status */ variant: BentoStatusVariant | `${BentoStatusVariant}`; }
@@ -0,0 +1 @@
1
+ import type { ComputedRef, Ref, UnwrapRef } from 'vue'; export enum BentoStepperTypeOption { LINEAR = 'linear', NON_LINEAR = 'non-linear', } export enum BentoStepperVariantOption { HORIZONTAL = 'horizontal', VERTICAL = 'vertical', } export interface BentoStepperStepExposeState { buttonElement: HTMLButtonElement | Ref<UnwrapRef<HTMLButtonElement>>; substeps: Array<BentoStepperStepExposeState> | Ref<Array<BentoStepperStepExposeState>>; stepContent: string | ComputedRef<string>; } export type BentoStepperState = Ref<{ activeStepIndex: number; latestActiveStep: number; type: `${BentoStepperTypeOption}`; variant: `${BentoStepperVariantOption}`; steps: Array<HTMLElement>; isParentStep?: boolean; navigateToStep: (index: number) => void; registerStep: (stepState: BentoStepperStepExposeState) => void; removeStep: (stepState: BentoStepperStepExposeState) => void; }>;
@@ -0,0 +1 @@
1
+ export type BentoStructuredListLayoutOptions = '25-75' | '33-66' | '42-58' | '50-50' | '75-25' | '66-33' | '58-42'; export const BentoStructuredListLayoutOptions = ['25-75', '33-66', '42-58', '50-50', '75-25', '66-33', '58-42'];
@@ -0,0 +1 @@
1
+ import type { BentoDashedUnderlineProps } from '@/components/dashed-underline'; import type { BentoSummaryGridItemSize, BentoSummaryGridItemTrendDirection } from '../../summary-grid.types'; /** * @deprecated for usage with properties since version 2.0. Use the string literal instead. */ export enum SummaryGridItemType { AMOUNT = 'amount', PERCENTAGE = 'percentage', NUMERIC = 'numeric', TEXT = 'text', CUSTOM = 'custom', } export interface BaseSummaryGridItemProps { /** * Text to copy to the clipboard */ copy?: string; /** * The width of `summary-grid-item` fits its content */ fitContent?: boolean; /** * Text showed in the info-icon tooltip on hover */ infoIconTooltipText?: string; // amount, percentage and numeric props /** * Defines the size of the `summary-grid-item` text content */ // TODO implement logic for Large size size?: `${BentoSummaryGridItemSize}`; /** * Text used as a title */ title: string; /** * Shows colored trend label next to text content */ trend?: string; /** * Defines the color of trend label */ trendDirection?: `${BentoSummaryGridItemTrendDirection}`; /** * Shows colored trend tag next to secondary metric value */ secondaryTrend?: string; /** * Defines the color of secondary trend tag */ secondaryTrendDirection?: `${BentoSummaryGridItemTrendDirection}`; /** * Size of the popover of a dashed-underline title */ underlinePopoverSize?: BentoDashedUnderlineProps['popoverSize']; /** * Text showed in a dashed-underline title tooltip on hover */ underlineTooltipText?: string; } export interface BentoSummaryGridItemProps extends BaseSummaryGridItemProps { /** * Applies styling based on content type */ // TODO add text truncation for SummaryGridItemType.TEXT itemType?: `${SummaryGridItemType}`; }
@@ -0,0 +1 @@
1
+ import type { BaseSummaryGridItemProps } from '../summary-grid-item/summary-grid-item.types'; export interface BentoSummaryGridItemAmountProps extends BaseSummaryGridItemProps { /** * Amount to be shown as the main value */ label: string; /** * Adds additional label next to amount content */ secondaryLabel?: string; /** * Amount to be shown as the secondary metric value */ secondaryMetric?: string; }
@@ -0,0 +1 @@
1
+ import type { BentoDashedUnderlineProps } from '@/components/dashed-underline'; export interface BentoSummaryGridItemCustomProps { /** * Text to copy to the clipboard */ copy?: string; /** * Text showed in the info-icon tooltip on hover */ infoIconTooltipText?: string; /** * Text used as a title */ title: string; /** * The width of `summary-grid-item` fits its content */ fitContent?: boolean; /** * Size of the popover of a dashed-underline title */ underlinePopoverSize?: BentoDashedUnderlineProps['popoverSize']; /** * Text showed in a dashed-underline title tooltip on hover */ underlineTooltipText?: string; }
@@ -0,0 +1 @@
1
+ import type { BaseSummaryGridItemProps } from '../summary-grid-item/summary-grid-item.types'; export interface BentoSummaryGridItemNumericProps extends BaseSummaryGridItemProps { /** * Amount to be shown as the main value */ label: string; /** * Amount to be shown as the secondary metric value */ secondaryMetric?: string; }
@@ -0,0 +1 @@
1
+ import type { BaseSummaryGridItemProps } from '../summary-grid-item/summary-grid-item.types'; export interface BentoSummaryGridItemPercentageProps extends BaseSummaryGridItemProps { /** * Amount to be shown as the main value */ label: string | number; /** * Amount to be shown as the secondary metric value */ secondaryMetric?: string | number; }
@@ -0,0 +1 @@
1
+ import type { BentoDashedUnderlineProps } from '@/components/dashed-underline'; export interface BentoSummaryGridItemTextProps { /** * Text to copy to the clipboard */ copy?: string; /** * The width of `summary-grid-item` fits its content */ fitContent?: boolean; /** * Text showed in the info-icon tooltip on hover */ infoIconTooltipText?: string; /** * Amount to be shown as the main value */ label: string; /** * Text used as a title */ title: string; /** * Size of the popover of a dashed-underline title */ underlinePopoverSize?: BentoDashedUnderlineProps['popoverSize']; /** * Text showed in a dashed-underline title tooltip on hover */ underlineTooltipText?: string; }
@@ -0,0 +1 @@
1
+ import { type GridLayoutColumnWidths } from '@/components/internal/grid-layout/grid-layout.types'; /** * @deprecated for usage with properties since version 2.0. Use the string literal instead. */ export enum BentoSummaryGridItemSize { SMALL = 'small', MEDIUM = 'medium', LARGE = 'large', } /** * @deprecated for usage with properties since version 2.0. Use the string literal instead. */ export enum BentoSummaryGridItemTrendDirection { POSITIVE = 'positive', NEGATIVE = 'negative', NEUTRAL = 'neutral', } export interface BentoSummaryGridColumnWidth { row1: GridLayoutColumnWidths; row2?: GridLayoutColumnWidths; row3?: GridLayoutColumnWidths; } export type BentoSummaryGridLayout = () => { isSummaryGridLayout: boolean; }; export interface BentoSummaryGridProps { /** * Sets the responsive columns widths values for 1 of the 3 rows. */ columnWidth?: BentoSummaryGridColumnWidth; /** * Renders a font numeric style with slashed zeros instead of normal ones. */ slashedZero?: boolean; }
@@ -0,0 +1 @@
1
+ import { type Ref } from 'vue'; import { type MaybeRef } from '@/types/maybe-ref'; /** * Public */ export interface BentoTabProps { /** * Displays a counter next to the tab title */ counter?: number; /** * Determines whether the tab is disabled */ disabled?: boolean; /** * Prevents a tab from being displayed. * Use `hidden` instead of `v-show`. */ hidden?: boolean; /** * Title of the tab */ title: string; /** * Displays the tab with a notification indicator */ withNotificationIndicator?: boolean; /** * Callback function to safely capture the underlying DOM element of the tab. * Useful for anchoring tooltips, popovers, or tutorials. * * @example * // 1. Define your ref and setter in setup() * const tabNode = ref<Element | null>(null); * const setTabNode = (el: Element | null) => { tabNode.value = el; }; * * // 2. Pass the setter to the tab * <bento-tab :set-element-ref="setTabNode"> */ setElementRef?: (el: Element | null) => void; } /** * Private */ export interface BentoTab { counter: Ref<number>; disabled: Ref<boolean>; hidden: Ref<boolean>; id: string; title: MaybeRef<string>; withNotificationIndicator: Ref<boolean>; setElementRef: BentoTabProps['setElementRef']; } export type BentoTabProvidedTitle = (value: string) => void;
@@ -0,0 +1 @@
1
+ import type { Ref } from 'vue'; /** * Private */ export interface BentoStickyTabsOptions { top?: Ref<number>; } export type BentoTabsRegisterTab = (props: { counter: Ref<number>; disabled: Ref<boolean>; hidden: Ref<boolean>; title: Ref<string>; withNotificationIndicator: Ref<boolean>; setElementRef: (el: Element | null) => void; }) => { id: string; unregisterTab: () => void }; export enum BentoTabsEvent { ACTIVE_TAB_INDEX = 'update:active-tab-index', }
@@ -0,0 +1 @@
1
+ export interface BentoTagProps { /** * The label text content of the Tag. */ label?: string; /** * The number of characters to limit the number of displayed characters for the tag text, truncating it with an ellipsis of three dots "...". */ truncate?: number; /** * The variant variant of tag */ variant?: BentoTagVariant | `${BentoTagVariant}`; } /** * @deprecated for usage with properties since version 2.0. Use the string literal instead. */ export enum BentoTagVariant { GREY = 'grey', BLUE = 'blue', GREEN = 'green', ORANGE = 'orange', RED = 'red', WHITE = 'white', }
@@ -0,0 +1 @@
1
+ import type { FormField } from '../../types/form-field'; /** * @deprecated for usage with properties since version 2.0. Use the string literal instead. */ export enum BentoTextareaResizeOption { HORIZONTAL = 'horizontal', VERTICAL = 'vertical', BOTH = 'both', NONE = 'none', } export enum BentoTextareaStateClass { CLEARABLE = 'clearable', DISABLED = 'disabled', ERROR = 'error', READONLY = 'readonly', } export enum BentoTextareaEvent { BLUR = 'blur', CHANGE = 'change', CLEAR = 'clear', ESCAPE_PRESSED = 'escape-pressed', FOCUS = 'focus', INPUT = 'input', UPDATE_MODEL_VALUE = 'update:model-value', KEYDOWN = 'keydown', KEYUP = 'keyup', } export interface BentoTextareaProps extends FormField { /** * Text that labels the input element * @default undefined */ ariaLabel?: string; /** * Text that shows number of characters in textarea * @default undefined */ characterLimit?: number; /** * If set to true, shows a button to clear all the text * @default false */ clearable?: boolean; /** * Sets the height of the textarea, e.g 200px OR 20vh * @default null */ height?: string | null; /** * Indicates the possibility of resize the textarea. * Accepts the Enum or the string literal version. * @default BentoTextareaResizeOption.BOTH */ resizable?: BentoTextareaResizeOption | `${BentoTextareaResizeOption}`; /** * Text displayed as the value of the textarea * @deprecated for usage with properties since version 2.0. Use `v-model` or `model-value` instead. */ value?: string; /** * Text displayed as the value of the textarea */ modelValue?: string; }
@@ -1 +1 @@
1
- <template> <li v-if="isVisible" class="b-timeline-item" :class="conditionalClasses"> <div v-if="timegap" class="b-timeline-item__row"> <div class="b-timeline-item__marker" aria-hidden="true"> <div class="b-timeline-item__icon b-timeline-item__icon--timegap"></div> <div class="b-timeline-item__separator"></div> </div> <div class="b-timeline-item__content"> <bento-typography class="b-timeline-item__timegap" :aria-label="timegapAriaLabel"> {{ timegap }} </bento-typography> </div> </div> <div class="b-timeline-item__row"> <div class="b-timeline-item__marker" aria-hidden="true"> <square-small-icon class="b-timeline-item__icon" :class="iconConditionalClasses" /> <div v-if="!isLastItem" class="b-timeline-item__separator" data-testid="last-timeline-item-separator" ></div> </div> <div class="b-timeline-item__content"> <bento-typography v-if="!isNoteType" el="div" variant="body" strongest class="b-timeline-item__title" role="heading" aria-level="2" > <bento-link v-if="isLinkTitle" v-bind="linkTitleProps" disable-typography>{{ linkTitleProps.title }}</bento-link> <span v-else>{{ title }}</span> </bento-typography> <bento-typography v-if="isNoteType && (description || hasSlot('default'))" el="div" variant="body" class="b-timeline-item__description" > <slot>{{ description }}</slot> </bento-typography> <bento-typography v-if="timestamp" class="b-timeline-item__timestamp" el="div" variant="caption"> <bento-date :date="timestamp.date" :format="timestamp.format" disable-typography /> {{ timestamp.value }} </bento-typography> <bento-typography v-if="!isNoteType && additionalTimestamp" class="b-timeline-item__timestamp" el="div" variant="caption" > <bento-date :date="additionalTimestamp.date" :format="additionalTimestamp.format" disable-typography /> {{ additionalTimestamp.value }} </bento-typography> <bento-typography v-if="!isNoteType && (description || hasSlot('default'))" el="div" variant="body" class="b-timeline-item__description" > <slot>{{ description }}</slot> </bento-typography> <div v-if="!isNoteType && dataList" class="b-timeline-item__data-list"> <bento-structured-list> <bento-structured-list-item v-for="listEntry in dataList" :key="generateUid(listEntry.label)" :label="listEntry.label" > <bento-typography variant="caption">{{ listEntry.value }}</bento-typography> </bento-structured-list-item> </bento-structured-list> </div> <bento-tag v-if="!isNoteType && tag" v-bind="tag" class="b-timeline-item__tag" /> </div> </div> <div v-if="displayShowMoreButton" class="b-timeline-item__row"> <div class="b-timeline-item__marker" aria-hidden="true"> <div class="b-timeline-item__separator"></div> </div> <div class="b-timeline-item__content"> <bento-button class="b-timeline__show-more" variant="tertiary" @click="showAll = !showAll"> <template v-if="!showAll">{{ t('showMore', { items: hiddenItems }) }}</template> <template v-else>{{ t('showLess') }}</template> </bento-button> </div> </div> </li> </template> <script setup lang="ts"> import { computed, defineComponent, inject, onUnmounted, provide, useSlots } from 'vue'; // Components import { BentoButton } from '@/components/button'; import { BentoDate } from '@/components/date'; import { BentoLink } from '@/components/link'; import { BentoTag } from '@/components/tag'; import { BentoTypography } from '@/components/typography'; import { BentoStructuredList, BentoStructuredListItem } from '@/components/structured-list'; import SquareSmallIcon from '@adyen/ui-assets-icons-16/vue/square-small-fill'; // Utils import { deprecate } from '@/utils/ts/deprecate'; import { generateUid } from '@/core/utils/ts'; import { useI18n } from '@/utils/ts/i18n'; import { useHasSlot } from '@/composables'; import { formatDistanceStrict } from 'date-fns/formatDistanceStrict'; // Types import { type BentoTimelineConfigData, type BentoTimelineEntry, type BentoTimelineItemProps, type BentoTimelineItemTitle, BentoTimelineItemVariant, type BentoTimelineRegisterEntry, } from '../../timeline.types'; // Keys import { TIMELINE_CONFIG_INJECTION_KEY, TIMELINE_REGISTER_ENTRY_INJECTION_KEY } from '../../timeline.keys'; import { STRUCTURED_LIST_CONDENSED_INJECTION_KEY } from '@/components/structured-list/structured-list.keys'; import messages from './messages.json'; type MessageSchema = (typeof messages)['en-US']; const props = withDefaults(defineProps<BentoTimelineItemProps>(), { additionalTimestamp: null, dataList: null, description: null, status: 'black', tag: undefined, title: null, type: 'milestone', variant: null, }); const { t } = useI18n<{ message: MessageSchema }>({ messages }); const slots = useSlots(); const hasSlot = useHasSlot(slots); const isNoteType = computed(() => props.type === 'note'); // Handle variant deprecation, by setting `critical` and `success` variants to their respective colors const computedStatus = computed(() => { if (props.variant === BentoTimelineItemVariant.CRITICAL) { return 'red'; } if (props.variant === BentoTimelineItemVariant.SUCCESS) { return 'green'; } return props.status; }); if (props.variant) { deprecate( 'BentoTimelineItem "variant" property', `Use the BentoTimelineItem "status" modifier instead to modify the color of the timeline icon. <bento-timeline-item status="red" />`, '2.0.0' ); } const iconConditionalClasses = computed(() => ({ [`b-timeline-item__icon--${computedStatus.value}`]: computedStatus.value && !isNoteType.value, })); const conditionalClasses = computed(() => ({ 'b-timeline-item--note': isNoteType.value, })); // Provide STRUCTURED_LIST_CONDENSED_INJECTION_KEY as true, to set the internal condensed style in the BentoStructuredList comp provide(STRUCTURED_LIST_CONDENSED_INJECTION_KEY, true); const entry: BentoTimelineEntry = { title: props.title, date: props.timestamp.date, }; // Register timeline entry to the timeline entries array const registerTimelineEntry: BentoTimelineRegisterEntry = inject(TIMELINE_REGISTER_ENTRY_INJECTION_KEY); const { timelineEntries, unregisterTimelineEntry } = registerTimelineEntry(entry); // On unmounting timeline item, unregister it from the parent timeline component onUnmounted(() => unregisterTimelineEntry()); // Get timeline config data from the parent Timeline comp const { showAll, showMoreIndex, hiddenItems, visibleIndexes, timegapLimit }: BentoTimelineConfigData = inject(TIMELINE_CONFIG_INJECTION_KEY); const index = computed(() => timelineEntries.value.indexOf(entry)); const allItemsShowing = computed(() => showAll.value || !visibleIndexes.value); const isVisible = computed(() => (allItemsShowing.value ? true : visibleIndexes.value.includes(index.value))); const isLinkTitle = computed(() => typeof props.title === 'object'); const linkTitleProps = computed(() => props.title as BentoTimelineItemTitle); const timegap = computed(() => { if (!timegapLimit.value) { return null; } const previousDate = timelineEntries.value[index.value - 1]?.date; const isPreviousItemVisible = allItemsShowing.value || visibleIndexes.value.includes(index.value - 1); if (!previousDate || !isPreviousItemVisible) { return null; } const { date } = timelineEntries.value[index.value]; const timegapInSelectedUnit = parseInt( formatDistanceStrict(previousDate, date, { unit: timegapLimit.value.unit }), 10 ); return timegapLimit.value.amount < timegapInSelectedUnit ? formatDistanceStrict(previousDate, date, { roundingMethod: 'floor' }) : null; }); const timegapAriaLabel = computed(() => (timegap.value ? t('timegap', { timegap: timegap.value }) : '')); const displayShowMoreButton = computed(() => hiddenItems.value && showMoreIndex.value === index.value); const isLastItem = computed(() => { // The index can be -1 before the parent has had a chance to sort the array. return index.value !== -1 && index.value === timelineEntries.value.length - 1; }); </script> <script lang="ts"> /** * BentoTimelineItem renders each event in the Timeline component * * @example * import { BentoDateFormat, BentoTimelineItem } from '@adyen/bento-vue2'; * * export default { * components: { BentoTimelineItem }, * template: ` * <bento-timeline-item * title="Milestone" * :timestamp="{ date: new Date(), value: 'Created at', format: BentoDateFormat.FULL_DATE_EXACT_TIME_WITHOUT_PERIOD }" * :additional-timestamp="{ date: new Date(), value: 'Modified at' }" * description="Milestone description" * :data-list="[ * { label: 'Label', value: 'Value' }, * { label: 'Label', value: 'Value' }, * ]" * :tag="{ label: 'Tag'}" * /> * ` * } */ export default defineComponent({ name: 'bento-timeline-item', i18n: { messages }, }); </script> <style lang="scss" scoped src="./timeline-item.scss" />
1
+ <template> <li v-if="isVisible" class="b-timeline-item" :class="conditionalClasses"> <div v-if="timegap" class="b-timeline-item__row"> <div class="b-timeline-item__marker" aria-hidden="true"> <div class="b-timeline-item__icon b-timeline-item__icon--timegap"></div> <div class="b-timeline-item__separator"></div> </div> <div class="b-timeline-item__content"> <bento-typography class="b-timeline-item__timegap" :aria-label="timegapAriaLabel"> {{ timegap }} </bento-typography> </div> </div> <div class="b-timeline-item__row"> <div class="b-timeline-item__marker" aria-hidden="true"> <square-small-icon class="b-timeline-item__icon" :class="iconConditionalClasses" /> <div v-if="!isLastItem" class="b-timeline-item__separator" data-testid="last-timeline-item-separator" ></div> </div> <div class="b-timeline-item__content"> <bento-typography v-if="!isNoteType" el="div" variant="body" strongest class="b-timeline-item__title" role="heading" aria-level="2" > <bento-link v-if="isLinkTitle" v-bind="linkTitleProps" disable-typography>{{ linkTitleProps.title }}</bento-link> <span v-else>{{ title }}</span> </bento-typography> <bento-typography v-if="isNoteType && (description || hasSlot('default'))" el="div" variant="body" class="b-timeline-item__description" > <slot>{{ description }}</slot> </bento-typography> <bento-typography v-if="timestamp" class="b-timeline-item__timestamp" el="div" variant="caption"> <bento-date :date="timestamp.date" :format="timestamp.format" disable-typography /> <bento-dashed-underline v-if="timestamp.description" v-bind="timestamp.description"> {{ timestamp.value }} </bento-dashed-underline> <span v-else>{{ timestamp.value }}</span> </bento-typography> <bento-typography v-if="!isNoteType && additionalTimestamp" class="b-timeline-item__timestamp" el="div" variant="caption" > <bento-date :date="additionalTimestamp.date" :format="additionalTimestamp.format" disable-typography /> <bento-dashed-underline v-if="additionalTimestamp.description" v-bind="additionalTimestamp.description" > {{ additionalTimestamp.value }} </bento-dashed-underline> <span v-else> {{ additionalTimestamp.value }} </span> </bento-typography> <bento-typography v-if="!isNoteType && (description || hasSlot('default'))" el="div" variant="body" class="b-timeline-item__description" > <slot>{{ description }}</slot> </bento-typography> <div v-if="!isNoteType && dataList" class="b-timeline-item__data-list"> <bento-structured-list> <bento-structured-list-item v-for="listEntry in dataList" :key="generateUid(listEntry.label)" :label="listEntry.label" > <bento-typography variant="caption">{{ listEntry.value }}</bento-typography> </bento-structured-list-item> </bento-structured-list> </div> <bento-tag v-if="!isNoteType && tag" v-bind="tag" class="b-timeline-item__tag" /> </div> </div> <div v-if="displayShowMoreButton" class="b-timeline-item__row"> <div class="b-timeline-item__marker" aria-hidden="true"> <div class="b-timeline-item__separator"></div> </div> <div class="b-timeline-item__content"> <bento-button class="b-timeline__show-more" variant="tertiary" @click="showAll = !showAll"> <template v-if="!showAll">{{ t('showMore', { items: hiddenItems }) }}</template> <template v-else>{{ t('showLess') }}</template> </bento-button> </div> </div> </li> </template> <script setup lang="ts"> import { computed, defineComponent, inject, onUnmounted, provide, useSlots } from 'vue'; // Components import { BentoButton } from '@/components/button'; import { BentoDashedUnderline } from '@/components/dashed-underline'; import { BentoDate } from '@/components/date'; import { BentoLink } from '@/components/link'; import { BentoTag } from '@/components/tag'; import { BentoTypography } from '@/components/typography'; import { BentoStructuredList, BentoStructuredListItem } from '@/components/structured-list'; import SquareSmallIcon from '@adyen/ui-assets-icons-16/vue/square-small-fill'; // Utils import { deprecate } from '@/utils/ts/deprecate'; import { generateUid } from '@/core/utils/ts'; import { useI18n } from '@/utils/ts/i18n'; import { useHasSlot } from '@/composables'; import { formatDistanceStrict } from 'date-fns/formatDistanceStrict'; // Types import { type BentoTimelineConfigData, type BentoTimelineEntry, type BentoTimelineItemProps, type BentoTimelineItemTitle, BentoTimelineItemVariant, type BentoTimelineRegisterEntry, } from '../../timeline.types'; // Keys import { TIMELINE_CONFIG_INJECTION_KEY, TIMELINE_REGISTER_ENTRY_INJECTION_KEY } from '../../timeline.keys'; import { STRUCTURED_LIST_CONDENSED_INJECTION_KEY } from '@/components/structured-list/structured-list.keys'; import messages from './messages.json'; type MessageSchema = (typeof messages)['en-US']; const props = withDefaults(defineProps<BentoTimelineItemProps>(), { additionalTimestamp: null, dataList: null, description: null, status: 'black', tag: undefined, title: null, type: 'milestone', variant: null, }); const { t } = useI18n<{ message: MessageSchema }>({ messages }); const slots = useSlots(); const hasSlot = useHasSlot(slots); const isNoteType = computed(() => props.type === 'note'); // Handle variant deprecation, by setting `critical` and `success` variants to their respective colors const computedStatus = computed(() => { if (props.variant === BentoTimelineItemVariant.CRITICAL) { return 'red'; } if (props.variant === BentoTimelineItemVariant.SUCCESS) { return 'green'; } return props.status; }); if (props.variant) { deprecate( 'BentoTimelineItem "variant" property', `Use the BentoTimelineItem "status" modifier instead to modify the color of the timeline icon. <bento-timeline-item status="red" />`, '2.0.0' ); } const iconConditionalClasses = computed(() => ({ [`b-timeline-item__icon--${computedStatus.value}`]: computedStatus.value && !isNoteType.value, })); const conditionalClasses = computed(() => ({ 'b-timeline-item--note': isNoteType.value, })); // Provide STRUCTURED_LIST_CONDENSED_INJECTION_KEY as true, to set the internal condensed style in the BentoStructuredList comp provide(STRUCTURED_LIST_CONDENSED_INJECTION_KEY, true); const entry: BentoTimelineEntry = { title: props.title, date: props.timestamp.date, }; // Register timeline entry to the timeline entries array const registerTimelineEntry: BentoTimelineRegisterEntry = inject(TIMELINE_REGISTER_ENTRY_INJECTION_KEY); const { timelineEntries, unregisterTimelineEntry } = registerTimelineEntry(entry); // On unmounting timeline item, unregister it from the parent timeline component onUnmounted(() => unregisterTimelineEntry()); // Get timeline config data from the parent Timeline comp const { showAll, showMoreIndex, hiddenItems, visibleIndexes, timegapLimit }: BentoTimelineConfigData = inject(TIMELINE_CONFIG_INJECTION_KEY); const index = computed(() => timelineEntries.value.indexOf(entry)); const allItemsShowing = computed(() => showAll.value || !visibleIndexes.value); const isVisible = computed(() => (allItemsShowing.value ? true : visibleIndexes.value.includes(index.value))); const isLinkTitle = computed(() => typeof props.title === 'object'); const linkTitleProps = computed(() => props.title as BentoTimelineItemTitle); const timegap = computed(() => { if (!timegapLimit.value) { return null; } const previousDate = timelineEntries.value[index.value - 1]?.date; const isPreviousItemVisible = allItemsShowing.value || visibleIndexes.value.includes(index.value - 1); if (!previousDate || !isPreviousItemVisible) { return null; } const { date } = timelineEntries.value[index.value]; const timegapInSelectedUnit = parseInt( formatDistanceStrict(previousDate, date, { unit: timegapLimit.value.unit }), 10 ); return timegapLimit.value.amount < timegapInSelectedUnit ? formatDistanceStrict(previousDate, date, { roundingMethod: 'floor' }) : null; }); const timegapAriaLabel = computed(() => (timegap.value ? t('timegap', { timegap: timegap.value }) : '')); const displayShowMoreButton = computed(() => hiddenItems.value && showMoreIndex.value === index.value); const isLastItem = computed(() => { // The index can be -1 before the parent has had a chance to sort the array. return index.value !== -1 && index.value === timelineEntries.value.length - 1; }); </script> <script lang="ts"> /** * BentoTimelineItem renders each event in the Timeline component * * @example * import { BentoDateFormat, BentoTimelineItem } from '@adyen/bento-vue2'; * * export default { * components: { BentoTimelineItem }, * template: ` * <bento-timeline-item * title="Milestone" * :timestamp="{ date: new Date(), value: 'Created at', format: BentoDateFormat.FULL_DATE_EXACT_TIME_WITHOUT_PERIOD }" * :additional-timestamp="{ date: new Date(), value: 'Modified at' }" * description="Milestone description" * :data-list="[ * { label: 'Label', value: 'Value' }, * { label: 'Label', value: 'Value' }, * ]" * :tag="{ label: 'Tag'}" * /> * ` * } */ export default defineComponent({ name: 'bento-timeline-item', i18n: { messages }, }); </script> <style lang="scss" scoped src="./timeline-item.scss" />
@@ -1 +1 @@
1
- import type { Meta, StoryObj } from '@storybook/vue'; import { storybookDocsParameter } from '@/utils/ts/storybook'; import { onMounted, ref } from 'vue'; import { isVue2 } from 'vue-demi'; import BentoTimeline from './timeline.vue'; import BentoTimelineItem from './components/timeline-item/timeline-item.vue'; import { BentoTimelineGapUnit, BentoTimelineShowMorePlacement } from './timeline.types'; import TimelineDynamicAddition from './__tests__/timeline-dynamic-add-stub.vue?raw'; import { BentoDateFormat } from '@/components/date/date.types'; import BentoLink from '@/components/link/link.vue'; import BentoButton from '@/components/button/button.vue'; const meta: Meta = { title: 'Timeline', component: BentoTimeline, argTypes: { // Slots default: { name: 'default', type: { name: 'string', required: false }, description: 'BentoTimelineItem components', control: 'text', table: { type: { summary: 'VNode[]' }, }, }, }, }; export default meta; type Story = StoryObj<typeof BentoTimeline>; const DEFAULT_PROPS = { timegapLimit: { unit: BentoTimelineGapUnit.DAY, amount: 15 }, showMore: { limit: 3, placement: BentoTimelineShowMorePlacement.AFTER_FIRST }, }; const DEFAULT_ITEM_PROPS = { timestamp: { date: new Date(), value: 'AuthorName', format: BentoDateFormat.FULL_DATE_EXACT_TIME_WITHOUT_PERIOD, }, dataList: [ { label: 'Label', value: 'Value' }, { label: 'Label', value: 'Value' }, ], description: 'Space to put some description about this milestone', }; const { description: _, ...DEFAULT_PROPS_WITHOUT_DESCRIPTION } = DEFAULT_ITEM_PROPS; export const Default: Story = { render: (_args, { argTypes }) => ({ components: { BentoTimeline, BentoTimelineItem }, props: Object.keys(argTypes), template: ` <bento-timeline v-bind="args"> <bento-timeline-item v-bind="milestone5" /> <bento-timeline-item v-bind="milestone4" /> <bento-timeline-item v-bind="milestone3" /> <bento-timeline-item v-bind="milestone2" /> <bento-timeline-item v-bind="milestone1" /> </bento-timeline> `, setup(props) { const milestone5 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 5', status: 'green', }; const milestone4 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 4', timestamp: { date: new Date().setDate(-2), value: 'AuthorName', }, }; const milestone3 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 3', timestamp: { date: new Date().setDate(-4), value: 'AuthorName', }, status: 'red', }; const milestone2 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 2', timestamp: { date: new Date().setDate(-14), value: 'AuthorName', }, additionalTimestamp: { date: new Date().setDate(-15), value: 'AuthorName', }, }; const milestone1 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 1', timestamp: { date: new Date().setDate(-150), value: 'AuthorName', }, tag: { label: 'Tag1', }, }; return { args: isVue2 ? props : _args, milestone1, milestone2, milestone3, milestone4, milestone5, }; }, }), args: { ...DEFAULT_PROPS, }, }; export const WithLinks: Story = { render: (_args, { argTypes }) => ({ components: { BentoLink, BentoTimeline, BentoTimelineItem }, props: Object.keys(argTypes), template: ` <bento-timeline v-bind="args"> <bento-timeline-item v-bind="milestone3" /> <bento-timeline-item v-bind="milestone2"> A description with <bento-link to="/">a link</bento-link> </bento-timeline-item> <bento-timeline-item v-bind="milestone1" /> </bento-timeline> `, setup(props) { const milestone3 = { ...DEFAULT_ITEM_PROPS, title: { title: 'Milestone 3', to: '/', }, timestamp: { date: new Date().setDate(-4), value: 'AuthorName', }, status: 'green', }; const milestone2 = { ...DEFAULT_PROPS_WITHOUT_DESCRIPTION, title: 'Milestone 2', timestamp: { date: new Date().setDate(-14), value: 'AuthorName', }, additionalTimestamp: { date: new Date().setDate(-15), value: 'AuthorName', }, }; const milestone1 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 1', timestamp: { date: new Date().setDate(-150), value: 'AuthorName', }, tag: { label: 'Tag1', }, }; return { args: isVue2 ? props : _args, milestone1, milestone2, milestone3, }; }, }), args: { ...DEFAULT_PROPS, }, }; const withNotesCode = ` <template> <bento-timeline v-bind="args" @add-timeline-note="addNote"> <bento-timeline-item v-for="item in timelineItems" v-bind="item" /> </bento-timeline> </template> <script setup> const milestone3 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 2', timestamp: { date: new Date().setDate(-4), value: 'AuthorName', }, additionalTimestamp: { date: new Date().setDate(-5), value: 'AuthorName', }, }; const milestone2 = { type: 'note', description: 'Milestone Note. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.', timestamp: { date: new Date().setDate(-14), value: 'AuthorName', }, }; const milestone1 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 1', timestamp: { date: new Date().setDate(-150), value: 'AuthorName', }, tag: { label: 'Tag1', }, }; const timelineItems = ref(); onMounted(() => { timelineItems.value = [milestone3, milestone2, milestone1]; }); const addNote = e => { timelineItems.value.unshift(e); }; return { args: isVue2 ? props : _args, timelineItems, addNote, }; </script> `; export const WithNotes: Story = { render: (_args, { argTypes }) => ({ components: { BentoTimeline, BentoTimelineItem }, props: Object.keys(argTypes), template: ` <bento-timeline v-bind="args"> <bento-timeline-item v-bind="milestone3" /> <bento-timeline-item v-bind="milestone2" /> <bento-timeline-item v-bind="milestone1" /> </bento-timeline> `, setup(props) { const milestone3 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 2', timestamp: { date: new Date().setDate(-4), value: 'AuthorName', }, additionalTimestamp: { date: new Date().setDate(-5), value: 'AuthorName', }, }; const milestone2 = { type: 'note', description: 'Milestone Note. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.', timestamp: { date: new Date().setDate(-14), value: 'AuthorName', }, }; const milestone1 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 1', timestamp: { date: new Date().setDate(-150), value: 'AuthorName', }, tag: { label: 'Tag1', }, }; return { args: isVue2 ? props : _args, milestone1, milestone2, milestone3, }; }, }), args: { ...DEFAULT_PROPS, showMore: null, }, parameters: storybookDocsParameter(withNotesCode), }; const addNoteCode = ` <template> <bento-timeline v-bind="args" add-note @add-timeline-note="addNote"> <bento-timeline-item v-for="item in timelineItems" v-bind="item" /> </bento-timeline> </template> <script setup> const milestone3 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 2', timestamp: { date: new Date().setDate(-4), value: 'AuthorName', }, additionalTimestamp: { date: new Date().setDate(-5), value: 'AuthorName', }, }; const milestone2 = { type: 'note', description: 'Milestone Note. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.', timestamp: { date: new Date().setDate(-14), value: 'AuthorName', }, }; const milestone1 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 1', timestamp: { date: new Date().setDate(-150), value: 'AuthorName', }, tag: { label: 'Tag1', }, }; const timelineItems = ref(); onMounted(() => { timelineItems.value = [milestone3, milestone2, milestone1]; }); const addNote = e => { timelineItems.value.unshift(e); }; return { timelineItems, addNote, }; </script> `; export const AddNote: Story = { render: (_args, { argTypes }) => ({ components: { BentoTimeline, BentoTimelineItem }, props: Object.keys(argTypes), template: ` <bento-timeline v-bind="args" add-note @add-timeline-note="addNote"> <bento-timeline-item v-for="item in timelineItems" v-bind="item" /> </bento-timeline> `, setup(props) { const milestone3 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 2', timestamp: { date: new Date().setDate(-4), value: 'AuthorName', }, additionalTimestamp: { date: new Date().setDate(-5), value: 'AuthorName', }, }; const milestone2 = { type: 'note', description: 'Milestone Note. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.', timestamp: { date: new Date().setDate(-14), value: 'AuthorName', }, }; const milestone1 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 1', timestamp: { date: new Date().setDate(-150), value: 'AuthorName', }, tag: { label: 'Tag1', }, }; const timelineItems = ref(); onMounted(() => { timelineItems.value = [milestone3, milestone2, milestone1]; }); const addNote = e => { const newNote = { ...e, timestamp: { ...e.timestamp, value: 'AuthorName' } }; timelineItems.value.unshift(newNote); }; return { args: isVue2 ? props : _args, timelineItems, addNote, }; }, }), args: { ...DEFAULT_PROPS, showMore: null, addNotes: true, }, parameters: storybookDocsParameter(addNoteCode), }; export const DynamicItemAddition: Story = { render: (_args, { argTypes }) => ({ components: { BentoButton, BentoTimeline, BentoTimelineItem }, props: Object.keys(argTypes), template: ` <div style="display: flex; flex-direction: row; align-items: flex-start; gap: 16px;"> <bento-button @click="addItem">Add timeline item</bento-button> <bento-timeline v-if="timelineEntries"> <bento-timeline-item v-for="entry in timelineEntries" :key="entry.title" v-bind="entry" /> </bento-timeline> </div> `, setup(props) { const timelineEntries = ref([]); let index = 0; const addItem = () => { if (index < 5) { timelineEntries.value.unshift(milestones[index]); index++; } }; const milestone5 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 5', status: 'green', }; const milestone4 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 4', timestamp: { date: new Date().setDate(-2), value: 'AuthorName', }, }; const milestone3 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 3', timestamp: { date: new Date().setDate(-4), value: 'AuthorName', }, status: 'red', }; const milestone2 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 2', timestamp: { date: new Date().setDate(-14), value: 'AuthorName', }, additionalTimestamp: { date: new Date().setDate(-15), value: 'AuthorName', }, }; const milestone1 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 1', timestamp: { date: new Date().setDate(-150), value: 'AuthorName', }, tag: { label: 'Tag1', }, }; const milestones = [milestone1, milestone2, milestone3, milestone4, milestone5]; return { args: isVue2 ? props : _args, timelineEntries, addItem, }; }, }), args: { ...DEFAULT_PROPS, }, parameters: storybookDocsParameter(TimelineDynamicAddition), };
1
+ import type { Meta, StoryObj } from '@storybook/vue'; import { storybookDocsParameter } from '@/utils/ts/storybook'; import { onMounted, ref } from 'vue'; import { isVue2 } from 'vue-demi'; import BentoTimeline from './timeline.vue'; import BentoTimelineItem from './components/timeline-item/timeline-item.vue'; import { BentoTimelineGapUnit, BentoTimelineShowMorePlacement } from './timeline.types'; import TimelineDynamicAddition from './__tests__/timeline-dynamic-add-stub.vue?raw'; import TimelineDefaultExample from './__tests__/timeline-default-example.vue?raw'; import { BentoDateFormat } from '@/components/date/date.types'; import BentoLink from '@/components/link/link.vue'; import BentoButton from '@/components/button/button.vue'; const meta: Meta = { title: 'Timeline', component: BentoTimeline, argTypes: { // Slots default: { name: 'default', type: { name: 'string', required: false }, description: 'BentoTimelineItem components', control: 'text', table: { type: { summary: 'VNode[]' }, }, }, }, }; export default meta; type Story = StoryObj<typeof BentoTimeline>; const DEFAULT_PROPS = { timegapLimit: { unit: BentoTimelineGapUnit.DAY, amount: 15 }, showMore: { limit: 3, placement: BentoTimelineShowMorePlacement.AFTER_FIRST }, }; const DEFAULT_ITEM_PROPS = { timestamp: { date: new Date(), value: 'AuthorName', format: BentoDateFormat.FULL_DATE_EXACT_TIME_WITHOUT_PERIOD, }, dataList: [ { label: 'Label', value: 'Value' }, { label: 'Label', value: 'Value' }, ], description: 'Space to put some description about this milestone', }; const { description: _, ...DEFAULT_PROPS_WITHOUT_DESCRIPTION } = DEFAULT_ITEM_PROPS; export const Default: Story = { render: (_args, { argTypes }) => ({ components: { BentoTimeline, BentoTimelineItem }, props: Object.keys(argTypes), template: ` <bento-timeline v-bind="args"> <bento-timeline-item v-bind="milestone5" /> <bento-timeline-item v-bind="milestone4" /> <bento-timeline-item v-bind="milestone3" /> <bento-timeline-item v-bind="milestone2" /> <bento-timeline-item v-bind="milestone1" /> </bento-timeline> `, setup(props) { const milestone5 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 5', status: 'green', }; const milestone4 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 4', timestamp: { date: new Date().setDate(-2), value: 'AuthorName', }, }; const milestone3 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 3', timestamp: { date: new Date().setDate(-4), value: 'AuthorName', }, status: 'red', }; const milestone2 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 2', timestamp: { date: new Date().setDate(-14), value: 'BookingDate', description: { popoverText: 'date of booking', }, }, additionalTimestamp: { date: new Date().setDate(-15), value: 'ValueDate', description: { tooltipText: 'date of value', }, }, }; const milestone1 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 1', timestamp: { date: new Date().setDate(-150), value: 'AuthorName', }, tag: { label: 'Tag1', }, }; return { args: isVue2 ? props : _args, milestone1, milestone2, milestone3, milestone4, milestone5, }; }, }), args: { ...DEFAULT_PROPS, }, parameters: storybookDocsParameter(TimelineDefaultExample), }; export const WithLinks: Story = { render: (_args, { argTypes }) => ({ components: { BentoLink, BentoTimeline, BentoTimelineItem }, props: Object.keys(argTypes), template: ` <bento-timeline v-bind="args"> <bento-timeline-item v-bind="milestone3" /> <bento-timeline-item v-bind="milestone2"> A description with <bento-link to="/">a link</bento-link> </bento-timeline-item> <bento-timeline-item v-bind="milestone1" /> </bento-timeline> `, setup(props) { const milestone3 = { ...DEFAULT_ITEM_PROPS, title: { title: 'Milestone 3', to: '/', }, timestamp: { date: new Date().setDate(-4), value: 'AuthorName', }, status: 'green', }; const milestone2 = { ...DEFAULT_PROPS_WITHOUT_DESCRIPTION, title: 'Milestone 2', timestamp: { date: new Date().setDate(-14), value: 'AuthorName', }, additionalTimestamp: { date: new Date().setDate(-15), value: 'AuthorName', }, }; const milestone1 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 1', timestamp: { date: new Date().setDate(-150), value: 'AuthorName', }, tag: { label: 'Tag1', }, }; return { args: isVue2 ? props : _args, milestone1, milestone2, milestone3, }; }, }), args: { ...DEFAULT_PROPS, }, }; const withNotesCode = ` <template> <bento-timeline v-bind="args" @add-timeline-note="addNote"> <bento-timeline-item v-for="item in timelineItems" v-bind="item" /> </bento-timeline> </template> <script setup> const milestone3 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 2', timestamp: { date: new Date().setDate(-4), value: 'AuthorName', }, additionalTimestamp: { date: new Date().setDate(-5), value: 'AuthorName', }, }; const milestone2 = { type: 'note', description: 'Milestone Note. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.', timestamp: { date: new Date().setDate(-14), value: 'AuthorName', }, }; const milestone1 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 1', timestamp: { date: new Date().setDate(-150), value: 'AuthorName', }, tag: { label: 'Tag1', }, }; const timelineItems = ref(); onMounted(() => { timelineItems.value = [milestone3, milestone2, milestone1]; }); const addNote = e => { timelineItems.value.unshift(e); }; return { args: isVue2 ? props : _args, timelineItems, addNote, }; </script> `; export const WithNotes: Story = { render: (_args, { argTypes }) => ({ components: { BentoTimeline, BentoTimelineItem }, props: Object.keys(argTypes), template: ` <bento-timeline v-bind="args"> <bento-timeline-item v-bind="milestone3" /> <bento-timeline-item v-bind="milestone2" /> <bento-timeline-item v-bind="milestone1" /> </bento-timeline> `, setup(props) { const milestone3 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 2', timestamp: { date: new Date().setDate(-4), value: 'AuthorName', }, additionalTimestamp: { date: new Date().setDate(-5), value: 'AuthorName', }, }; const milestone2 = { type: 'note', description: 'Milestone Note. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.', timestamp: { date: new Date().setDate(-14), value: 'AuthorName', }, }; const milestone1 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 1', timestamp: { date: new Date().setDate(-150), value: 'AuthorName', }, tag: { label: 'Tag1', }, }; return { args: isVue2 ? props : _args, milestone1, milestone2, milestone3, }; }, }), args: { ...DEFAULT_PROPS, showMore: null, }, parameters: storybookDocsParameter(withNotesCode), }; const addNoteCode = ` <template> <bento-timeline v-bind="args" add-note @add-timeline-note="addNote"> <bento-timeline-item v-for="item in timelineItems" v-bind="item" /> </bento-timeline> </template> <script setup> const milestone3 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 2', timestamp: { date: new Date().setDate(-4), value: 'AuthorName', }, additionalTimestamp: { date: new Date().setDate(-5), value: 'AuthorName', }, }; const milestone2 = { type: 'note', description: 'Milestone Note. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.', timestamp: { date: new Date().setDate(-14), value: 'AuthorName', }, }; const milestone1 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 1', timestamp: { date: new Date().setDate(-150), value: 'AuthorName', }, tag: { label: 'Tag1', }, }; const timelineItems = ref(); onMounted(() => { timelineItems.value = [milestone3, milestone2, milestone1]; }); const addNote = e => { timelineItems.value.unshift(e); }; return { timelineItems, addNote, }; </script> `; export const AddNote: Story = { render: (_args, { argTypes }) => ({ components: { BentoTimeline, BentoTimelineItem }, props: Object.keys(argTypes), template: ` <bento-timeline v-bind="args" add-note @add-timeline-note="addNote"> <bento-timeline-item v-for="item in timelineItems" v-bind="item" /> </bento-timeline> `, setup(props) { const milestone3 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 2', timestamp: { date: new Date().setDate(-4), value: 'AuthorName', }, additionalTimestamp: { date: new Date().setDate(-5), value: 'AuthorName', }, }; const milestone2 = { type: 'note', description: 'Milestone Note. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.', timestamp: { date: new Date().setDate(-14), value: 'AuthorName', }, }; const milestone1 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 1', timestamp: { date: new Date().setDate(-150), value: 'AuthorName', }, tag: { label: 'Tag1', }, }; const timelineItems = ref(); onMounted(() => { timelineItems.value = [milestone3, milestone2, milestone1]; }); const addNote = e => { const newNote = { ...e, timestamp: { ...e.timestamp, value: 'AuthorName' } }; timelineItems.value.unshift(newNote); }; return { args: isVue2 ? props : _args, timelineItems, addNote, }; }, }), args: { ...DEFAULT_PROPS, showMore: null, addNotes: true, }, parameters: storybookDocsParameter(addNoteCode), }; export const DynamicItemAddition: Story = { render: (_args, { argTypes }) => ({ components: { BentoButton, BentoTimeline, BentoTimelineItem }, props: Object.keys(argTypes), template: ` <div style="display: flex; flex-direction: row; align-items: flex-start; gap: 16px;"> <bento-button @click="addItem">Add timeline item</bento-button> <bento-timeline v-if="timelineEntries"> <bento-timeline-item v-for="entry in timelineEntries" :key="entry.title" v-bind="entry" /> </bento-timeline> </div> `, setup(props) { const timelineEntries = ref([]); let index = 0; const addItem = () => { if (index < 5) { timelineEntries.value.unshift(milestones[index]); index++; } }; const milestone5 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 5', status: 'green', }; const milestone4 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 4', timestamp: { date: new Date().setDate(-2), value: 'AuthorName', }, }; const milestone3 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 3', timestamp: { date: new Date().setDate(-4), value: 'AuthorName', }, status: 'red', }; const milestone2 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 2', timestamp: { date: new Date().setDate(-14), value: 'AuthorName', }, additionalTimestamp: { date: new Date().setDate(-15), value: 'AuthorName', }, }; const milestone1 = { ...DEFAULT_ITEM_PROPS, title: 'Milestone 1', timestamp: { date: new Date().setDate(-150), value: 'AuthorName', }, tag: { label: 'Tag1', }, }; const milestones = [milestone1, milestone2, milestone3, milestone4, milestone5]; return { args: isVue2 ? props : _args, timelineEntries, addItem, }; }, }), args: { ...DEFAULT_PROPS, }, parameters: storybookDocsParameter(TimelineDynamicAddition), };
@@ -0,0 +1 @@
1
+ import { type BentoDashedUnderlineProps } from '@/components/dashed-underline/dashed-underline.types'; import { type BentoDateFormat } from '@/components/date/date.types'; import { type BentoTag } from '@/components/tag'; import { type Ref } from 'vue'; import type { RouterLinkProps } from 'vue-router/types/router.d.ts'; export enum BentoTimelineShowMorePlacement { BOTTOM = 'bottom', AFTER_FIRST = 'after-first', BEFORE_LAST = 'before-last', } export interface BentoTimelineShowMoreObject { limit: number; placement?: BentoTimelineShowMorePlacement; } export enum BentoTimelineGapUnit { SECOND = 'second', MINUTE = 'minute', HOUR = 'hour', DAY = 'day', MONTH = 'month', YEAR = 'year', } export interface BentoTimelineGapObject { amount: number; unit: BentoTimelineGapUnit; } /** * @deprecated "variant" prop was deprecated. Use "status" modifier instead. */ export enum BentoTimelineItemVariant { DEFAULT = 'SquareSmallIcon', SUCCESS = 'CheckedCircleIcon', CRITICAL = 'CrossCircleIcon', } export enum BentoTimelineStatus { BLACK = 'black', BLUE = 'blue', GREEN = 'green', GREY = 'grey', ORANGE = 'orange', RED = 'red', YELLOW = 'yellow', } export interface BentoTimelineItemTitle extends RouterLinkProps { /** * Link label. */ title: string; /** * Set the rendered link to a regular external anchor link. */ external?: boolean; /** * Sets the target of the rendered link. */ target?: string; // This has been added to allow users to add HTML and Aria attribute // eslint-disable-next-line @typescript-eslint/no-explicit-any [name: string]: any; } export interface BentoTimelineTimestamp { date: Date | number; format?: BentoDateFormat; value?: string; description?: BentoDashedUnderlineProps; } export interface BentoTimelineDataListObject { label: string; value: string; } export type BentoTimelineDataList = Array<BentoTimelineDataListObject>; export type BentoTimelineTagProps = InstanceType<typeof BentoTag>['$props']; export interface BentoTimelineEntry { title?: string | BentoTimelineItemTitle; description?: string; date: Date | number; } /** * @deprecated from version 2.0.0. */ export type BentoTimelineRegisterEntry = (props: { title?: string | BentoTimelineItemTitle; description?: string; date: Date | number; }) => { timelineEntries: Ref<Array<BentoTimelineEntry>>; index: number; unregisterTimelineEntry: () => void }; /** * @private */ export type BentoInternalTimelineRegisterEntry = ( entry: BentoTimelineEntry ) => { timelineEntries: Ref<Array<BentoTimelineEntry>>; unregisterTimelineEntry: () => void }; export interface BentoTimelineConfigData { showAll: Ref<boolean>; showMoreIndex: Ref<number>; hiddenItems: Ref<number>; visibleIndexes: Ref<Array<number>>; timegapLimit: Ref<BentoTimelineGapObject>; timelineEntries: Ref<Array<BentoTimelineEntry>>; } export interface BentoTimelineProps { /** * If set to true, gives the possibility to manually add notes to the timeline via a textarea */ addNote?: boolean; /** * Object that determines the max number of items to show without clicking the show more button * and where in the timeline is the show more button placed */ showMore?: BentoTimelineShowMoreObject; /** * Object that determines minimum amount of time for the automatic timegap indicator; * Define a unit (hour, day, month) and an amount (e.g. { amount: 7, unit: 'days' }). * If null, automatic timegap detection will be turned off */ timegapLimit?: BentoTimelineGapObject; } export interface BentoTimelineItemProps { /** * Additional timestamp of the event */ additionalTimestamp?: BentoTimelineTimestamp; /** * Relevant key-value pair data to display in the event */ dataList?: BentoTimelineDataList; /** * Description of the event */ description?: string; /** * Modifier that changes the color of the timeline icon * @values blue, black, green, grey, orange, red, yellow */ status?: string; /** * Tag props that will be passed down to inner tag component */ tag?: BentoTimelineTagProps; /** * Main timestamp of the event. Used for timegap detection. */ timestamp: BentoTimelineTimestamp; /** * Title of the event */ title?: BentoTimelineItemTitle | string; /** * Type of the timeline item. If set to 'note', it renders a note item in the timeline. Defaults to 'milestone'. * @values milestone, note */ type?: string; /** * Variant for the timeline item * @values DEFAULT, SUCCESS, CRITICAL * * @deprecated Use "status" prop instead */ variant?: BentoTimelineItemVariant | `${BentoTimelineItemVariant}`; }
@@ -0,0 +1 @@
1
+ import type { BentoToastItem } from '@/composables'; export interface BentoToastItemWithDimensions extends BentoToastItem { bottom: number; height: number; }
@@ -0,0 +1 @@
1
+ export enum BentoTogglePropClass { LABEL_FIRST = 'label-first', } /** * @deprecated for usage with properties since version 2.0. Use the string literal instead. */ export enum BentoToggleLabelPosition { BEFORE = 'before', AFTER = 'after', }
@@ -0,0 +1 @@
1
+ import type { Ref } from 'vue'; import type { BentoButtonActionObject } from '@/components/button'; import type { BentoImage } from '@/components/image'; import type { BentoPopoverPositions } from '@/components/popover'; import type { VueNodeElement } from '@/types/elements'; export interface BentoTutorialStep { target: VueNodeElement | Ref<VueNodeElement>; image?: Omit<InstanceType<typeof BentoImage>['$props'], 'aspectRatio'>; title: string; description: string; action?: BentoButtonActionObject; position?: `${BentoPopoverPositions}`; } export type BentoTutorialScrollOptions = boolean | ScrollIntoViewOptions;
@@ -0,0 +1 @@
1
+ /** * @deprecated for usage with properties since version 2.0. Use the string literal instead. */ export enum BentoTypographyVariant { CAPTION = 'caption', BODY = 'body', /** @deprecated Use "TITLE" instead. */ SUBTITLE = 'subtitle', TITLE = 'title', } export enum BentoTypographyModifier { WIDE = 'wide', STRONGER = 'stronger', STRONGER_WIDE = 'stronger-wide', STRONGEST = 'strongest', STRONGEST_WIDE = 'strongest-wide', MEDIUM = 'm', LARGE = 'l', MOBILE = 'mobile', } /** * @deprecated for usage with properties since version 2.0. Use the string literal instead. */ export enum BentoTypographyElement { H1 = 'h1', H2 = 'h2', H3 = 'h3', H4 = 'h4', H5 = 'h5', H6 = 'h6', DIV = 'div', PARAGRAPH = 'p', SPAN = 'span', } export interface BentoTypographyProps { /** * Sets the HTML DOM element. * @values h1, h2, h3, h4, h5, h6, div, p, span */ el?: BentoTypographyElement | `${BentoTypographyElement}`; /** * Adds the large class modifier. * Applicable to the Title variant. */ large?: boolean; /** * Adds the medium class modifier. * Applicable to the Title variant. */ medium?: boolean; /** * Adds the rich-text modifier, which allows for the use of HTML tags inside typography. */ richText?: boolean; /** * Adds the stronger class modifier. * Applicable to Caption, Body and Subtitle variants. */ stronger?: boolean; /** * Adds the strongest class modifier. * Applicable to Caption, Body and Subtitle variants. */ strongest?: boolean; /** * Sets the type of typography variant. * @values caption, body, title. */ variant?: BentoTypographyVariant | `${BentoTypographyVariant}`; /** * Adds the medium class modifier. * Applicable to the Body variant. */ wide?: boolean; }
@@ -0,0 +1,102 @@
1
+ [
2
+ "BentoAccordion",
3
+ "BentoAccordionItem",
4
+ "BentoActionBar",
5
+ "BentoAiTag",
6
+ "BentoAlert",
7
+ "BentoAnchorScroller",
8
+ "BentoAvatar",
9
+ "BentoBaseFilter",
10
+ "BentoButton",
11
+ "BentoButtonActions",
12
+ "BentoCard",
13
+ "BentoCheckbox",
14
+ "BentoCheckboxGroup",
15
+ "BentoChip",
16
+ "BentoClickOutside",
17
+ "BentoCodeSnippet",
18
+ "BentoCountry",
19
+ "BentoCurrency",
20
+ "BentoDashboardSection",
21
+ "BentoDashboardTemplate",
22
+ "BentoDashedUnderline",
23
+ "BentoDataGrid",
24
+ "BentoDataGridStaticIcon",
25
+ "BentoDataGridTagWithTextCell",
26
+ "BentoDataGridTemplate",
27
+ "BentoDataGridTrendCell",
28
+ "BentoDate",
29
+ "BentoDatePicker",
30
+ "BentoDateRangePicker",
31
+ "BentoDivider",
32
+ "BentoDropdown",
33
+ "BentoDropdownAvatar",
34
+ "BentoDropdownCountry",
35
+ "BentoDropdownCurrency",
36
+ "BentoDropdownPaymentMethod",
37
+ "BentoDropdownTag",
38
+ "BentoEmptyState",
39
+ "BentoFileUploader",
40
+ "BentoFilterBar",
41
+ "BentoFormLayout",
42
+ "BentoFormLayoutFieldTip",
43
+ "BentoFormLayoutGroup",
44
+ "BentoFormLayoutTitle",
45
+ "BentoHeader",
46
+ "BentoHeaderWithViews",
47
+ "BentoImage",
48
+ "BentoInfoIcon",
49
+ "BentoInputField",
50
+ "BentoInputFieldPassword",
51
+ "BentoInputFieldPhoneNumber",
52
+ "BentoInputTime",
53
+ "BentoInspector",
54
+ "BentoLayout",
55
+ "BentoLayoutRow",
56
+ "BentoLink",
57
+ "BentoList",
58
+ "BentoListItem",
59
+ "BentoLoadingButton",
60
+ "BentoLoadingIndicator",
61
+ "BentoMenu",
62
+ "BentoModal",
63
+ "BentoModalFullscreen",
64
+ "BentoModalFullscreenPage",
65
+ "BentoModalPage",
66
+ "BentoPagination",
67
+ "BentoPaymentMethod",
68
+ "BentoPopover",
69
+ "BentoPromoBanner",
70
+ "BentoRadioButton",
71
+ "BentoRadioGroup",
72
+ "BentoRichTextEditor",
73
+ "BentoSearchBar",
74
+ "BentoSecondaryNav",
75
+ "BentoSegmentedControl",
76
+ "BentoSelectionCard",
77
+ "BentoSelectionCardGroup",
78
+ "BentoSidepanel",
79
+ "BentoSidepanelPage",
80
+ "BentoStatus",
81
+ "BentoStep",
82
+ "BentoStepper",
83
+ "BentoStructuredList",
84
+ "BentoStructuredListItem",
85
+ "BentoSummaryGrid",
86
+ "BentoSummaryGridItemAmount",
87
+ "BentoSummaryGridItemCustom",
88
+ "BentoSummaryGridItemNumeric",
89
+ "BentoSummaryGridItemPercentage",
90
+ "BentoSummaryGridItemText",
91
+ "BentoTab",
92
+ "BentoTabs",
93
+ "BentoTag",
94
+ "BentoTextarea",
95
+ "BentoTimeline",
96
+ "BentoTimelineItem",
97
+ "BentoToast",
98
+ "BentoToggle",
99
+ "BentoToggleButton",
100
+ "BentoTutorial",
101
+ "BentoTypography"
102
+ ]
@@ -0,0 +1 @@
1
+ import { type App, isVue2, type Vue2 } from 'vue-demi'; import { useBentoThemeKey } from './use-bento-theme.types'; import { BentoTheme } from './install.types'; const getTheme = () => document.body.className.match(/b-\w+-theme/)?.[0] ?? ''; const getThemeForSystemPreference = () => { const preferredDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches; if (preferredDarkMode) { return BentoTheme.BENTO_DARK; } return BentoTheme.BENTO_LIGHT; }; export const setTheme = (theme: BentoTheme) => { const currentTheme = getTheme(); const systemTheme = getThemeForSystemPreference(); const themeToSet = theme === BentoTheme.BENTO_SYSTEM ? systemTheme : theme; if (themeToSet === BentoTheme.BENTO_LIGHT || themeToSet === BentoTheme.BENTO) { document.documentElement.style.colorScheme = 'light'; } else if (themeToSet === BentoTheme.BENTO_DARK) { document.documentElement.style.colorScheme = 'dark'; } // if theme is different from current and it is not `BentoTheme.BENTO` if (currentTheme.length && currentTheme !== themeToSet) { document.body.classList.remove(currentTheme); } // if theme is not `BentoTheme.BENTO` if (themeToSet.length) { document.body.classList.add(themeToSet); } }; /** * This function is used to create and register global reactive state necessary for theme to operate. * @param {Vue} Vue A context application to register global state with. */ export default Vue => { const themeProvider = { getTheme, setTheme, }; if (isVue2) { // Add theme as a global property as there is no "app.provide" functionality in Vue2 // eslint-disable-next-line no-param-reassign -- this is an official way of setting up instance properties on Vue (Vue as typeof Vue2).prototype[useBentoThemeKey] = themeProvider; } else { (Vue as App).provide(useBentoThemeKey, themeProvider); } };
@@ -0,0 +1 @@
1
+ export enum BentoTheme { /** * @deprecated in favor of {@link BENTO_LIGHT}. To be removed in v2.0.0. */ LEGACY = 'b-legacy-theme', STYLEGUIDE = 'b-styleguide-theme', /** * @deprecated in favor of {@link BENTO_LIGHT}. To be removed in v2.0.0. */ BENTO = '', BENTO_LIGHT = 'b-light-theme', BENTO_DARK = 'b-dark-theme', BENTO_SYSTEM = 'b-system', }
@@ -0,0 +1 @@
1
+ import { type BentoTheme } from './install.types'; export const useBentoThemeKey = Symbol('use-bento-theme'); export interface UseBentoTheme { getTheme: () => string; setTheme: (theme: BentoTheme | `${BentoTheme}`) => void; }
@@ -0,0 +1 @@
1
+ import { type App, isVue2, type Vue2 } from 'vue-demi'; import { createToastStack, toastStackInjectionKey } from './toast-stack'; /** * This function is used to create and register global reactive state necessary fro the Toasts to operate. * @param {Vue} Vue A context application to register global state with. */ export default Vue => { if (isVue2) { // Add toast stack as a global property as there is no "app.provide" functionality in Vue2 // eslint-disable-next-line no-param-reassign -- this is an official way of setting up instance properties on Vue (Vue as typeof Vue2).prototype[toastStackInjectionKey] = createToastStack(); } else { (Vue as App).provide(toastStackInjectionKey, createToastStack()); } };
@@ -0,0 +1 @@
1
+ import { type DeepReadonly, type Ref } from 'vue'; export interface BentoToastItemAction { handler: () => void; text: string; } export interface BentoToastItemParams { action?: BentoToastItemAction; text: string; } export interface BentoToastItem extends BentoToastItemParams { id: string; dismiss: () => void; } export type BentoToastItemsList = Array<BentoToastItem>; interface Toast { dismiss: () => void; } export interface ToastStack { stack: DeepReadonly<Ref<BentoToastItemsList>>; addToast: (params: BentoToastItemParams) => Toast; } export type UseBentoToastController = ToastStack;
@@ -0,0 +1 @@
1
+ import type { typeToFlattenedError } from 'zod'; /** * Object of all the form field props with their respective list of errors * @deprecated For usage with Zod/v3. Migrate to Zod/v4 and use `@adyen/bento-vue2/use-form-v4' instead or migrate to Vue3 and use Vee-Validate instead. */ export type ErrorBag<T> = typeToFlattenedError<T, string>['fieldErrors']; /** * Extracts all the keys from a type * @deprecated For usage with Zod/v3. Migrate to Zod/v4 and use `@adyen/bento-vue2/use-form-v4' instead or migrate to Vue3 and use Vee-Validate instead. */ export type allKeys<T> = T extends any ? keyof T : never; /** * useForm composable configuration object * @deprecated For usage with Zod/v3. Migrate to Zod/v4 and use `@adyen/bento-vue2/use-form-v4' instead or migrate to Vue3 and use Vee-Validate instead. */ export interface UseForm<T> { validationSchema: T; }
@@ -0,0 +1 @@
1
+ import type { typeToFlattenedError } from 'zod'; /** * Object of all the form field props with their respective list of errors */ export type ErrorBag<T> = typeToFlattenedError<T, string>['fieldErrors']; /** * Extracts all the keys from a type */ export type allKeys<T> = T extends any ? keyof T : never; /** * useForm composable configuration object */ export interface UseForm<T> { validationSchema: T; }
@@ -0,0 +1 @@
1
+ import type { Ref, UnwrapRef } from 'vue'; import type { StyleValue } from 'vue/types/jsx.d.ts'; export type UseVirtualListItemHeight = number | ((index: number) => number); export interface UseVirtualListOptions { disabled?: boolean; prefixHeight?: Ref<number>; itemHeight: UseVirtualListItemHeight; overscan?: number; } export interface UseVirtualListContainerProps { ref: Ref<UnwrapRef<HTMLElement | null>>; style: StyleValue; } export interface UseVirtualListWrapperProps { style: StyleValue; } export interface UseVirtualListItem<T> { data: T; index: number; }