@bethinkpl/design-system 40.1.0 → 41.0.1

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 (68) hide show
  1. package/dist/design-system.css +1 -1
  2. package/dist/design-system.js +7004 -6905
  3. package/dist/design-system.js.map +1 -1
  4. package/dist/lib/js/components/Cards/Card/Card.vue.d.ts +2 -9
  5. package/dist/lib/js/components/Cards/CardExpandable/CardExpandable.vue.d.ts +2 -36
  6. package/dist/lib/js/components/DatePickers/DatePicker/DatePicker.vue.d.ts +1 -1
  7. package/dist/lib/js/components/Drawer/DrawerTile/DrawerTile.vue.d.ts +2 -2
  8. package/dist/lib/js/components/LabelValue/LabelValueItem/LabelValueItem.consts.d.ts +17 -0
  9. package/dist/lib/js/components/LabelValue/LabelValueItem/LabelValueItem.vue.d.ts +27 -0
  10. package/dist/lib/js/components/LabelValue/LabelValueItemGroup/LabelValueItemGroup.vue.d.ts +13 -0
  11. package/dist/lib/js/components/Pagination/Pagination.vue.d.ts +6 -2
  12. package/dist/lib/js/components/RichList/BasicRichListItem/BasicRichListItem.vue.d.ts +3 -12
  13. package/dist/lib/js/components/RichList/RichListItem/RichListItem.vue.d.ts +1 -1
  14. package/dist/lib/js/components/SelectList/SelectListItem/SelectListItem.vue.d.ts +6 -2
  15. package/dist/lib/js/components/SelectList/SelectListItemToggle/SelectListItemToggle.vue.d.ts +6 -2
  16. package/dist/lib/js/components/Stepper/Stepper.vue.d.ts +23 -0
  17. package/dist/lib/js/components/Stepper/index.d.ts +3 -0
  18. package/dist/lib/js/components/SurveyQuestions/SurveyQuestionOpenEnded/SurveyQuestionOpenEnded.vue.d.ts +2 -36
  19. package/dist/lib/js/components/SurveyQuestions/SurveyQuestionScale/SurveyQuestionScale.vue.d.ts +2 -36
  20. package/dist/lib/js/components/TextGroup/TextGroup.vue.d.ts +0 -3
  21. package/dist/lib/js/components/Tile/Tile.vue.d.ts +1 -1
  22. package/dist/lib/js/components/Toast/Toast.vue.d.ts +2 -36
  23. package/dist/lib/js/components/Toggles/ToggleButton/ToggleButton.vue.d.ts +1 -1
  24. package/dist/lib/js/components/TopNav/TopNav/TopNav.vue.d.ts +17 -0
  25. package/dist/lib/js/components/TopNav/TopNavBranding/TopNavBranding.vue.d.ts +33 -0
  26. package/dist/lib/js/components/TopNav/topNavStoryLogo.d.ts +1 -0
  27. package/dist/lib/js/index.d.ts +6 -5
  28. package/lib/js/components/Cards/Card/Card.spec.ts +50 -0
  29. package/lib/js/components/Cards/Card/Card.stories.ts +5 -0
  30. package/lib/js/components/Cards/Card/Card.vue +14 -11
  31. package/lib/js/components/LabelValue/LabelValueItem/LabelValueItem.consts.ts +20 -0
  32. package/lib/js/components/LabelValue/LabelValueItem/LabelValueItem.spec.ts +125 -0
  33. package/lib/js/components/LabelValue/LabelValueItem/LabelValueItem.stories.ts +69 -0
  34. package/lib/js/components/LabelValue/LabelValueItem/LabelValueItem.vue +101 -0
  35. package/lib/js/components/LabelValue/LabelValueItemGroup/LabelValueItemGroup.spec.ts +24 -0
  36. package/lib/js/components/LabelValue/LabelValueItemGroup/LabelValueItemGroup.stories.ts +31 -0
  37. package/lib/js/components/LabelValue/LabelValueItemGroup/LabelValueItemGroup.vue +19 -0
  38. package/lib/js/components/RichList/BasicRichListItem/BasicRichListItem.stories.ts +93 -8
  39. package/lib/js/components/RichList/BasicRichListItem/BasicRichListItem.vue +3 -0
  40. package/lib/js/components/RichList/RichListItem/RichListItem.stories.ts +83 -0
  41. package/lib/js/components/RichList/RichListItem/RichListItem.vue +11 -4
  42. package/lib/js/components/SelectList/SelectListItem/SelectListItem.stories.ts +7 -0
  43. package/lib/js/components/SelectList/SelectListItem/SelectListItem.vue +9 -3
  44. package/lib/js/components/Stepper/Stepper.spec.ts +99 -0
  45. package/lib/js/components/Stepper/Stepper.stories.ts +62 -0
  46. package/lib/js/components/Stepper/Stepper.vue +97 -0
  47. package/lib/js/components/Stepper/index.ts +3 -0
  48. package/lib/js/components/TextGroup/TextGroup.vue +0 -5
  49. package/lib/js/components/TopNav/TopNav/TopNav.spec.ts +56 -0
  50. package/lib/js/components/TopNav/TopNav/TopNav.stories.ts +99 -0
  51. package/lib/js/components/TopNav/TopNav/TopNav.vue +79 -0
  52. package/lib/js/components/TopNav/TopNavBranding/TopNavBranding.spec.ts +103 -0
  53. package/lib/js/components/TopNav/TopNavBranding/TopNavBranding.stories.ts +107 -0
  54. package/lib/js/components/TopNav/TopNavBranding/TopNavBranding.vue +102 -0
  55. package/lib/js/components/TopNav/topNavStoryLogo.ts +19 -0
  56. package/lib/js/index.ts +6 -5
  57. package/lib/js/styles/Radiuses/Radiuses.stories.ts +44 -0
  58. package/lib/js/styles/Shadows/Shadows.stories.scss +33 -0
  59. package/lib/js/styles/Shadows/Shadows.stories.ts +37 -0
  60. package/package.json +1 -1
  61. package/dist/lib/js/components/Drawer/DrawerListItem/DrawerListItem.consts.d.ts +0 -5
  62. package/dist/lib/js/components/Drawer/DrawerListItem/DrawerListItem.vue.d.ts +0 -406
  63. package/dist/lib/js/components/Drawer/DrawerListItemGroup/DrawerListItemGroup.vue.d.ts +0 -2
  64. package/lib/js/components/Drawer/DrawerListItem/DrawerListItem.consts.ts +0 -7
  65. package/lib/js/components/Drawer/DrawerListItem/DrawerListItem.stories.ts +0 -44
  66. package/lib/js/components/Drawer/DrawerListItem/DrawerListItem.vue +0 -83
  67. package/lib/js/components/Drawer/DrawerListItemGroup/DrawerListItemGroup.stories.ts +0 -31
  68. package/lib/js/components/Drawer/DrawerListItemGroup/DrawerListItemGroup.vue +0 -21
