@carbon/vue 3.0.8-alpha.0 → 3.0.9

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 (37) hide show
  1. package/README.md +60 -21
  2. package/dist/carbon-vue-3.common.js +539 -69
  3. package/dist/carbon-vue-3.common.js.map +1 -1
  4. package/dist/carbon-vue-3.umd.js +539 -69
  5. package/dist/carbon-vue-3.umd.js.map +1 -1
  6. package/dist/carbon-vue-3.umd.min.js +4 -4
  7. package/dist/carbon-vue-3.umd.min.js.map +1 -1
  8. package/package.json +2 -2
  9. package/src/components/CvFileUploader/CvFileUploader.stories.mdx +24 -6
  10. package/src/components/CvFileUploader/CvFileUploader.vue +58 -19
  11. package/src/components/CvNotification/CvToastNotification.stories.js +71 -1
  12. package/src/components/CvNotification/CvToastNotification.vue +6 -4
  13. package/src/components/CvOverflowMenu/CvOverflowMenu.stories.mdx +68 -12
  14. package/src/components/CvOverflowMenu/CvOverflowMenu.vue +39 -45
  15. package/src/components/CvOverflowMenu/CvOverflowMenuItem.vue +6 -11
  16. package/src/components/CvOverflowMenu/index.js +2 -1
  17. package/src/components/CvStructuredList/CvStructuredList.stories.js +141 -0
  18. package/src/components/CvStructuredList/CvStructuredList.vue +44 -0
  19. package/src/components/CvStructuredList/CvStructuredListData.vue +19 -0
  20. package/src/components/CvStructuredList/CvStructuredListHeading.vue +11 -0
  21. package/src/components/CvStructuredList/CvStructuredListItem.vue +47 -0
  22. package/src/components/CvStructuredList/CvStructuredListItemSelectable.vue +56 -0
  23. package/src/components/CvStructuredList/CvStructuredListItemStandard.vue +11 -0
  24. package/src/components/CvStructuredList/__tests__/__snapshots__/CvStructuredList.spec.js.snap +73 -0
  25. package/src/components/CvStructuredList/__tests__/__snapshots__/CvStructuredListData.spec.js.snap +5 -0
  26. package/src/components/CvStructuredList/__tests__/__snapshots__/CvStructuredListHeading.spec.js.snap +9 -0
  27. package/src/components/CvStructuredList/__tests__/__snapshots__/CvStructuredListItem.spec.js.snap +7 -0
  28. package/src/components/CvStructuredList/index.js +12 -0
  29. package/src/components/CvTabs/CvTabs.stories.mdx +84 -3
  30. package/src/components/CvTabs/CvTabs.vue +3 -1
  31. package/src/components/CvTabs/__tests__/__snapshots__/CvTabs.spec.js.snap +24 -0
  32. package/src/components/CvTag/CvTag.stories.js +2 -1
  33. package/src/components/CvTag/CvTag.vue +10 -5
  34. package/src/components/CvTag/CvTagSkeleton.stories.js +39 -0
  35. package/src/components/CvTag/CvTagSkeleton.vue +20 -0
  36. package/src/components/CvTag/index.js +2 -1
  37. package/src/use/useRadio.js +0 -1
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@carbon/vue",
3
3
  "license": "Apache-2.0",
4
- "version": "3.0.8-alpha.0",
4
+ "version": "3.0.9",
5
5
  "description": "A collection of components for the Carbon Design System built using Vue.js",
6
6
  "packageManager": "yarn@3.2.0",
7
7
  "main": "dist/carbon-vue-3.umd.min.js",
@@ -206,5 +206,5 @@
206
206
  "url": "git+https://github.com/carbon-design-system/carbon-components-vue.git"
207
207
  },
208
208
  "sideEffects": true,
209
- "gitHead": "15a95f30d38d6b600fd1b70274502895e777e02c"
209
+ "gitHead": "746ba85d1d2060314ea9bb7f8ae9c45783572efc"
210
210
  }
@@ -48,7 +48,7 @@ const skeletonTemplate = `
48
48
  </div>
49
49
  `;
50
50
 
