@bethinkpl/design-system 30.4.3 → 31.0.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 (68) hide show
  1. package/dist/design-system.css +1 -1
  2. package/dist/design-system.js +4274 -4286
  3. package/dist/design-system.js.map +1 -1
  4. package/dist/lib/js/components/Buttons/IconButton/IconButton.vue.d.ts +1 -0
  5. package/dist/lib/js/components/Cards/CardExpandable/CardExpandable.vue.d.ts +1 -0
  6. package/dist/lib/js/components/Chip/Chip.vue.d.ts +2 -0
  7. package/dist/lib/js/components/DatePickers/DateBox/DateBox.vue.d.ts +1 -0
  8. package/dist/lib/js/components/DatePickers/DatePicker/DatePicker.vue.d.ts +1 -0
  9. package/dist/lib/js/components/DatePickers/DateRangePicker/DateRangePicker.vue.d.ts +1 -0
  10. package/dist/lib/js/components/Drawer/DrawerHeader/DrawerHeader.vue.d.ts +4 -0
  11. package/dist/lib/js/components/Drawer/DrawerListItem/DrawerListItem.vue.d.ts +1 -0
  12. package/dist/lib/js/components/Drawer/DrawerSection/DrawerSection.vue.d.ts +3 -0
  13. package/dist/lib/js/components/Form/RadioButton/RadioButton.vue.d.ts +1 -0
  14. package/dist/lib/js/components/Headers/OverlayHeader/OverlayHeader.vue.d.ts +2 -0
  15. package/dist/lib/js/components/Headers/SectionHeader/SectionHeader.vue.d.ts +2 -0
  16. package/dist/lib/js/components/Icons/Icon/Icon.consts.d.ts +1 -0
  17. package/dist/lib/js/components/Menu/Menu/Menu.consts.d.ts +9 -0
  18. package/dist/lib/js/components/Menu/Menu/Menu.vue.d.ts +28 -0
  19. package/dist/lib/js/components/Menu/Menu/index.d.ts +4 -0
  20. package/dist/lib/js/components/Menu/MenuDivider/MenuDivider.vue.d.ts +71 -0
  21. package/dist/lib/js/components/Menu/MenuDivider/index.d.ts +3 -0
  22. package/dist/lib/js/components/Menu/MenuItem/MenuItem.consts.d.ts +23 -0
  23. package/dist/lib/js/components/Menu/MenuItem/MenuItem.vue.d.ts +68 -0
  24. package/dist/lib/js/components/Menu/MenuItem/index.d.ts +4 -0
  25. package/dist/lib/js/components/Modal/Modal.vue.d.ts +1 -0
  26. package/dist/lib/js/components/Modals/Modal/Modal.vue.d.ts +2 -0
  27. package/dist/lib/js/components/Modals/ModalDialog/ModalDialog.vue.d.ts +2 -0
  28. package/dist/lib/js/components/Pagination/Pagination.vue.d.ts +3 -0
  29. package/dist/lib/js/components/ProgressBar/ProgressBar.vue.d.ts +1 -0
  30. package/dist/lib/js/components/ProgressDonutChart/ProgressDonutChart.vue.d.ts +1 -0
  31. package/dist/lib/js/components/RichList/BasicRichListItem/BasicRichListItem.vue.d.ts +1 -0
  32. package/dist/lib/js/components/RichList/RichListItem/RichListItem.vue.d.ts +1 -0
  33. package/dist/lib/js/components/SelectList/SelectListItem/SelectListItem.vue.d.ts +1 -0
  34. package/dist/lib/js/components/SelectList/SelectListItemToggle/SelectListItemToggle.vue.d.ts +1 -0
  35. package/dist/lib/js/components/Statuses/AccessStatus/AccessStatus.vue.d.ts +1 -0
  36. package/dist/lib/js/components/Statuses/BlockadeStatus/BlockadeStatus.vue.d.ts +1 -0
  37. package/dist/lib/js/components/SurveyQuestions/SurveyQuestionOpenEnded/SurveyQuestionOpenEnded.vue.d.ts +3 -0
  38. package/dist/lib/js/components/SurveyQuestions/SurveyQuestionScale/SurveyQuestionScale.vue.d.ts +3 -0
  39. package/dist/lib/js/components/Switch/Switch.vue.d.ts +1 -0
  40. package/dist/lib/js/components/Tile/Tile.sb.shared.d.ts +1 -0
  41. package/dist/lib/js/components/Toggles/ToggleButton/ToggleButton.vue.d.ts +1 -0
  42. package/dist/lib/js/icons/fontawesome.d.ts +1 -0
  43. package/dist/lib/js/index.d.ts +8 -7
  44. package/lib/js/components/Menu/Menu/Menu.consts.ts +11 -0
  45. package/lib/js/components/Menu/Menu/Menu.spec.ts +134 -0
  46. package/lib/js/components/Menu/Menu/Menu.stories.ts +52 -0
  47. package/lib/js/components/Menu/Menu/Menu.vue +56 -0
  48. package/lib/js/components/Menu/Menu/index.ts +4 -0
  49. package/lib/js/components/{Outline/OutlineDivider/OutlineDivider.stories.ts → Menu/MenuDivider/MenuDivider.stories.ts} +7 -7
  50. package/lib/js/components/{Outline/OutlineDivider/OutlineDivider.vue → Menu/MenuDivider/MenuDivider.vue} +5 -4
  51. package/lib/js/components/Menu/MenuDivider/index.ts +3 -0
  52. package/lib/js/components/Menu/MenuItem/MenuItem.consts.ts +34 -0
  53. package/lib/js/components/Menu/MenuItem/MenuItem.spec.ts +424 -0
  54. package/lib/js/components/Menu/MenuItem/MenuItem.stories.ts +177 -0
  55. package/lib/js/components/Menu/MenuItem/MenuItem.vue +377 -0
  56. package/lib/js/components/Menu/MenuItem/index.ts +4 -0
  57. package/lib/js/icons/fontawesome.ts +2 -0
  58. package/lib/js/index.ts +8 -7
  59. package/package.json +1 -1
  60. package/dist/storybook/localhost:8080/node_modules/.vite/deps/@bethinkpl_design-system.js?v=62a0baa6 +0 -7919
  61. package/lib/js/components/Outline/OutlineDivider/index.ts +0 -3
  62. package/lib/js/components/Outline/OutlineItem/OutlineItem.consts.ts +0 -22
  63. package/lib/js/components/Outline/OutlineItem/OutlineItem.stories.ts +0 -120
  64. package/lib/js/components/Outline/OutlineItem/OutlineItem.vue +0 -325
  65. package/lib/js/components/Outline/OutlineItem/index.ts +0 -4
  66. package/lib/js/components/Outline/OutlineSectionHeader/OutlineSectionHeader.stories.ts +0 -35
  67. package/lib/js/components/Outline/OutlineSectionHeader/OutlineSectionHeader.vue +0 -30
  68. package/lib/js/components/Outline/OutlineSectionHeader/index.ts +0 -3