@@ -4,6 +4,9 @@ import { withActions } from '@storybook/addon-actions/decorator';
4
4
  import { useArgs } from '@storybook/preview-api';
5
5
  import { Args, ArgTypes, Meta, StoryFn } from '@storybook/vue3';
6
6
  import { DsImage } from '../../../index';
7
+ import SlotPlaceholder, {
8
+ SLOT_PLACEHOLDER_SIZES,
9
+ } from '../../../../../.storybook/SlotPlaceholder/SlotPlaceholder.vue';
7
10
  import { ICON_COLORS, ICONS } from '../../Icons/Icon';
8
11
  import {
9
12
  RICH_LIST_ITEM_BACKGROUND_COLOR,
@@ -14,6 +17,7 @@ import {
14
17
  RICH_LIST_ITEM_STATE,
15
18
  RICH_LIST_ITEM_TYPE,
16
19
  } from '../RichListItem';
20
+ import { toRefs } from 'vue';
17
21
 
18
22
  export default {
19
23
  title: 'Components/RichList/BasicRichListItem',
@@ -90,6 +94,9 @@ const expandStory = (story: StoryFn<typeof BasicRichListItem>, args = {}) => {
90
94
  metadata: {
91
95
  control: 'text',
92
96
  },
97
+ leadingAccessory: {
98
+ control: 'text',
99
+ },
93
100
  textSlot: {
94
101
  control: 'text',
95
102
  },
@@ -141,6 +148,7 @@ const expandStory = (story: StoryFn<typeof BasicRichListItem>, args = {}) => {
141
148
  isSupportingTextTooltipEnabled: false,
142
149
 
143
150
  metadata: 'Metadata Slot',
151
+ leadingAccessory: '',
144
152
  textSlot: '',
145
153
  actions: 'ACS',
146
154
 
@@ -167,11 +175,9 @@ const InteractiveStoryTemplate: StoryFn<typeof BasicRichListItem> = (args) => {
167
175
  return {
168
176
  components: { BasicRichListItem },
169
177
  setup() {
170
- return args;
171
- },
172
- data() {
173
178
  return {
174
- ICONS: Object.freeze(ICONS),
179
+ ...toRefs(args),
180
+ ICONS,
175
181
  };
176
182
  },
177
183
  methods: {
@@ -213,6 +219,9 @@ const InteractiveStoryTemplate: StoryFn<typeof BasicRichListItem> = (args) => {
213
219
  <template v-if="metadata" #metadata>
214
220
  <div v-html="metadata" />
215
221
  </template>
222
+ <template v-if="leadingAccessory" #leadingAccessory>
223
+ <div v-html="leadingAccessory" />
224
+ </template>
216
225
  <template v-if="textSlot" #text>
217
226
  <div v-html="textSlot" />
218
227
  </template>
@@ -226,17 +235,88 @@ const InteractiveStoryTemplate: StoryFn<typeof BasicRichListItem> = (args) => {
226
235
  export const Interactive = InteractiveStoryTemplate.bind({});
227
236
  expandStory(Interactive);
228
237
 
238
+ const PlaceholderSlotsStoryTemplate: StoryFn<typeof BasicRichListItem> = (args) => {
239
+ const [_, updateArgs] = useArgs();
240
+
241
+ return {
242
+ components: { BasicRichListItem, SlotPlaceholder },
243
+ setup() {
244
+ return {
245
+ ...toRefs(args),
246
+ SLOT_PLACEHOLDER_SIZES,
247
+ };
248
+ },
249
+ methods: {
250
+ updateIsSelected(isSelected) {
251
+ updateArgs({ isSelected });
252
+ },
253
+ },
254
+ template: `
255
+ <basic-rich-list-item
256
+ :size="size"
257
+ :type="type"
258
+ :layout="layout"
259
+ :is-interactive="isInteractive"
260
+ :is-draggable="isDraggable"
261
+ :is-dimmed="isDimmed"
262
+ :border-color="borderColor"
263
+ :border-color-hex="borderColorHex"
264
+ :eyebrow="eyebrow === 'null' ? null : eyebrow"
265
+ :eyebrow-ellipsis="eyebrowEllipsis"
266
+ :is-eyebrow-uppercase="isEyebrowUppercase"
267
+ :text="text"
268
+ :text-ellipsis="textEllipsis"
269
+ :supporting-text="supportingText === 'null' ? null : supportingText"
270
+ :supporting-text-ellipsis="supportingTextEllipsis"
271
+ :is-supporting-text-tooltip-enabled="isSupportingTextTooltipEnabled"
272
+ :state="state"
273
+ :background-color="backgroundColor"
274
+ :elevation="elevation"
275
+ :has-draggable-handler="hasDraggableHandler"
276
+ :has-actions-slot-divider="hasActionsSlotDivider"
277
+ :is-selectable="isSelectable"
278
+ :is-selected="isSelected"
279
+ @update:is-selected="updateIsSelected"
280
+ >
281
+ <template #media>
282
+ <slot-placeholder :size="SLOT_PLACEHOLDER_SIZES.SMALL" label="media" />
283
+ </template>
284
+ <template #leadingAccessory>
285
+ <slot-placeholder :size="SLOT_PLACEHOLDER_SIZES.SMALL" label="leadingAccessory" />
286
+ </template>
287
+ <template #text>
288
+ <slot-placeholder :size="SLOT_PLACEHOLDER_SIZES.SMALL" label="text" />
289
+ </template>
290
+ <template #metadata>
291
+ <slot-placeholder :size="SLOT_PLACEHOLDER_SIZES.SMALL" label="metadata" />
292
+ </template>
293
+ <template #actions>
294
+ <slot-placeholder :size="SLOT_PLACEHOLDER_SIZES.SMALL" label="actions" />
295
+ </template>
296
+ </basic-rich-list-item>`,
297
+ };
298
+ };
299
+
300
+ export const PlaceholderSlots = PlaceholderSlotsStoryTemplate.bind({});
301
+ expandStory(PlaceholderSlots);
302
+ // All slots are provided by the story template, so their controls are not editable.
303
+ PlaceholderSlots.argTypes = {
304
+ ...PlaceholderSlots.argTypes,
305
+ leadingAccessory: { control: false },
306
+ metadata: { control: false },
307
+ textSlot: { control: false },
308
+ actions: { control: false },
309
+ } as ArgTypes;
310
+
229
311
  const WithMediaStoryTemplate: StoryFn<typeof BasicRichListItem> = (args) => {
230
312
  const [_, updateArgs] = useArgs();
231
313
 
232
314
  return {
233
315
  components: { BasicRichListItem, DsImage },
234
316
  setup() {
235
- return args;
236
- },
237
- data() {
238
317
  return {
239
- ICONS: Object.freeze(ICONS),
318
+ ...toRefs(args),
319
+ ICONS,
240
320
  };
241
321
  },
242
322
  methods: {
@@ -293,3 +373,8 @@ expandStory(WithMedia, {
293
373
  imageSrcUsedInStoryBook:
294
374
  'https://storage.googleapis.com/media-manager/lek/018f6291-3956-7342-8e6b-0ee901d48643/018f6291-3a56-7213-aef6-b5da7253839f.jpg',
295
375
  });
376
+ // The media story does not use the leadingAccessory slot, so its control is not editable.
377
+ WithMedia.argTypes = {
378
+ ...WithMedia.argTypes,
379
+ leadingAccessory: { control: false },
380
+ } as ArgTypes;
@@ -30,6 +30,9 @@
30
30
  <template v-if="$slots.media" #media>
31
31
  <slot name="media" />
32
32
  </template>
33
+ <template v-if="$slots.leadingAccessory" #leadingAccessory>
34
+ <slot name="leadingAccessory" />
35
+ </template>
33
36
  <template #content>
34
37
  <div class="ds-basicRichListItem__content">
35
38
  <ds-text-group
@@ -12,6 +12,9 @@ import {
12
12
  } from './RichListItem.consts';
13
13
  import { ICON_COLORS, ICONS } from '../../Icons/Icon';
14
14
  import { DsImage } from '../../../index';
15
+ import SlotPlaceholder, {
16
+ SLOT_PLACEHOLDER_SIZES,
17
+ } from '../../../../../.storybook/SlotPlaceholder/SlotPlaceholder.vue';
15
18
  import { useArgs } from '@storybook/preview-api';
16
19
  import { withActions } from '@storybook/addon-actions/decorator';
17
20
 
@@ -66,6 +69,9 @@ const expandStory = (story: StoryFn<typeof RichListItem>, args = {}) => {
66
69
  content: {
67
70
  control: 'text',
68
71
  },
72
+ leadingAccessory: {
73
+ control: 'text',
74
+ },
69
75
  metadata: {
70
76
  control: 'text',
71
77
  },
@@ -107,6 +113,7 @@ const expandStory = (story: StoryFn<typeof RichListItem>, args = {}) => {
107
113
  draggableIconClassName: 'draggableIconClassName-1',
108
114
 
109
115
  content: 'Content Slot',
116
+ leadingAccessory: '',
110
117
  metadata: 'Metadata Slot',
111
118
  actions: 'ACS',
112
119
 
@@ -170,6 +177,9 @@ const InteractiveStoryTemplate: StoryFn<typeof RichListItem> = (args) => {
170
177
  <template v-if="content" #content>
171
178
  <div v-html="content" />
172
179
  </template>
180
+ <template v-if="leadingAccessory" #leadingAccessory>
181
+ <div v-html="leadingAccessory" />
182
+ </template>
173
183
  <template v-if="metadata" #metadata>
174
184
  <div v-html="metadata" />
175
185
  </template>
@@ -183,6 +193,74 @@ const InteractiveStoryTemplate: StoryFn<typeof RichListItem> = (args) => {
183
193
  export const Interactive = InteractiveStoryTemplate.bind({});
184
194
  expandStory(Interactive);
185
195
 
196
+ const PlaceholderSlotsStoryTemplate: StoryFn<typeof RichListItem> = (args) => {
197
+ const [_, updateArgs] = useArgs();
198
+
199
+ return {
200
+ components: { RichListItem, SlotPlaceholder },
201
+ setup() {
202
+ return args;
203
+ },
204
+ data() {
205
+ return {
206
+ SLOT_PLACEHOLDER_SIZES,
207
+ };
208
+ },
209
+ methods: {
210
+ updateIsSelected(isSelected) {
211
+ updateArgs({ isSelected });
212
+ },
213
+ },
214
+ template: `
215
+ <rich-list-item
216
+ :size="size"
217
+ :type="type"
218
+ :layout="layout"
219
+ :is-interactive="isInteractive"
220
+ :is-draggable="isDraggable"
221
+ :is-dimmed="isDimmed"
222
+ :border-color="borderColor"
223
+ :border-color-hex="borderColorHex"
224
+ :draggable-icon-class-name="draggableIconClassName"
225
+ :state="state"
226
+ :background-color="backgroundColor"
227
+ :elevation="elevation"
228
+ :has-draggable-handler="hasDraggableHandler"
229
+ :has-actions-slot-divider="hasActionsSlotDivider"
230
+ :is-selectable="isSelectable"
231
+ :is-selected="isSelected"
232
+ @update:is-selected="updateIsSelected"
233
+ >
234
+ <template #media>
235
+ <slot-placeholder :size="SLOT_PLACEHOLDER_SIZES.SMALL" label="media" />
236
+ </template>
237
+ <template #leadingAccessory>
238
+ <slot-placeholder :size="SLOT_PLACEHOLDER_SIZES.SMALL" label="leadingAccessory" />
239
+ </template>
240
+ <template #content>
241
+ <slot-placeholder :size="SLOT_PLACEHOLDER_SIZES.SMALL" label="content" />
242
+ </template>
243
+ <template #metadata>
244
+ <slot-placeholder :size="SLOT_PLACEHOLDER_SIZES.SMALL" label="metadata" />
245
+ </template>
246
+ <template #actions>
247
+ <slot-placeholder :size="SLOT_PLACEHOLDER_SIZES.SMALL" label="actions" />
248
+ </template>
249
+ </rich-list-item>`,
250
+ };
251
+ };
252
+
253
+ export const PlaceholderSlots = PlaceholderSlotsStoryTemplate.bind({});
254
+ expandStory(PlaceholderSlots);
255
+ // All slots are provided by the story template, so their controls are not editable.
256
+ PlaceholderSlots.argTypes = {
257
+ ...PlaceholderSlots.argTypes,
258
+ content: { control: false },
259
+ leadingAccessory: { control: false },
260
+ metadata: { control: false },
261
+ actions: { control: false },
262
+ } as ArgTypes;
263
+
186
264
  const WithMediaStoryTemplate: StoryFn<typeof RichListItem> = (args) => {
187
265
  const [_, updateArgs] = useArgs();
188
266
 
@@ -245,3 +323,8 @@ expandStory(WithMedia, {
245
323
  imageSrcUsedInStoryBook:
246
324
  'https://storage.googleapis.com/media-manager/lek/018f6291-3956-7342-8e6b-0ee901d48643/018f6291-3a56-7213-aef6-b5da7253839f.jpg',
247
325
  });
326
+ // The media story does not use the leadingAccessory slot, so its control is not editable.
327
+ WithMedia.argTypes = {
328
+ ...WithMedia.argTypes,
329
+ leadingAccessory: { control: false },
330
+ } as ArgTypes;
@@ -37,6 +37,9 @@
37
37
  @click.prevent="$emit('icon-click')"
38
38
  />
39
39
  </div>
40
+ <div v-if="$slots.leadingAccessory" class="ds-richListItem__leadingAccessory">
41
+ <slot name="leadingAccessory" />
42
+ </div>
40
43
  <div class="ds-richListItem__content">
41
44
  <slot name="content" />
42
45
  </div>
@@ -136,7 +139,8 @@ $rich-list-item-media-horizontal-height: 80px;
136
139
  }
137
140
 
138
141
  #{$root}__dragAndDrop,
139
- #{$root}__iconWrapper {
142
+ #{$root}__iconWrapper,
143
+ #{$root}__leadingAccessory {
140
144
  align-items: center;
141
145
  padding: $space-3 $space-1 $space-3 $space-8;
142
146
  }
@@ -171,7 +175,8 @@ $rich-list-item-media-horizontal-height: 80px;
171
175
  padding: 0 $space-2 0 0;
172
176
 
173
177
  #{$root}__dragAndDrop,
174
- #{$root}__iconWrapper {
178
+ #{$root}__iconWrapper,
179
+ #{$root}__leadingAccessory {
175
180
  padding: $space-3 0 $space-3 $space-6;
176
181
  }
177
182
 
@@ -211,7 +216,8 @@ $rich-list-item-media-horizontal-height: 80px;
211
216
  }
212
217
 
213
218
  #{$root}__dragAndDrop,
214
- #{$root}__iconWrapper {
219
+ #{$root}__iconWrapper,
220
+ #{$root}__leadingAccessory {
215
221
  align-items: flex-start;
216
222
  padding: $space-6 0 0 $space-6;
217
223
  }
@@ -244,7 +250,8 @@ $rich-list-item-media-horizontal-height: 80px;
244
250
 
245
251
  &.-ds-small {
246
252
  #{$root}__dragAndDrop,
247
- #{$root}__iconWrapper {
253
+ #{$root}__iconWrapper,
254
+ #{$root}__leadingAccessory {
248
255
  padding: $space-4 $space-2 0 $space-4;
249
256
  }
250
257
 
@@ -39,6 +39,9 @@ const StoryTemplate: StoryFn<typeof SelectListItem> = (args) => ({
39
39
  <template v-if="args.accessorySlot" #accessory>
40
40
  <slot-placeholder :size="SLOT_PLACEHOLDER_SIZES.SMALL" :label="args.accessorySlot" />
41
41
  </template>
42
+ <template v-if="args.metadataSlot" #metadata>
43
+ <slot-placeholder :size="SLOT_PLACEHOLDER_SIZES.SMALL" :label="args.metadataSlot" />
44
+ </template>
42
45
  </select-list-item>
43
46
  `,
44
47
  });
@@ -55,6 +58,7 @@ const args = {
55
58
  isSelected: false,
56
59
  selectionMode: SELECT_LIST_ITEM_SELECTION_MODE.SELECT_ONLY,
57
60
  accessorySlot: 'accessory',
61
+ metadataSlot: 'metadata',
58
62
  } as Args;
59
63
 
60
64
  const argTypes = {
@@ -77,6 +81,9 @@ const argTypes = {
77
81
  accessorySlot: {
78
82
  control: 'text',
79
83
  },
84
+ metadataSlot: {
85
+ control: 'text',
86
+ },
80
87
  } as ArgTypes;
81
88
 
82
89
  Interactive.argTypes = argTypes;
@@ -30,13 +30,15 @@
30
30
  <span class="ds-selectListItem__text">{{ label }}</span>
31
31
  </span>
32
32
 
33
+ <slot name="metadata" />
34
+
33
35
  <ds-icon
34
36
  v-if="isSelected"
35
37
  class="ds-selectListItem__iconRight"
36
38
  :icon="ICONS.FA_CHECK_SOLID"
37
39
  :size="ICON_SIZES.XX_SMALL"
38
40
  />
39
- <div v-else class="ds-selectListItem__placeholderRight" />
41
+ <div v-else-if="!hasMetadata" class="ds-selectListItem__placeholderRight" />
40
42
  </div>
41
43
  </template>
42
44
 
@@ -107,12 +109,10 @@
107
109
 
108
110
  &__iconRight {
109
111
  color: $color-primary-icon;
110
- margin-left: $space-6;
111
112
  }
112
113
 
113
114
  &__placeholderRight {
114
115
  flex-shrink: 0;
115
- margin-left: $space-6;
116
116
  width: $icon-xs;
117
117
  }
118
118
 
@@ -194,6 +194,12 @@ const {
194
194
  state?: SelectListItemState;
195
195
  }>();
196
196
 
197
+ const slots = defineSlots<{
198
+ accessory?: () => any;
199
+ metadata?: () => any;
200
+ }>();
201
+
197
202
  const isLoading = computed(() => state === SELECT_LIST_ITEM_STATES.LOADING);
198
203
  const isDisabled = computed(() => state === SELECT_LIST_ITEM_STATES.DISABLED);
204
+ const hasMetadata = computed(() => !!slots.metadata);
199
205
  </script>
@@ -0,0 +1,99 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { mount } from '@vue/test-utils';
3
+
4
+ import Stepper from './Stepper.vue';
5
+
6
+ interface createComponentOptions {
7
+ title?: string;
8
+ counterLabel?: string;
9
+ hasCounterValue?: boolean;
10
+ totalSteps?: number;
11
+ currentStep?: number;
12
+ }
13
+
14
+ describe('Stepper', () => {
15
+ const createComponent = ({
16
+ title,
17
+ counterLabel,
18
+ hasCounterValue,
19
+ totalSteps = 5,
20
+ currentStep = 1,
21
+ }: createComponentOptions = {}) => {
22
+ return mount(Stepper, {
23
+ props: {
24
+ title,
25
+ counterLabel,
26
+ hasCounterValue,
27
+ totalSteps,
28
+ currentStep,
29
+ },
30
+ });
31
+ };
32
+
33
+ it('should create', () => {
34
+ const component = createComponent();
35
+
36
+ expect(component.exists()).toBe(true);
37
+ });
38
+
39
+ it('renders one step per total step', () => {
40
+ const component = createComponent({ totalSteps: 4 });
41
+
42
+ expect(component.findAll('.ds-stepper__step')).toHaveLength(4);
43
+ });
44
+
45
+ it('marks the steps up to the current step as active', () => {
46
+ const component = createComponent({ totalSteps: 5, currentStep: 2 });
47
+
48
+ const steps = component.findAll('.ds-stepper__step');
49
+ expect(steps[0].classes()).toContain('-ds-active');
50
+ expect(steps[1].classes()).toContain('-ds-active');
51
+ expect(steps[2].classes()).not.toContain('-ds-active');
52
+ expect(steps[3].classes()).not.toContain('-ds-active');
53
+ expect(steps[4].classes()).not.toContain('-ds-active');
54
+ });
55
+
56
+ it('renders the title when provided', () => {
57
+ const title = 'My title';
58
+ const component = createComponent({ title });
59
+
60
+ expect(component.find('.ds-stepper__title').text()).toBe(title);
61
+ });
62
+
63
+ it('renders the counter value with the current and total steps by default', () => {
64
+ const component = createComponent({ totalSteps: 5, currentStep: 3 });
65
+
66
+ expect(component.find('.ds-stepper__counterValue').text()).toBe('3/5');
67
+ });
68
+
69
+ it('renders the counter label when provided', () => {
70
+ const counterLabel = 'Counter Label';
71
+ const component = createComponent({ counterLabel });
72
+
73
+ expect(component.find('.ds-stepper__counterLabel').text()).toBe(counterLabel);
74
+ });
75
+
76
+ it('does not render the counter label when it is not provided', () => {
77
+ const component = createComponent({ counterLabel: undefined });
78
+
79
+ expect(component.find('.ds-stepper__counterLabel').exists()).toBe(false);
80
+ });
81
+
82
+ it('hides only the counter value when hasCounterValue is false', () => {
83
+ const counterLabel = 'Counter Label';
84
+ const component = createComponent({ counterLabel, hasCounterValue: false });
85
+
86
+ expect(component.find('.ds-stepper__counterValue').exists()).toBe(false);
87
+ expect(component.find('.ds-stepper__counterLabel').text()).toBe(counterLabel);
88
+ });
89
+
90
+ it('does not render the header when there is no title, no counter label and the counter value is hidden', () => {
91
+ const component = createComponent({
92
+ title: undefined,
93
+ counterLabel: undefined,
94
+ hasCounterValue: false,
95
+ });
96
+
97
+ expect(component.find('.ds-stepper__header').exists()).toBe(false);
98
+ });
99
+ });
@@ -0,0 +1,62 @@
1
+ import Stepper from './Stepper.vue';
2
+
3
+ import { Args, ArgTypes, Meta, StoryFn } from '@storybook/vue3';
4
+
5
+ export default {
6
+ title: 'Components/Stepper',
7
+ component: Stepper,
8
+ } as Meta<typeof Stepper>;
9
+
10
+ const StoryTemplate: StoryFn<typeof Stepper> = (args) => ({
11
+ components: { Stepper },
12
+ setup() {
13
+ return args;
14
+ },
15
+ template: `
16
+ <stepper
17
+ :title="title"
18
+ :counter-label="counterLabel"
19
+ :has-counter-value="hasCounterValue"
20
+ :total-steps="totalSteps"
21
+ :current-step="currentStep"
22
+ />
23
+ `,
24
+ });
25
+
26
+ export const Interactive = StoryTemplate.bind({});
27
+
28
+ const args = {
29
+ title: 'Title here',
30
+ counterLabel: 'Counter Label',
31
+ hasCounterValue: true,
32
+ totalSteps: 5,
33
+ currentStep: 1,
34
+ } as Args;
35
+
36
+ const argTypes = {
37
+ title: {
38
+ control: 'text',
39
+ },
40
+ counterLabel: {
41
+ control: 'text',
42
+ },
43
+ hasCounterValue: {
44
+ control: 'boolean',
45
+ },
46
+ totalSteps: {
47
+ control: { type: 'number', min: 1 },
48
+ },
49
+ currentStep: {
50
+ control: { type: 'number', min: 0 },
51
+ },
52
+ } as ArgTypes;
53
+
54
+ Interactive.argTypes = argTypes;
55
+ Interactive.args = args;
56
+
57
+ Interactive.parameters = {
58
+ design: {
59
+ type: 'figma',
60
+ url: 'https://www.figma.com/design/xym3gXf0vBCofzksDtRDaU/INI-201-E-commerce?node-id=240-17773&m=dev',
61
+ },
62
+ };
@@ -0,0 +1,97 @@
1
+ <template>
2
+ <div class="ds-stepper">
3
+ <div v-if="title || counterLabel || hasCounterValue" class="ds-stepper__header">
4
+ <div class="ds-stepper__title">
5
+ {{ title }}
6
+ </div>
7
+ <div v-if="counterLabel || hasCounterValue" class="ds-stepper__counter">
8
+ <span v-if="counterLabel" class="ds-stepper__counterLabel">
9
+ {{ counterLabel }}
10
+ </span>
11
+ <span v-if="hasCounterValue" class="ds-stepper__counterValue">
12
+ {{ currentStep }}/{{ totalSteps }}
13
+ </span>
14
+ </div>
15
+ </div>
16
+ <div class="ds-stepper__steps">
17
+ <div
18
+ v-for="step in totalSteps"
19
+ :key="step"
20
+ class="ds-stepper__step"
21
+ :class="{ '-ds-active': step <= currentStep }"
22
+ />
23
+ </div>
24
+ </div>
25
+ </template>
26
+
27
+ <style lang="scss" scoped>
28
+ @import '../../../styles/settings/colors/tokens';
29
+ @import '../../../styles/settings/spacings';
30
+ @import '../../../styles/settings/typography/tokens';
31
+ @import '../../../styles/settings/radiuses';
32
+
33
+ .ds-stepper {
34
+ display: flex;
35
+ flex-direction: column;
36
+ gap: $space-2;
37
+ width: 100%;
38
+
39
+ &__header {
40
+ align-items: baseline;
41
+ display: flex;
42
+ gap: $space-4;
43
+ width: 100%;
44
+ }
45
+
46
+ &__title {
47
+ @include heading-m-default-regular;
48
+
49
+ color: $color-neutral-text-heavy;
50
+ flex: 1 0 0;
51
+ min-width: 0;
52
+ overflow: hidden;
53
+ text-overflow: ellipsis;
54
+ white-space: nowrap;
55
+ }
56
+
57
+ &__counter {
58
+ @include label-m-default-regular;
59
+
60
+ align-items: baseline;
61
+ color: $color-neutral-text-weak;
62
+ display: flex;
63
+ flex-shrink: 0;
64
+ gap: $space-2;
65
+ text-align: right;
66
+ }
67
+
68
+ &__steps {
69
+ align-items: center;
70
+ display: flex;
71
+ gap: $space-2;
72
+ width: 100%;
73
+ }
74
+
75
+ &__step {
76
+ background-color: $color-neutral-background-medium;
77
+ border-radius: $radius-xs;
78
+ flex: 1 0 0;
79
+ height: 4px;
80
+ min-width: 0;
81
+
82
+ &.-ds-active {
83
+ background-color: $color-primary-background-strong;
84
+ }
85
+ }
86
+ }
87
+ </style>
88
+
89
+ <script setup lang="ts">
90
+ const { hasCounterValue = true } = defineProps<{
91
+ title?: string;
92
+ counterLabel?: string;
93
+ hasCounterValue?: boolean;
94
+ totalSteps: number;
95
+ currentStep: number;
96
+ }>();
97
+ </script>
@@ -0,0 +1,3 @@
1
+ import Stepper from './Stepper.vue';
2
+
3
+ export default Stepper;
@@ -372,7 +372,6 @@ import {
372
372
  TEXT_GROUP_PROMINENCE,
373
373
  } from './TextGroup.consts';
374
374
  import DsTooltip from '../Tooltip';
375
- import { RemovedProp } from '../../utils/type.utils';
376
375
 
377
376
  const {
378
377
  size = TEXT_GROUP_SIZES.MEDIUM,
@@ -414,10 +413,6 @@ const {
414
413
  isSupportingTextTooltipEnabledOnMobile?: boolean;
415
414
  isSupportingTextTooltipAutoFilledWithContent?: boolean;
416
415
  supportingTextTooltipContent?: string;
417
-
418
- // Removed prop kept as a removal marker so existing usages fail type-checking.
419
- /** @deprecated use `mainTextColor` set to `primary` instead */
420
- isSelected?: RemovedProp<'use mainTextColor=primary instead'>;
421
416
  }>();
422
417
 
423
418
  const prominenceClassName = computed(() => `-ds-${prominence}`);