51
- export const args = {
51
+ export const argTypes = {
52
52
  // attributes
53
53
  multiple: {
54
54
  type: 'boolean',
@@ -61,6 +61,7 @@ export const args = {
61
61
  // props
62
62
  accept: {
63
63
  type: 'string',
64
+ defaultValue: '.jpg,.png',
64
65
  table: {
65
66
  type: { summary: 'string' },
66
67
  category: 'props',
@@ -106,6 +107,14 @@ export const args = {
106
107
  },
107
108
  description: 'Reset file list when files are added',
108
109
  },
110
+ disabled: {
111
+ type: 'boolean',
112
+ table: {
113
+ type: { summary: 'boolean' },
114
+ category: 'props',
115
+ },
116
+ description: 'Disables input',
117
+ },
109
118
  dropTargetLabel: {
110
119
  type: 'string',
111
120
  table: {
@@ -122,6 +131,14 @@ export const args = {
122
131
  },
123
132
  description: 'Helper text positioned below label',
124
133
  },
134
+ initialStateUploading: {
135
+ type: 'boolean',
136
+ table: {
137
+ type: { summary: 'boolean' },
138
+ category: 'props',
139
+ },
140
+ description: 'Set "UPLOADING" state to new files',
141
+ },
125
142
  kind: {
126
143
  type: 'string',
127
144
  control: 'select',
@@ -235,7 +252,7 @@ Migration notes:
235
252
  helperText: 'Select the files you want to upload',
236
253
  removable: true,
237
254
  }}
238
- argTypes={args}
255
+ argTypes={argTypes}
239
256
  >
240
257
  {Template.bind({})}
241
258
  </Story>
@@ -263,11 +280,12 @@ Migration notes:
263
280
  helperText: 'Select the files you want to upload',
264
281
  kind: KINDS.BUTTON,
265
282
  removable: true,
283
+ dropTargetLabel: 'Add file',
266
284
  }}
267
285
  argTypes={{
268
- ...args,
286
+ ...argTypes,
269
287
  kind: {
270
- ...args.kind,
288
+ ...argTypes.kind,
271
289
  control: 'none',
272
290
  },
273
291
  }}
@@ -299,9 +317,9 @@ Migration notes:
299
317
  removable: true,
300
318
  }}
301
319
  argTypes={{
302
- ...args,
320
+ ...argTypes,
303
321
  kind: {
304
- ...args.kind,
322
+ ...argTypes.kind,
305
323
  control: 'none',
306
324
  },
307
325
  }}
@@ -1,11 +1,28 @@
1
1
  <template>
2
2
  <cv-form-item class="cv-file-uploader">
3
- <p :class="`${carbonPrefix}--file--label`">{{ label }}</p>
4
- <p :class="`${carbonPrefix}--label-description`">{{ helperText }}</p>
3
+ <p
4
+ :class="[
5
+ `${carbonPrefix}--file--label`,
6
+ { [`${carbonPrefix}--file--label--disabled`]: disabled },
7
+ ]"
8
+ >
9
+ {{ label }}
10
+ </p>
11
+ <p
12
+ :class="[
13
+ `${carbonPrefix}--label-description`,
14
+ { [`${carbonPrefix}--label-description--disabled`]: disabled },
15
+ ]"
16
+ >
17
+ {{ helperText }}
18
+ </p>
5
19
  <div v-if="kind === 'button'" :class="`${carbonPrefix}--file`" data-file>
6
20
  <label
7
21
  :for="cvId"
8
- :class="buttonClasses"
22
+ :class="[
23
+ buttonClasses,
24
+ { [`${carbonPrefix}--btn--disabled`]: disabled },
25
+ ]"
9
26
  tabindex="0"
10
27
  @keydown.enter.prevent="onKeyHit"
11
28
  @keydown.space.prevent="onKeyHit"
@@ -17,6 +34,7 @@
17
34
  ref="fileInput"
18
35
  :class="`${carbonPrefix}--file-input`"
19
36
  :accept="accept"
37
+ :disabled="disabled"
20
38
  type="file"
21
39
  v-bind="$attrs"
22
40
  data-file-uploader
@@ -34,8 +52,10 @@
34
52
  `${carbonPrefix}--file-browse-btn`,
35
53
  `${carbonPrefix}--file__drop-container`,
36
54
  {
37
- [`${carbonPrefix}--file__drop-container--drag-over`]: allowDrop,
55
+ [`${carbonPrefix}--file__drop-container--drag-over`]:
56
+ allowDrop && !disabled,
38
57
  },
58
+ { [`${carbonPrefix}--file-browse-btn--disabled`]: disabled },
39
59
  ]"
40
60
  @dragover="onDragEvent"
41
61
  @dragleave="onDragEvent"
@@ -50,6 +70,7 @@
50
70
  ref="fileInput"