@@ -0,0 +1,424 @@
1
+ import { describe, expect, it, test } from 'vitest';
2
+ import { mount, shallowMount } from '@vue/test-utils';
3
+ import { h } from 'vue';
4
+ import MenuItem from './MenuItem.vue';
5
+ import {
6
+ MENU_ITEM_ACCESSORY_STATES,
7
+ MENU_ITEM_BACKGROUND_COLORS,
8
+ MENU_ITEM_LEVEL_INJECTION_KEY,
9
+ MENU_ITEM_SIZES,
10
+ MENU_ITEM_STATES,
11
+ } from './MenuItem.consts';
12
+ import { ICONS } from '../../Icons/Icon';
13
+
14
+ describe('MenuItem', () => {
15
+ const createComponent = (props = {} as any, options = {}) => {
16
+ return shallowMount(MenuItem, {
17
+ props: {
18
+ label: 'Test MenuItem',
19
+ ...props,
20
+ },
21
+ ...options,
22
+ });
23
+ };
24
+
25
+ describe('Basic rendering', () => {
26
+ it('renders as span by default', () => {
27
+ const wrapper = createComponent();
28
+ expect(wrapper.find('.ds-menuItem').element.tagName).toBe('SPAN');
29
+ });
30
+
31
+ it('renders label correctly', () => {
32
+ const wrapper = createComponent({ label: 'Test Label' });
33
+ expect(wrapper.find('.ds-menuItem__label').text()).toBe('Test Label');
34
+ });
35
+
36
+ it('renders additional text when provided', () => {
37
+ const wrapper = createComponent({
38
+ additionalText: 'Additional Info',
39
+ });
40
+ expect(wrapper.find('.ds-menuItem__additionalText').text()).toBe('Additional Info');
41
+ });
42
+
43
+ it('renders index when provided', () => {
44
+ const wrapper = createComponent({
45
+ index: 5,
46
+ });
47
+ expect(wrapper.find('.ds-menuItem__index').text()).toBe('5.');
48
+ });
49
+ });
50
+
51
+ describe('Component type rendering', () => {
52
+ it('renders as anchor when href is provided', () => {
53
+ const wrapper = createComponent({ href: 'https://example.com' });
54
+ const menuItem = wrapper.find('.ds-menuItem');
55
+
56
+ expect(menuItem.element.tagName).toBe('A');
57
+ expect(menuItem.attributes('href')).toBe('https://example.com');
58
+ });
59
+
60
+ it('renders as router-link when to prop is provided', () => {
61
+ const wrapper = createComponent({ to: '/test-route' });
62
+
63
+ expect(wrapper.find('.ds-menuItem').element.tagName).toBe('ROUTER-LINK');
64
+ });
65
+
66
+ it('prioritizes href over to prop', () => {
67
+ const wrapper = createComponent({
68
+ href: 'https://example.com',
69
+ to: '/test-route',
70
+ });
71
+ const menuItem = wrapper.find('.ds-menuItem');
72
+
73
+ expect(menuItem.element.tagName).toBe('A');
74
+ expect(menuItem.attributes('href')).toBe('https://example.com');
75
+ });
76
+ });
77
+
78
+ describe('Size variations', () => {
79
+ test.each([
80
+ [MENU_ITEM_SIZES.SMALL, false],
81
+ [MENU_ITEM_SIZES.MEDIUM, true],
82
+ ])('applies correct size class for %s', (size, shouldHaveMediumClass) => {
83
+ const wrapper = createComponent({ size });
84
+ const menuItem = wrapper.find('.ds-menuItem');
85
+
86
+ if (shouldHaveMediumClass) {
87
+ expect(menuItem.classes()).toContain('-ds-medium');
88
+ } else {
89
+ expect(menuItem.classes()).not.toContain('-ds-medium');
90
+ }
91
+ });
92
+ });
93
+
94
+ describe('State variations', () => {
95
+ it('applies disabled class when state is disabled', () => {
96
+ const wrapper = createComponent({ state: MENU_ITEM_STATES.DISABLED });
97
+
98
+ expect(wrapper.find('.ds-menuItem').classes()).toContain('-ds-disabled');
99
+ });
100
+
101
+ it('does not apply disabled class for default state', () => {
102
+ const wrapper = createComponent({ state: MENU_ITEM_STATES.DEFAULT });
103
+
104
+ expect(wrapper.find('.ds-menuItem').classes()).not.toContain('-ds-disabled');
105
+ });
106
+ });
107
+
108
+ describe('Selection state', () => {
109
+ it('applies selected class when isSelected is true', () => {
110
+ const wrapper = createComponent({ isSelected: true });
111
+
112
+ expect(wrapper.find('.ds-menuItem').classes()).toContain('-ds-selected');
113
+ });
114
+
115
+ it('applies hoverable class when not selected', () => {
116
+ const wrapper = createComponent({ isSelected: false });
117
+
118
+ expect(wrapper.find('.ds-menuItem').classes()).toContain('-ds-hoverable');
119
+ });
120
+
121
+ it('applies hoverable class when selected but interactive', () => {
122
+ const wrapper = createComponent({
123
+ isSelected: true,
124
+ isSelectedInteractive: true,
125
+ });
126
+
127
+ expect(wrapper.find('.ds-menuItem').classes()).toContain('-ds-hoverable');
128
+ });
129
+
130
+ it('does not apply hoverable class when selected and not interactive', () => {
131
+ const wrapper = createComponent({
132
+ isSelected: true,
133
+ isSelectedInteractive: false,
134
+ });
135
+
136
+ expect(wrapper.find('.ds-menuItem').classes()).not.toContain('-ds-hoverable');
137
+ });
138
+
139
+ it('applies active class to index when selected', () => {
140
+ const wrapper = createComponent({
141
+ index: 1,
142
+ isSelected: true,
143
+ });
144
+
145
+ expect(wrapper.find('.ds-menuItem__index').classes()).toContain('-ds-active');
146
+ });
147
+ });
148
+
149
+ describe('Background colors', () => {
150
+ test.each([
151
+ [MENU_ITEM_BACKGROUND_COLORS.NEUTRAL_WEAK, false],
152
+ [MENU_ITEM_BACKGROUND_COLORS.NEUTRAL, true],
153
+ ])('applies correct background class for %s', (backgroundColor, shouldHaveNeutralClass) => {
154
+ const wrapper = createComponent({ backgroundColor });
155
+ const menuItem = wrapper.find('.ds-menuItem');
156
+
157
+ if (shouldHaveNeutralClass) {
158
+ expect(menuItem.classes()).toContain('-ds-backgroundNeutral');
159
+ } else {
160
+ expect(menuItem.classes()).not.toContain('-ds-backgroundNeutral');
161
+ }
162
+ });
163
+ });
164
+
165
+ describe('Icons', () => {
166
+ it('renders right icon when provided', () => {
167
+ const wrapper = createComponent({ iconRight: ICONS.FA_CHEVRON_RIGHT });
168
+
169
+ expect(wrapper.find('.ds-menuItem__rightContent').exists()).toBe(true);
170
+ });
171
+
172
+ it('renders done icon when isDone is true', () => {
173
+ const wrapper = createComponent({ isDone: true });
174
+
175
+ expect(wrapper.find('.ds-menuItem__rightContent').exists()).toBe(true);
176
+ });
177
+
178
+ it('renders right content when iconLeft is provided', () => {
179
+ const wrapper = createComponent({ iconLeft: ICONS.FA_CHEVRON_RIGHT });
180
+
181
+ expect(wrapper.find('.ds-menuItem__icon').exists()).toBe(true);
182
+ });
183
+ });
184
+
185
+ describe('Accessory state', () => {
186
+ it('does not render accessory when accessoryState is null', () => {
187
+ const wrapper = createComponent({ accessoryState: null });
188
+
189
+ expect(wrapper.find('.ds-menuItem__accessory').exists()).toBe(false);
190
+ });
191
+
192
+ it('renders dot accessory when accessoryState is dot', () => {
193
+ const wrapper = createComponent({
194
+ accessoryState: MENU_ITEM_ACCESSORY_STATES.DOT,
195
+ });
196
+
197
+ expect(wrapper.find('.ds-menuItem__accessory').exists()).toBe(true);
198
+ });
199
+ });
200
+
201
+ describe('Label variations', () => {
202
+ it('applies uppercase class when isLabelUppercase is true', () => {
203
+ const wrapper = createComponent({
204
+ label: 'Test Label',
205
+ isLabelUppercase: true,
206
+ });
207
+
208
+ expect(wrapper.find('.ds-menuItem__label').classes()).toContain('-ds-uppercase');
209
+ });
210
+
211
+ it('does not apply uppercase class when isLabelUppercase is false', () => {
212
+ const wrapper = createComponent({
213
+ label: 'Test Label',
214
+ isLabelUppercase: false,
215
+ });
216
+
217
+ expect(wrapper.find('.ds-menuItem__label').classes()).not.toContain('-ds-uppercase');
218
+ });
219
+ });
220
+
221
+ describe('Slots', () => {
222
+ it('renders labelSlot when provided and prioritizes labelSlot over label prop', () => {
223
+ const wrapper = mount(MenuItem, {
224
+ props: { label: 'Default Label' },
225
+ slots: {
226
+ labelSlot: '<strong>Custom Label</strong>',
227
+ },
228
+ });
229
+
230
+ expect(wrapper.find('.ds-menuItem__label').html()).toContain(
231
+ '<strong>Custom Label</strong>',
232
+ );
233
+ });
234
+
235
+ it('renders default slot content', () => {
236
+ const wrapper = mount(MenuItem, {
237
+ props: { label: 'Test Label' },
238
+ slots: {
239
+ default: '<span class="custom-content">Custom Content</span>',
240
+ },
241
+ });
242
+
243
+ const rightContent = wrapper.find('.ds-menuItem__rightContent');
244
+ expect(rightContent.exists()).toBe(true);
245
+ expect(rightContent.html()).toContain('Custom Content');
246
+ });
247
+
248
+ it('renders children slot', () => {
249
+ const wrapper = mount(MenuItem, {
250
+ props: { label: 'Test Label' },
251
+ slots: {
252
+ children: '<ul class="nested-menu">Nested Menu</ul>',
253
+ },
254
+ });
255
+
256
+ expect(wrapper.html()).toContain('<ul class="nested-menu">Nested Menu</ul>');
257
+ });
258
+
259
+ it('applies centered content class when default slot is present', () => {
260
+ const wrapper = mount(MenuItem, {
261
+ props: { label: 'Test Label' },
262
+ slots: {
263
+ default: 'Content',
264
+ },
265
+ });
266
+
267
+ expect(wrapper.find('.ds-menuItem__rightContent').classes()).toContain(
268
+ '-ds-centeredContent',
269
+ );
270
+ });
271
+ });
272
+
273
+ describe('Level handling', () => {
274
+ it('applies default level 1 when no level provided', () => {
275
+ const wrapper = createComponent();
276
+
277
+ expect(wrapper.find('.ds-menuItem').classes()).toContain('-ds-level1');
278
+ });
279
+
280
+ it('applies specified level class', () => {
281
+ const wrapper = createComponent({ level: 3 });
282
+
283
+ expect(wrapper.find('.ds-menuItem').classes()).toContain('-ds-level3');
284
+ });
285
+
286
+ it('caps level at 6', () => {
287
+ const wrapper = createComponent({ level: 10 });
288
+ const menuItem = wrapper.find('.ds-menuItem');
289
+
290
+ expect(menuItem.classes()).toContain('-ds-level6');
291
+ expect(menuItem.classes()).not.toContain('-ds-level10');
292
+ });
293
+
294
+ it('uses injected level when no level prop provided', () => {
295
+ const wrapper = shallowMount(MenuItem, {
296
+ props: { label: 'Test Label' },
297
+ global: {
298
+ provide: {
299
+ [MENU_ITEM_LEVEL_INJECTION_KEY]: 4,
300
+ },
301
+ },
302
+ });
303
+
304
+ expect(wrapper.find('.ds-menuItem').classes()).toContain('-ds-level4');
305
+ });
306
+
307
+ it('prioritizes level prop over injected level', () => {
308
+ const wrapper = shallowMount(MenuItem, {
309
+ props: {
310
+ label: 'Test Label',
311
+ level: 2,
312
+ },
313
+ global: {
314
+ provide: {
315
+ [MENU_ITEM_LEVEL_INJECTION_KEY]: 4,
316
+ },
317
+ },
318
+ });
319
+ const menuItem = wrapper.find('.ds-menuItem');
320
+
321
+ expect(menuItem.classes()).toContain('-ds-level2');
322
+ expect(menuItem.classes()).not.toContain('-ds-level4');
323
+ });
324
+
325
+ it('provides incremented level to children', () => {
326
+ let providedLevel: number | null = null;
327
+
328
+ const ChildComponent = {
329
+ setup() {
330
+ const { inject } = require('vue');
331
+ providedLevel = inject(MENU_ITEM_LEVEL_INJECTION_KEY, null);
332
+ return () => h('div', 'child');
333
+ },
334
+ };
335
+
336
+ mount(MenuItem, {
337
+ props: {
338
+ label: 'Test Label',
339
+ level: 2,
340
+ },
341
+ slots: {
342
+ children: () => h(ChildComponent),
343
+ },
344
+ });
345
+
346
+ expect(providedLevel).toBe(3);
347
+ });
348
+ });
349
+
350
+ describe('Conditional rendering', () => {
351
+ it('does not render when no content is provided', () => {
352
+ const wrapper = shallowMount(MenuItem, {
353
+ props: {
354
+ label: '',
355
+ additionalText: '',
356
+ index: null,
357
+ iconLeft: null,
358
+ accessoryState: null,
359
+ },
360
+ });
361
+
362
+ expect(wrapper.find('.ds-menuItem').exists()).toBe(false);
363
+ });
364
+
365
+ it('renders when label is provided', () => {
366
+ const wrapper = createComponent({ label: 'Test' });
367
+ expect(wrapper.find('.ds-menuItem').exists()).toBe(true);
368
+ });
369
+
370
+ it('renders when additionalText is provided', () => {
371
+ const wrapper = createComponent({
372
+ label: '',
373
+ additionalText: 'Additional',
374
+ });
375
+ expect(wrapper.find('.ds-menuItem').exists()).toBe(true);
376
+ });
377
+
378
+ it('renders when index is provided', () => {
379
+ const wrapper = createComponent({
380
+ label: '',
381
+ index: 1,
382
+ });
383
+ expect(wrapper.find('.ds-menuItem').exists()).toBe(true);
384
+ });
385
+
386
+ it('renders when iconLeft is provided with label', () => {
387
+ const wrapper = createComponent({
388
+ label: 'Test',
389
+ iconLeft: ICONS.FA_CHEVRON_RIGHT,
390
+ });
391
+ // Component should render when iconLeft is provided with label
392
+ expect(wrapper.find('.ds-menuItem').exists()).toBe(true);
393
+ });
394
+
395
+ it('renders when accessoryState is provided', () => {
396
+ const wrapper = createComponent({
397
+ label: '',
398
+ accessoryState: MENU_ITEM_ACCESSORY_STATES.DOT,
399
+ });
400
+ expect(wrapper.find('.ds-menuItem').exists()).toBe(true);
401
+ });
402
+
403
+ it('renders right content section when needed', () => {
404
+ // Should not render right content by default
405
+ const wrapper1 = createComponent();
406
+ expect(wrapper1.find('.ds-menuItem__rightContent').exists()).toBe(false);
407
+
408
+ // Should render when isDone is true
409
+ const wrapper2 = createComponent({ isDone: true });
410
+ expect(wrapper2.find('.ds-menuItem__rightContent').exists()).toBe(true);
411
+
412
+ // Should render when iconRight is provided
413
+ const wrapper3 = createComponent({ iconRight: ICONS.FA_CHEVRON_RIGHT });
414
+ expect(wrapper3.find('.ds-menuItem__rightContent').exists()).toBe(true);
415
+
416
+ // Should render when default slot is provided
417
+ const wrapper4 = mount(MenuItem, {
418
+ props: { label: 'Test' },
419
+ slots: { default: 'Content' },
420
+ });
421
+ expect(wrapper4.find('.ds-menuItem__rightContent').exists()).toBe(true);
422
+ });
423
+ });
424
+ });
@@ -0,0 +1,177 @@
1
+ import MenuItem from './MenuItem.vue';
2
+ import DsChip from '../../Chip/Chip.vue';
3
+ import { Args, ArgTypes, Meta, StoryFn } from '@storybook/vue3';
4
+ import { toRefs } from 'vue';
5
+ import { ICONS } from '../../Icons/Icon';
6
+ import {
7
+ MENU_ITEM_ACCESSORY_STATES,
8
+ MENU_ITEM_BACKGROUND_COLORS,
9
+ MENU_ITEM_SIZES,
10
+ MENU_ITEM_STATES,
11
+ } from './MenuItem.consts';
12
+ import DsMenu from '../Menu';
13
+ import SlotPlaceholder, {
14
+ SLOT_PLACEHOLDER_SIZES,
15
+ } from '../../../../../.storybook/SlotPlaceholder/SlotPlaceholder.vue';
16
+
17
+ export default {
18
+ title: 'Components/Menu/MenuItem',
19
+ component: MenuItem,
20
+ } as Meta<typeof MenuItem>;
21
+
22
+ const StoryTemplate: StoryFn<typeof MenuItem> = (args) => ({
23
+ components: { MenuItem, DsChip, SlotPlaceholder },
24
+ setup() {
25
+ const reactiveArgs = toRefs(args);
26
+
27
+ return {
28
+ ...reactiveArgs,
29
+ ICONS,
30
+ SLOT_PLACEHOLDER_SIZES,
31
+ };
32
+ },
33
+ template: `
34
+ <menu-item :label="label" :additional-text="additionalText" :size="size" :state="state"
35
+ :icon-left="ICONS[iconLeft]" :icon-right="ICONS[iconRight]" :is-done="isDone"
36
+ :is-selected="isSelected" :background-color="backgroundColor" :index="index"
37
+ :is-label-uppercase="isLabelUppercase" :icon-right-rotation="iconRightRotation"
38
+ :has-selected-icons-color-primary="hasSelectedIconsColorPrimary"
39
+ :is-selected-interactive="isSelectedInteractive" :level="level"
40
+ :accessoryState="accessoryState">
41
+ <template #labelSlot v-if="labelSlot">
42
+ <span v-html="labelSlot" />
43
+ </template>
44
+ <template #default>
45
+ <slot-placeholder label="defaul slot" :size="SLOT_PLACEHOLDER_SIZES.SMALL" />
46
+ </template>
47
+ <template #children>
48
+ <slot-placeholder label="children slot" />
49
+ </template>
50
+ </menu-item>`,
51
+ });
52
+
53
+ export const Interactive = StoryTemplate.bind({});
54
+
55
+ const args = {
56
+ additionalText: '',
57
+ labelSlot: 'Menu Item label in slot',
58
+ size: MENU_ITEM_SIZES.SMALL,
59
+ backgroundColor: MENU_ITEM_BACKGROUND_COLORS.NEUTRAL_WEAK,
60
+ iconLeft: null,
61
+ iconRight: null,
62
+ iconRightRotation: null,
63
+ index: null,
64
+ level: 1,
65
+ label: 'Menu Item label',
66
+ isLabelUppercase: false,
67
+ state: MENU_ITEM_STATES.DEFAULT,
68
+ accessoryState: null,
69
+ isSelected: false,
70
+ isDone: false,
71
+ hasSelectedIconsColorPrimary: true,
72
+ isSelectedInteractive: false,
73
+ } as Args;
74
+
75
+ const argTypes = {
76
+ labelSlot: { control: 'text' },
77
+ size: {
78
+ control: 'select',
79
+ options: Object.values(MENU_ITEM_SIZES),
80
+ },
81
+ backgroundColor: {
82
+ control: 'select',
83
+ options: Object.values(MENU_ITEM_BACKGROUND_COLORS),
84
+ },
85
+ iconLeft: {
86
+ control: 'select',
87
+ options: [null, ...Object.keys(ICONS)],
88
+ },
89
+ iconRight: {
90
+ control: 'select',
91
+ options: [null, ...Object.keys(ICONS)],
92
+ },
93
+ iconRightRotation: {
94
+ control: 'select',
95
+ options: [null, 90, 180, 270],
96
+ },
97
+ index: {
98
+ control: { type: 'number' },
99
+ },
100
+ level: {
101
+ control: { type: 'number' },
102
+ },
103
+ label: { control: 'text' },
104
+ isLabelUppercase: {
105
+ control: 'boolean',
106
+ },
107
+ additionalText: { control: 'text' },
108
+ state: {
109
+ control: 'select',
110
+ options: Object.values(MENU_ITEM_STATES),
111
+ },
112
+ accessoryState: {
113
+ control: 'select',
114
+ options: [null, ...Object.values(MENU_ITEM_ACCESSORY_STATES)],
115
+ },
116
+ isSelected: {
117
+ control: 'boolean',
118
+ },
119
+ isDone: {
120
+ control: 'boolean',
121
+ },
122
+ hasSelectedIconsColorPrimary: {
123
+ control: 'boolean',
124
+ },
125
+ isSelectedInteractive: {
126
+ control: 'boolean',
127
+ },
128
+ } as ArgTypes;
129
+
130
+ Interactive.argTypes = argTypes;
131
+ Interactive.args = args;
132
+
133
+ Interactive.parameters = {
134
+ design: {
135
+ type: 'figma',
136
+ url: 'https://www.figma.com/file/izQdYyiBR1GQgFkaOIfIJI/LMS---DS-Components?type=design&node-id=6148-111431&t=Amd0mke9FMknuKCX-0',
137
+ },
138
+ };
139
+
140
+ const NestedMenuTemplate: StoryFn<typeof MenuItem> = (args) => ({
141
+ components: { MenuItem, DsMenu },
142
+ template: `
143
+ <menu-item label="level 1">
144
+ <template #children>
145
+ <ds-menu>
146
+ <menu-item label="level 2" />
147
+ <menu-item label="level 2">
148
+ <template #children>
149
+ <ds-menu>
150
+ <menu-item label="level 3">
151
+ <template #children>
152
+ <ds-menu>
153
+ <menu-item label="level 4">
154
+ <template #children>
155
+ <ds-menu>
156
+ <menu-item label="level 5">
157
+ <template #children>
158
+ <ds-menu>
159
+ <menu-item label="level 6" />
160
+ </ds-menu>
161
+ </template>
162
+ </menu-item>
163
+ </ds-menu>
164
+ </template>
165
+ </menu-item>
166
+ </ds-menu>
167
+ </template>
168
+ </menu-item>
169
+ </ds-menu>
170
+ </template>
171
+ </menu-item>
172
+ <menu-item label="level 2" />
173
+ </ds-menu>
174
+ </template>
175
+ </menu-item>`,
176
+ });
177
+ export const Nested = NestedMenuTemplate.bind({});