51
71
  :class="`${carbonPrefix}--file-input`"
52
72
  :accept="accept"
73
+ :disabled="disabled"
53
74
  type="file"
54
75
  v-bind="$attrs"
55
76
  tabindex="-1"
@@ -107,8 +128,10 @@ const props = defineProps({
107
128
  },
108
129
  buttonSize: commonCvButtonProps.size,
109
130
  clearOnReselect: Boolean,
131
+ disabled: Boolean,
110
132
  dropTargetLabel: String,
111
133
  helperText: String,
134
+ initialStateUploading: Boolean,
112
135
  kind: {
113
136
  type: String,
114
137
  default: KINDS.DRAG_TARGET,
@@ -178,7 +201,7 @@ function addFiles(files) {
178
201
  const newFile = createInternalFile(internalFile?.file || file);
179
202
 
180
203
  if (internalFile) {
181
- internalFile.state = newFile.initialState;
204
+ internalFile.state = newFile.state;
182
205
  internalFile.invalidMessageTitle = newFile.invalidMessageTitle;
183
206
  internalFile.invalidMessage = newFile.invalidMessage;
184
207
  } else {
@@ -216,6 +239,11 @@ function onChange(ev) {
216
239
  }
217
240
 
218
241
  function onDragEvent(evt) {
242
+ if (props.disabled) {
243
+ evt.preventDefault();
244
+ return;
245
+ }
246
+
219
247
  if (Array.prototype.indexOf.call(evt.dataTransfer.types, 'Files') === -1) {
220
248
  return;
221
249
  }
@@ -249,7 +277,7 @@ function onDragEvent(evt) {
249
277
 
250
278
  function onItemRemove(index) {
251
279
  internalFiles.value.splice(index, 1);
252
- emit('update:modelValue', this.internalFiles);
280
+ emit('update:modelValue', internalFiles.value);
253
281
  }
254
282
 
255
283
  function onKeyHit() {
@@ -262,20 +290,31 @@ onMounted(() => {
262
290
  });
263
291
 
264
292
  // exposed methods
293
+ function clear() {
294
+ internalFiles.value = [];
295
+ emit('update:modelValue', internalFiles.value);
296
+ }
297
+
298
+ function remove(index) {
299
+ onItemRemove(index);
300
+ }
301
+
302
+ function setInvalidMessage(index, message) {
303
+ internalFiles.value[index].invalidMessage = message;
304
+ }
305
+
306
+ function setState(index, state) {
307
+ if ([STATES.COMPLETE, STATES.UPLOADING, STATES.NONE].includes(state)) {
308
+ internalFiles.value[index].state = state;
309
+ }
310
+ }
311
+
312
+ // exposing methods
265
313
  defineExpose({
266
- setState(index, state) {
267
- if ([STATES.COMPLETE, STATES.UPLOADING, STATES.NONE].includes(state)) {
268
- internalFiles.value[index].state = state;
269
- }
270
- },
271
- clear() {
272
- internalFiles.value = [];
273
- emit('update:modelValue', internalFiles);
274
- },
275
- setInvalidMessage(index, message) {
276
- internalFiles.value[index].invalidMessage = message;
277
- },
278
- remove: onItemRemove,
314
+ clear,
315
+ remove,
316
+ setInvalidMessage,
317
+ setState,
279
318
  });
280
319
  </script>
281
320
 
@@ -58,10 +58,56 @@ export default {
58
58
  lowContrast: {
59
59
  control: { type: 'boolean' },
60
60
  },
61
+ // slots
62
+ default: {
63
+ table: {
64
+ type: { summary: 'string | html | Component' },
65
+ category: 'slots',
66
+ },
67
+ description: 'Slot for additional custom content.',
68
+ },
69
+ 'title ': {
70
+ table: {
71
+ type: { summary: 'string | html | Component' },
72
+ category: 'slots',
73
+ },
74
+ description: 'Title slot for more custom content.',
75
+ },
76
+ subtitle: {
77
+ table: {
78
+ type: { summary: 'string | html | Component' },
79
+ category: 'slots',
80
+ },
81
+ description: 'Subtitle slot for more custom content.',
82
+ },
83
+ 'caption ': {
84
+ table: {
85
+ type: { summary: 'string | html | Component' },
86
+ category: 'slots',
87
+ },
88
+ description: 'Caption slot for more custom content.',
89
+ },
61
90
  },
62
91
  };
63
92
 
64
- const template = `<cv-toast-notification v-bind="args" @close="onClose" />`;
93
+ const template = `
94
+ <cv-toast-notification v-bind="args" @close="onClose" >
95
+ <template v-if="args.titleSlot" #title>
96
+ <strong style="color: orange; font-size: 1.25rem;">Custom</strong> <span style="color: yellow;">title</span>
97
+ </template>
98
+
99
+ <template v-if="args.subtitleSlot" #subtitle>
100
+ Some <strong style="color: orange; font-size: 1.25rem;">custom</strong> <span style="color: yellow;">subtitle</span>
101
+ </template>
102
+
103
+ <template v-if="args.captionSlot" #caption>
104
+ Some <span style="color: green;">custom</span> <strong style="color: orange; font-size: 0.75rem;">caption</strong>
105
+ </template>
106
+
107
+ <template v-if="args.defaultSlot">
108
+ Default slot content.
109
+ </template>
110
+ </cv-toast-notification>`;
65
111
  const Template = args => {
66
112
  return {
67
113
  components: { CvToastNotification },
@@ -106,3 +152,27 @@ export const Error = Template.bind({});
106
152
  Error.args = {
107
153
  kind: CvNotificationConsts.notificationKinds[5],
108
154
  };
155
+
156
+ export const SlotDefault = Template.bind({});
157
+ SlotDefault.args = {
158
+ kind: CvNotificationConsts.notificationKinds[4],
159
+ defaultSlot: true,
160
+ };
161
+
162
+ export const SlotTitle = Template.bind({});
163
+ SlotTitle.args = {
164
+ kind: CvNotificationConsts.notificationKinds[0],
165
+ titleSlot: true,
166
+ };
167
+
168
+ export const SlotSubtitle = Template.bind({});
169
+ SlotSubtitle.args = {
170
+ kind: CvNotificationConsts.notificationKinds[3],
171
+ subtitleSlot: true,
172
+ };
173
+
174
+ export const SlotCaption = Template.bind({});
175
+ SlotCaption.args = {
176
+ kind: CvNotificationConsts.notificationKinds[1],
177
+ captionSlot: true,
178
+ };
@@ -13,12 +13,14 @@
13
13
  :class="`${carbonPrefix}--toast-notification__icon`"
14
14
  />
15
15
  <div :class="`${carbonPrefix}--toast-notification__details`">
16
- <h3 :class="`${carbonPrefix}--toast-notification__title`">{{ title }}</h3>
16
+ <h3 :class="`${carbonPrefix}--toast-notification__title`">
17
+ <slot name="title">{{ title }}</slot>
18
+ </h3>
17
19
  <div :class="`${carbonPrefix}--toast-notification__subtitle`">
18
- {{ subTitle }}
20
+ <slot name="subtitle">{{ subTitle }}</slot>
19
21
  </div>
20
22
  <div :class="`${carbonPrefix}--toast-notification__caption`">
21
- {{ caption }}
23
+ <slot name="caption">{{ caption }}</slot>
22
24
  </div>
23
25
  <slot />
24
26
  </div>
@@ -28,7 +30,7 @@
28
30
  :class="`${carbonPrefix}--toast-notification__close-button`"
29
31
  @click="$emit('close')"
30
32
  >
31
- <close20 :class="`${carbonPrefix}--inline-notification__close-icon`" />
33
+ <close20 :class="`${carbonPrefix}--toast-notification__close-icon`" />
32
34
  </button>
33
35
  </div>
34
36
  </template>
@@ -25,18 +25,20 @@ export const Template = args => ({
25
25
  template: args.template,
26
26
  });
27
27
  const defaultTemplate = `
28
- <cv-overflow-menu
29
- :flip-menu="flipMenu"
30
- :up="up"
31
- :offset="offset"
32
- :label="label"
33
- :tip-position="tipPosition"
34
- :tip-alignment="tipAlignment"
35
- @change=onChange>
36
- <cv-overflow-menu-item value="item 1" primary-focus>list item 1</cv-overflow-menu-item>
37
- <cv-overflow-menu-item value="item 2" disabled>list item 2</cv-overflow-menu-item>
38
- <cv-overflow-menu-item value="item 3" danger>list item 3</cv-overflow-menu-item>
39
- </cv-overflow-menu>
28
+ <div style="padding: 100px;">
29
+ <cv-overflow-menu
30
+ :flip-menu="flipMenu"
31
+ :up="up"
32
+ :offset="offset"
33
+ :label="label"
34
+ :tip-position="tipPosition"
35
+ :tip-alignment="tipAlignment"
36
+ @change=onChange>
37
+ <cv-overflow-menu-item value="item 1" primary-focus>list item 1</cv-overflow-menu-item>
38
+ <cv-overflow-menu-item value="item 2" disabled>list item 2</cv-overflow-menu-item>
39
+ <cv-overflow-menu-item value="item 3" danger>list item 3</cv-overflow-menu-item>
40
+ </cv-overflow-menu>
41
+ </div>
40
42
  `;
41
43
  const slotsTemplate = `
42
44
  <cv-overflow-menu
@@ -117,3 +119,57 @@ Use slots for more control over the display.
117
119
  {Template.bind({})}
118
120
  </Story>
119
121
  </Canvas>
122
+
123
+ <Canvas>
124
+ <Story
125
+ name="Flipped"
126
+ parameters={{
127
+ controls: {
128
+ exclude: ['default', 'template', 'trigger', 'change'],
129
+ },
130
+ docs: { source: { code: defaultTemplate } },
131
+ }}
132
+ args={{
133
+ template: defaultTemplate,
134
+ label: 'Overflow menu',
135
+ flipMenu: true,
136
+ up: undefined,
137
+ offset: undefined,
138
+ tipPosition: undefined,
139
+ tipAlignment: undefined,
140
+ }}
141
+ argTypes={{
142
+ tipPosition: { control: 'select', default: 'right', options: ['top', 'left', 'bottom', 'right'] },
143
+ tipAlignment: { control: 'select', default: 'center', options: ['start', 'center', 'end'] },
144
+ }}
145
+ >
146
+ {Template.bind({})}
147
+ </Story>
148
+ </Canvas>
149
+
150
+ <Canvas>
151
+ <Story
152
+ name="Up"
153
+ parameters={{
154
+ controls: {
155
+ exclude: ['default', 'template', 'trigger', 'change'],
156
+ },
157
+ docs: { source: { code: defaultTemplate } },
158
+ }}
159
+ args={{
160
+ template: defaultTemplate,
161
+ label: 'Overflow menu',
162
+ flipMenu: undefined,
163
+ up: true,
164
+ offset: undefined,
165
+ tipPosition: undefined,
166
+ tipAlignment: undefined,
167
+ }}
168
+ argTypes={{
169
+ tipPosition: { control: 'select', default: 'right', options: ['top', 'left', 'bottom', 'right'] },
170
+ tipAlignment: { control: 'select', default: 'center', options: ['start', 'center', 'end'] },
171
+ }}
172
+ >
173
+ {Template.bind({})}
174
+ </Story>
175
+ </Canvas>
@@ -38,40 +38,42 @@
38
38
  />
39
39
  </slot>
40
40
  </button>
41
- <div
42
- :class="[
43
- `${carbonPrefix}--overflow-menu-options`,
44
- {
45
- [`${carbonPrefix}--overflow-menu--flip`]: flipMenu,
46
- [`${carbonPrefix}--overflow-menu-options--open`]: open,
47
- },
48
- ]"
49
- tabindex="-1"
50
- ref="popup"
51
- :aria-labelledby="`${uid}-trigger`"
52
- :id="`${uid}-menu`"
53
- :style="{ left: left + 'px', top: top + 'px' }"
54
- @focusout="checkFocusOut"
55
- @mousedown.prevent="preventFocusOut"
56
- >
41
+ <Teleport to="body">
57
42
  <div
58
- class="cv-overflow-menu__before-content"
59
- ref="beforeContent"
60
- tabindex="0"
61
- style="position: absolute; height: 1px; width: 1px; left: -9999px"
62
- @focus="focusBeforeContent"
63
- />
64
- <ul :class="`${carbonPrefix}--overflow-menu-options__content`">
65
- <slot></slot>
66
- </ul>
67
- <div
68
- class="cv-overflow-menu__after-content"
69
- ref="afterContent"
70
- tabindex="0"
71
- style="position: absolute; height: 1px; width: 1px; left: -9999px"
72
- @focus="focusAfterContent"
73
- />
74
- </div>
43
+ :class="[
44
+ `${carbonPrefix}--overflow-menu-options`,
45
+ {
46
+ [`${carbonPrefix}--overflow-menu--flip`]: flipMenu,
47
+ [`${carbonPrefix}--overflow-menu-options--open`]: open,
48
+ },
49
+ ]"
50
+ tabindex="-1"
51
+ ref="popup"
52
+ :aria-labelledby="`${uid}-trigger`"
53
+ :id="`${uid}-menu`"
54
+ :style="{ left: left + 'px', top: top + 'px' }"
55
+ @focusout="checkFocusOut"
56
+ @mousedown.prevent="preventFocusOut"
57
+ >
58
+ <div
59
+ class="cv-overflow-menu__before-content"
60
+ ref="beforeContent"
61
+ tabindex="0"
62
+ style="position: absolute; height: 1px; width: 1px; left: -9999px"
63
+ @focus="focusBeforeContent"
64
+ />
65
+ <ul :class="`${carbonPrefix}--overflow-menu-options__content`">
66
+ <slot></slot>
67
+ </ul>
68
+ <div
69
+ class="cv-overflow-menu__after-content"
70
+ ref="afterContent"
71
+ tabindex="0"
72
+ style="position: absolute; height: 1px; width: 1px; left: -9999px"
73
+ @focus="focusAfterContent"
74
+ />
75
+ </div>
76
+ </Teleport>
75
77
  </div>
76
78
  </template>
77
79
 
@@ -79,8 +81,7 @@
79
81
  import { carbonPrefix } from '../../global/settings';
80
82
  import { props as propsCvId, useCvId } from '../../use/cvId';
81
83
  import OverflowMenuVertical16 from '@carbon/icons-vue/es/overflow-menu--vertical/16';
82
- import { computed, nextTick, onBeforeMount, onUnmounted, ref } from 'vue';
83
- import { getBus, removeBus } from '../../global/component-utils/event-bus';
84
+ import { computed, nextTick, provide, ref } from 'vue';
84
85
  const props = defineProps({
85
86
  /**
86
87
  * assistive text shown as a tooltip
@@ -135,15 +136,8 @@ const offsetTop = computed(() => {
135
136
  return props.offset ? props.offset.top : 0;
136
137
  });
137
138
 
138
- let bus = undefined;
139
- onBeforeMount(() => {
140
- bus = getBus(uid.value);
141
- bus.on('cv:close', doClose);
142
- bus.on('cv:click', menuItemClick);
143
- });
144
- onUnmounted(() => {
145
- removeBus(uid.value);
146
- });
139
+ provide('cv:close', doClose);
140
+ provide('cv:click', menuItemClick);
147
141
 
148
142
  const trigger = ref(null);
149
143
  const popup = ref(null);
@@ -216,7 +210,7 @@ async function positionMenu() {
216
210
  popup.value.offsetHeight +
217
211
  pixelsScrolledY;
218
212
  } else {
219
- top.value = menuPosition.left + offsetLeft.value + pixelsScrolledX;
213
+ top.value = menuPosition.bottom + offsetTop.value + pixelsScrolledY;
220
214
  }
221
215
  });
222
216
  }
@@ -26,27 +26,22 @@
26
26
 
27
27
  <script setup>
28
28
  import { carbonPrefix } from '../../global/settings';
29
- import { onMounted, ref, useAttrs } from 'vue';
30
- import { getBus } from '../../global/component-utils/event-bus';
29
+ import { ref, useAttrs, inject } from 'vue';
31
30
 
32
31
  defineProps({
33
32
  primaryFocus: Boolean,
34
33
  disabled: Boolean,
35
34
  danger: Boolean,
36
35
  });
37
- let bus = undefined;
38
36
  const el = ref(null);
39
- onMounted(() => {
40
- const pe = el.value.closest('[data-overflow-menu]');
41
- const parent = pe?.getAttribute('id');
42
- if (parent) bus = getBus(parent);
43
- else console.warn('overflow menu not found');
44
- });
37
+ const emitClick = inject('cv:click');
38
+ const emitClose = inject('cv:close');
39
+
45
40
  const attrs = useAttrs();
46
41
  function onClick() {
47
- bus?.emit('cv:click', attrs.value);
42
+ emitClick(attrs.value);
48
43
  }
49
44
  function onEsc() {
50
- bus?.emit('cv:close');
45
+ emitClose();
51
46
  }
52
47
  </script>
@@ -1,3 +1,4 @@
1
1
  import CvOverflowMenu from './CvOverflowMenu.vue';
2
- export { CvOverflowMenu };
2
+ import CvOverflowMenuItem from './CvOverflowMenuItem.vue';
3
+ export { CvOverflowMenu, CvOverflowMenuItem };
3
4
  export default CvOverflowMenu;