@carbon/vue 3.0.7-alpha.0 → 3.0.9-alpha.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.
- package/README.md +7 -0
- package/dist/carbon-vue-3.common.js +3850 -217
- package/dist/carbon-vue-3.common.js.map +1 -1
- package/dist/carbon-vue-3.umd.js +3850 -217
- package/dist/carbon-vue-3.umd.js.map +1 -1
- package/dist/carbon-vue-3.umd.min.js +4 -4
- package/dist/carbon-vue-3.umd.min.js.map +1 -1
- package/package.json +7 -4
- package/src/components/CvCheckbox/CvCheckbox.stories.js +18 -7
- package/src/components/CvCheckbox/CvCheckbox.vue +19 -3
- package/src/components/CvCheckbox/CvCheckboxSkeleton.vue +16 -0
- package/src/components/CvCheckbox/__tests__/__snapshots__/CvCheckboxSkeleton.spec.js.snap +3 -0
- package/src/components/CvCheckbox/index.js +2 -1
- package/src/components/CvDropdown/CvDropdown.vue +0 -2
- package/src/components/CvFileUploader/CvFileUploader.stories.mdx +333 -0
- package/src/components/CvFileUploader/CvFileUploader.vue +286 -0
- package/src/components/CvFileUploader/CvFileUploaderItem.vue +92 -0
- package/src/components/CvFileUploader/CvFileUploaderSkeleton.vue +16 -0
- package/src/components/CvFileUploader/const.js +10 -0
- package/src/components/CvFileUploader/index.js +5 -0
- package/src/components/CvMultiSelect/CvMultiSelect.stories.mdx +1 -1
- package/src/components/CvNotification/CvToastNotification.stories.js +71 -1
- package/src/components/CvNotification/CvToastNotification.vue +6 -4
- package/src/components/CvOverflowMenu/CvOverflowMenu.stories.mdx +68 -12
- package/src/components/CvOverflowMenu/CvOverflowMenu.vue +39 -45
- package/src/components/CvOverflowMenu/CvOverflowMenuItem.vue +6 -11
- package/src/components/CvOverflowMenu/index.js +2 -1
- package/src/components/CvProgress/CvProgress.stories.mdx +202 -0
- package/src/components/CvProgress/CvProgress.vue +78 -0
- package/src/components/CvProgress/CvProgressStep.vue +124 -0
- package/src/components/CvProgress/index.js +4 -0
- package/src/components/CvRadioButton/CvRadioButton.stories.js +166 -0
- package/src/components/CvRadioButton/CvRadioButton.vue +57 -0
- package/src/components/CvRadioButton/CvRadioGroup.vue +27 -0
- package/src/components/CvRadioButton/__tests__/__snapshots__/CvRadioButton.spec.js.snap +27 -0
- package/src/components/CvRadioButton/index.js +6 -0
- package/src/components/CvSearch/CvSearch.stories.mdx +168 -0
- package/src/components/CvSearch/CvSearch.vue +250 -0
- package/src/components/CvSearch/index.js +3 -0
- package/src/components/CvSelect/CvSelect.vue +27 -6
- package/src/components/CvSlider/CvSlider.stories.js +166 -0
- package/src/components/CvSlider/CvSlider.vue +324 -0
- package/src/components/CvSlider/CvSliderSkeleton.stories.js +26 -0
- package/src/components/CvSlider/CvSliderSkeleton.vue +18 -0
- package/src/components/CvSlider/__tests__/__snapshots__/CvSlider.spec.js.snap +13 -0
- package/src/components/CvSlider/__tests__/__snapshots__/CvSliderSkeleton.spec.js.snap +13 -0
- package/src/components/CvSlider/index.js +5 -0
- package/src/components/CvSlider/sbSliderPrefix.js +2 -0
- package/src/components/CvStructuredList/CvStructuredList.stories.js +141 -0
- package/src/components/CvStructuredList/CvStructuredList.vue +44 -0
- package/src/components/CvStructuredList/CvStructuredListData.vue +19 -0
- package/src/components/CvStructuredList/CvStructuredListHeading.vue +11 -0
- package/src/components/CvStructuredList/CvStructuredListItem.vue +47 -0
- package/src/components/CvStructuredList/CvStructuredListItemSelectable.vue +56 -0
- package/src/components/CvStructuredList/CvStructuredListItemStandard.vue +11 -0
- package/src/components/CvStructuredList/__tests__/__snapshots__/CvStructuredList.spec.js.snap +73 -0
- package/src/components/CvStructuredList/__tests__/__snapshots__/CvStructuredListData.spec.js.snap +5 -0
- package/src/components/CvStructuredList/__tests__/__snapshots__/CvStructuredListHeading.spec.js.snap +9 -0
- package/src/components/CvStructuredList/__tests__/__snapshots__/CvStructuredListItem.spec.js.snap +7 -0
- package/src/components/CvStructuredList/index.js +12 -0
- package/src/components/CvTextArea/CvTextArea.stories.js +2 -2
- package/src/components/CvTextArea/CvTextAreaSkeleton.stories.js +29 -0
- package/src/components/CvTextArea/CvTextAreaSkeleton.vue +10 -0
- package/src/components/CvTextArea/StorybookGroupConst.js +1 -0
- package/src/components/CvTextArea/__tests__/__snapshots__/CvTextAreaSkeleton.spec.js.snap +7 -0
- package/src/components/CvTextArea/index.js +2 -1
- package/src/components/CvTimePicker/CvTimePicker.stories.mdx +325 -0
- package/src/components/CvTimePicker/CvTimePicker.vue +217 -0
- package/src/components/CvTimePicker/index.js +21 -0
- package/src/components/CvToggle/CvToggle-Skeleton.vue +27 -12
- package/src/components/CvToggle/CvToggle.stories.js +20 -3
- package/src/components/CvToggle/CvToggle.vue +22 -5
- package/src/components/CvToggle/__tests__/__snapshots__/CvToggle.spec.js.snap +3 -3
- package/src/components/CvTooltip/CvDefinitionTooltip.stories.js +80 -0
- package/src/components/CvTooltip/CvDefinitionTooltip.vue +61 -0
- package/src/components/CvTooltip/CvInteractiveTooltip.stories.js +90 -0
- package/src/components/CvTooltip/CvInteractiveTooltip.vue +267 -0
- package/src/components/CvTooltip/CvTooltip.stories.js +128 -0
- package/src/components/CvTooltip/CvTooltip.vue +44 -0
- package/src/components/CvTooltip/__tests__/__snapshots__/CvTooltip.spec.js.snap +525 -0
- package/src/components/CvTooltip/consts.js +15 -0
- package/src/components/CvTooltip/index.js +6 -0
- package/src/components/CvTooltip/sbTooltipPrefix.js +2 -0
- package/src/components/CvUIShell/CvSideNav.vue +10 -1
- package/src/components/CvUIShell/CvUIShell.stories.mdx +116 -50
- package/src/index.d.ts +6 -0
- package/src/index.js +11 -0
- package/src/use/cvCheck.js +3 -0
- package/src/use/index.js +2 -0
- package/src/use/useMethods.js +18 -0
- package/src/use/useRadio.js +24 -0
|
@@ -38,40 +38,42 @@
|
|
|
38
38
|
/>
|
|
39
39
|
</slot>
|
|
40
40
|
</button>
|
|
41
|
-
<
|
|
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="
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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,
|
|
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
|
-
|
|
139
|
-
|
|
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.
|
|
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 {
|
|
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
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
-
|
|
42
|
+
emitClick(attrs.value);
|
|
48
43
|
}
|
|
49
44
|
function onEsc() {
|
|
50
|
-
|
|
45
|
+
emitClose();
|
|
51
46
|
}
|
|
52
47
|
</script>
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { Canvas, Meta, Story } from '@storybook/addon-docs';
|
|
2
|
+
import { CvProgress, CvProgressStep } from '.';
|
|
3
|
+
import { Time20 as TimeIcon } from '@carbon/icons-vue';
|
|
4
|
+
// noinspection ES6PreferShortImport
|
|
5
|
+
import { sbCompPrefix } from '../../global/storybook-utils';
|
|
6
|
+
import { action } from '@storybook/addon-actions';
|
|
7
|
+
|
|
8
|
+
<Meta title={`${sbCompPrefix}/CvProgress`} component={CvProgress} />
|
|
9
|
+
|
|
10
|
+
export const Template = args => ({
|
|
11
|
+
// Components used in your story `template` are defined in the `components` object
|
|
12
|
+
components: {
|
|
13
|
+
CvProgress,
|
|
14
|
+
CvProgressStep,
|
|
15
|
+
TimeIcon,
|
|
16
|
+
},
|
|
17
|
+
// The story's `args` need to be mapped into the template through the `setup()` method
|
|
18
|
+
setup() {
|
|
19
|
+
return {
|
|
20
|
+
initialStep: args.initialStep,
|
|
21
|
+
steps: args.steps,
|
|
22
|
+
vertical: args.vertical,
|
|
23
|
+
spaceEqually: args.spaceEqually,
|
|
24
|
+
step1: args.step1,
|
|
25
|
+
step2: args.step2,
|
|
26
|
+
step3: args.step3,
|
|
27
|
+
step4: args.step4,
|
|
28
|
+
step5: args.step5,
|
|
29
|
+
completeIds: args.completeIds,
|
|
30
|
+
invalidIds: args.invalidIds,
|
|
31
|
+
disabledIds: args.disabledIds,
|
|
32
|
+
onStepClicked: action('step-clicked'),
|
|
33
|
+
};
|
|
34
|
+
},
|
|
35
|
+
// And then the `args` are bound to your component with `v-bind="args"`
|
|
36
|
+
template: args.template,
|
|
37
|
+
});
|
|
38
|
+
const defaultTemplate = `
|
|
39
|
+
<cv-progress
|
|
40
|
+
:initial-step="initialStep"
|
|
41
|
+
:steps="steps"
|
|
42
|
+
:vertical="vertical"
|
|
43
|
+
:space-equally="spaceEqually"
|
|
44
|
+
@step-clicked="onStepClicked">
|
|
45
|
+
</cv-progress>
|
|
46
|
+
`;
|
|
47
|
+
const slotTemplate = `
|
|
48
|
+
<cv-progress
|
|
49
|
+
:initial-step="initialStep"
|
|
50
|
+
:vertical="vertical"
|
|
51
|
+
:spaceEqually="spaceEqually"
|
|
52
|
+
>
|
|
53
|
+
<cv-progress-step
|
|
54
|
+
id="step-1"
|
|
55
|
+
:label="step1"
|
|
56
|
+
:complete="completeIds.includes('step-1')"
|
|
57
|
+
:invalid="invalidIds.includes('step-1')"
|
|
58
|
+
:disabled="disabledIds.includes('step-1')"
|
|
59
|
+
additionalInfo="with Meg Murry"
|
|
60
|
+
description="time icon description"
|
|
61
|
+
@step-clicked="onStepClicked"
|
|
62
|
+
>
|
|
63
|
+
<template v-slot:step-icon>
|
|
64
|
+
<time-icon :class="[{['bx--progress__warning']:invalidIds.includes('step-1')}]"/>
|
|
65
|
+
</template>
|
|
66
|
+
</cv-progress-step>
|
|
67
|
+
<cv-progress-step
|
|
68
|
+
id="step-2"
|
|
69
|
+
:label="step2"
|
|
70
|
+
:complete="completeIds.includes('step-2')"
|
|
71
|
+
:invalid="invalidIds.includes('step-2')"
|
|
72
|
+
:disabled="disabledIds.includes('step-2')"
|
|
73
|
+
additionalInfo="save Charles Wallace"
|
|
74
|
+
@step-clicked="onStepClicked"
|
|
75
|
+
>
|
|
76
|
+
</cv-progress-step>
|
|
77
|
+
<cv-progress-step
|
|
78
|
+
id="step-3"
|
|
79
|
+
:label="step3"
|
|
80
|
+
:complete="completeIds.includes('step-3')"
|
|
81
|
+
:invalid="invalidIds.includes('step-3')"
|
|
82
|
+
:disabled="disabledIds.includes('step-3')"
|
|
83
|
+
additionalInfo="save the world"
|
|
84
|
+
@step-clicked="onStepClicked"
|
|
85
|
+
>
|
|
86
|
+
</cv-progress-step>
|
|
87
|
+
<cv-progress-step
|
|
88
|
+
id="step-4"
|
|
89
|
+
:label="step4"
|
|
90
|
+
:complete="completeIds.includes('step-4')"
|
|
91
|
+
:invalid="invalidIds.includes('step-4')"
|
|
92
|
+
:disabled="disabledIds.includes('step-4')"
|
|
93
|
+
additionalInfo="Twins Dennys and Sandy"
|
|
94
|
+
@step-clicked="onStepClicked"
|
|
95
|
+
>
|
|
96
|
+
</cv-progress-step>
|
|
97
|
+
<cv-progress-step
|
|
98
|
+
id="step-5"
|
|
99
|
+
:label="step5"
|
|
100
|
+
:complete="completeIds.includes('step-5')"
|
|
101
|
+
:invalid="invalidIds.includes('step-5')"
|
|
102
|
+
:disabled="disabledIds.includes('step-5')"
|
|
103
|
+
additionalInfo="with Polyhymnia O'Keefe"
|
|
104
|
+
@step-clicked="onStepClicked"
|
|
105
|
+
>
|
|
106
|
+
</cv-progress-step>
|
|
107
|
+
</cv-progress>
|
|
108
|
+
`;
|
|
109
|
+
|
|
110
|
+
# CvProgress
|
|
111
|
+
|
|
112
|
+
**Migration notes:**
|
|
113
|
+
|
|
114
|
+
- The "current" icon is updated to match Carbon React
|
|
115
|
+
- Added the property `spaceEqually` to match Carbon React
|
|
116
|
+
- The property name `initialStep` is misleading. It is treated as the Current progress (currentIndex).
|
|
117
|
+
- To override the default icons, provide an icon in the `step-icon` slot in the `cv-progress-step`
|
|
118
|
+
|
|
119
|
+
<Canvas>
|
|
120
|
+
<Story
|
|
121
|
+
name="Default"
|
|
122
|
+
parameters={{
|
|
123
|
+
controls: {
|
|
124
|
+
exclude: ['default', 'template', 'step-clicked'],
|
|
125
|
+
},
|
|
126
|
+
docs: { source: { code: defaultTemplate } },
|
|
127
|
+
}}
|
|
128
|
+
args={{
|
|
129
|
+
template: defaultTemplate,
|
|
130
|
+
steps: [
|
|
131
|
+
'Planet Uriel',
|
|
132
|
+
'The Happy Medium',
|
|
133
|
+
'The Black Thing',
|
|
134
|
+
'Rescue Dr. Murry',
|
|
135
|
+
'Rescue Charles Wallace',
|
|
136
|
+
'Back to Earth',
|
|
137
|
+
],
|
|
138
|
+
}}
|
|
139
|
+
argTypes={{
|
|
140
|
+
initialStep: {
|
|
141
|
+
control: {
|
|
142
|
+
type: 'number',
|
|
143
|
+
min: -1,
|
|
144
|
+
max: 6,
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
}}
|
|
148
|
+
>
|
|
149
|
+
{Template.bind({})}
|
|
150
|
+
</Story>
|
|
151
|
+
</Canvas>
|
|
152
|
+
|
|
153
|
+
# Slotted
|
|
154
|
+
|
|
155
|
+
Use `cv-progress-step` for more control over the display.
|
|
156
|
+
|
|
157
|
+
<Canvas>
|
|
158
|
+
<Story
|
|
159
|
+
name="slotted"
|
|
160
|
+
parameters={{
|
|
161
|
+
controls: {
|
|
162
|
+
exclude: ['default', 'template', 'step-clicked', 'steps'],
|
|
163
|
+
},
|
|
164
|
+
docs: { source: { code: slotTemplate } },
|
|
165
|
+
}}
|
|
166
|
+
args={{
|
|
167
|
+
template: slotTemplate,
|
|
168
|
+
step1: 'A Wrinkle in Time',
|
|
169
|
+
step2: 'A Wind in the Door',
|
|
170
|
+
step3: 'A Swiftly Tilting Planet',
|
|
171
|
+
step4: 'Many Waters',
|
|
172
|
+
step5: 'An Acceptable Time',
|
|
173
|
+
vertical: true,
|
|
174
|
+
completeIds: [],
|
|
175
|
+
invalidIds: [],
|
|
176
|
+
disabledIds: [],
|
|
177
|
+
}}
|
|
178
|
+
argTypes={{
|
|
179
|
+
initialStep: {
|
|
180
|
+
control: {
|
|
181
|
+
type: 'number',
|
|
182
|
+
min: -1,
|
|
183
|
+
max: 6,
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
disabledIds: {
|
|
187
|
+
control: 'multi-select',
|
|
188
|
+
options: ['step-1', 'step-2', 'step-3', 'step-4', 'step-5'],
|
|
189
|
+
},
|
|
190
|
+
completeIds: {
|
|
191
|
+
control: 'multi-select',
|
|
192
|
+
options: ['step-1', 'step-2', 'step-3', 'step-4', 'step-5'],
|
|
193
|
+
},
|
|
194
|
+
invalidIds: {
|
|
195
|
+
control: 'multi-select',
|
|
196
|
+
options: ['step-1', 'step-2', 'step-3', 'step-4', 'step-5'],
|
|
197
|
+
},
|
|
198
|
+
}}
|
|
199
|
+
>
|
|
200
|
+
{Template.bind({})}
|
|
201
|
+
</Story>
|
|
202
|
+
</Canvas>
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<ul
|
|
3
|
+
data-progress
|
|
4
|
+
data-progress-current
|
|
5
|
+
:class="[
|
|
6
|
+
`cv-progress ${carbonPrefix}--progress`,
|
|
7
|
+
{ [`${carbonPrefix}--progress--space-equal`]: isEqual },
|
|
8
|
+
{ [`${carbonPrefix}--progress--vertical`]: vertical },
|
|
9
|
+
]"
|
|
10
|
+
>
|
|
11
|
+
<slot>
|
|
12
|
+
<cv-progress-step
|
|
13
|
+
v-for="(step, index) in steps"
|
|
14
|
+
:key="`step:${index}:${initialStep > index}`"
|
|
15
|
+
:label="step"
|
|
16
|
+
:complete="initialStep > index"
|
|
17
|
+
@step-clicked="emit('step-clicked', { ...$event, index })"
|
|
18
|
+
/>
|
|
19
|
+
</slot>
|
|
20
|
+
</ul>
|
|
21
|
+
</template>
|
|
22
|
+
|
|
23
|
+
<script setup>
|
|
24
|
+
// noinspection ES6PreferShortImport
|
|
25
|
+
import { carbonPrefix } from '../../global/settings';
|
|
26
|
+
import CvProgressStep from './CvProgressStep.vue';
|
|
27
|
+
import { computed, onMounted, provide, ref, watch } from 'vue';
|
|
28
|
+
|
|
29
|
+
const props = defineProps({
|
|
30
|
+
/**
|
|
31
|
+
* Optionally specify the current step array index
|
|
32
|
+
*/
|
|
33
|
+
initialStep: { type: Number, default: 0 },
|
|
34
|
+
/**
|
|
35
|
+
* An array of labels for the steps. Use `cv-progress-step` components for more control over the step logic.
|
|
36
|
+
*/
|
|
37
|
+
steps: Array,
|
|
38
|
+
/**
|
|
39
|
+
* Determines whether the ProgressIndicator should be rendered vertically.
|
|
40
|
+
*/
|
|
41
|
+
vertical: { type: Boolean, default: false },
|
|
42
|
+
/**
|
|
43
|
+
* Specify whether the progress steps should be split equally in size in the div
|
|
44
|
+
*/
|
|
45
|
+
spaceEqually: { type: Boolean, default: false },
|
|
46
|
+
});
|
|
47
|
+
const emit = defineEmits(['step-clicked']);
|
|
48
|
+
|
|
49
|
+
const isEqual = computed(() => props.spaceEqually && !props.vertical);
|
|
50
|
+
provide('progress-space-equally', isEqual);
|
|
51
|
+
const completedSteps = ref(new Set());
|
|
52
|
+
provide('progress-completed-steps', completedSteps);
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @typedef ProgressStepData
|
|
56
|
+
* @type {string} uid
|
|
57
|
+
* @type {string} label
|
|
58
|
+
*/
|
|
59
|
+
/**
|
|
60
|
+
* @type {Ref<UnwrapRef<Array<ProgressStepData>>>}
|
|
61
|
+
*/
|
|
62
|
+
const progressSteps = ref([]);
|
|
63
|
+
provide('progress-steps', progressSteps);
|
|
64
|
+
|
|
65
|
+
const currentStep = ref('');
|
|
66
|
+
provide('progress-current-step', currentStep);
|
|
67
|
+
function updateSteps() {
|
|
68
|
+
if (
|
|
69
|
+
props.initialStep > -1 &&
|
|
70
|
+
props.initialStep < progressSteps.value.length
|
|
71
|
+
) {
|
|
72
|
+
const step = progressSteps.value[props.initialStep];
|
|
73
|
+
currentStep.value = step.uid;
|
|
74
|
+
} else currentStep.value = '';
|
|
75
|
+
}
|
|
76
|
+
onMounted(updateSteps);
|
|
77
|
+
watch(() => props.initialStep, updateSteps);
|
|
78
|
+
</script>
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
<!--suppress HtmlUnknownTag -->
|
|
2
|
+
<template>
|
|
3
|
+
<li
|
|
4
|
+
:class="[
|
|
5
|
+
`cv-progress-step ${carbonPrefix}--progress-step`,
|
|
6
|
+
`${carbonPrefix}--progress-step--${internalState}`,
|
|
7
|
+
]"
|
|
8
|
+
:id="uid"
|
|
9
|
+
:aria-disabled="disabled"
|
|
10
|
+
>
|
|
11
|
+
<button
|
|
12
|
+
type="button"
|
|
13
|
+
:class="[
|
|
14
|
+
`${carbonPrefix}--progress-step-button`,
|
|
15
|
+
{ [`${carbonPrefix}--progress-step-button--unclickable`]: isCurrent },
|
|
16
|
+
]"
|
|
17
|
+
tabindex="-1"
|
|
18
|
+
:title="label"
|
|
19
|
+
@click.prevent="emit('step-clicked', { uid })"
|
|
20
|
+
>
|
|
21
|
+
<span v-if="isCurrent" :class="`${carbonPrefix}--assistive-text`"
|
|
22
|
+
>Current</span
|
|
23
|
+
>
|
|
24
|
+
<slot name="step-icon">
|
|
25
|
+
<component :is="stepIcon" :class="stepClass">
|
|
26
|
+
<title>{{ description }}</title>
|
|
27
|
+
</component>
|
|
28
|
+
</slot>
|
|
29
|
+
<div
|
|
30
|
+
:class="`${carbonPrefix}--progress-text`"
|
|
31
|
+
:style="{ maxWidth: isEqual ? 'calc(100% - 1rem)' : undefined }"
|
|
32
|
+
>
|
|
33
|
+
<!-- todo: add tooltip when tooltip is implemented -->
|
|
34
|
+
<!-- <cv-tooltip v-if="tipText" ... v-else -->
|
|
35
|
+
<div :class="[`${carbonPrefix}--progress-label`]">
|
|
36
|
+
{{ label }}
|
|
37
|
+
</div>
|
|
38
|
+
<p v-if="additionalInfo" class="bx--progress-optional">
|
|
39
|
+
{{ additionalInfo }}
|
|
40
|
+
</p>
|
|
41
|
+
</div>
|
|
42
|
+
<span :class="`${carbonPrefix}--progress-line`"></span>
|
|
43
|
+
</button>
|
|
44
|
+
</li>
|
|
45
|
+
</template>
|
|
46
|
+
|
|
47
|
+
<script setup>
|
|
48
|
+
import {
|
|
49
|
+
Incomplete16,
|
|
50
|
+
CheckmarkOutline16,
|
|
51
|
+
Warning16,
|
|
52
|
+
CircleDash16,
|
|
53
|
+
} from '@carbon/icons-vue';
|
|
54
|
+
// noinspection ES6PreferShortImport
|
|
55
|
+
import { carbonPrefix } from '../../global/settings';
|
|
56
|
+
import { useCvId, props as propsCvId } from '../../use/cvId';
|
|
57
|
+
import { computed, inject, onBeforeUnmount, onMounted, ref, watch } from 'vue';
|
|
58
|
+
|
|
59
|
+
const STEP_CURRENT = 'current';
|
|
60
|
+
const STEP_COMPLETE = 'complete';
|
|
61
|
+
const STEP_INCOMPLETE = 'incomplete';
|
|
62
|
+
const STEP_DISABLED = 'disabled';
|
|
63
|
+
|
|
64
|
+
const props = defineProps({
|
|
65
|
+
additionalInfo: String,
|
|
66
|
+
description: String,
|
|
67
|
+
disabled: Boolean,
|
|
68
|
+
invalid: Boolean,
|
|
69
|
+
label: String,
|
|
70
|
+
tipText: String,
|
|
71
|
+
complete: Boolean,
|
|
72
|
+
...propsCvId,
|
|
73
|
+
});
|
|
74
|
+
const uid = useCvId(props, true);
|
|
75
|
+
const isEqual = inject('progress-space-equally');
|
|
76
|
+
|
|
77
|
+
const emit = defineEmits(['step-clicked']);
|
|
78
|
+
|
|
79
|
+
const internalState = ref(STEP_INCOMPLETE);
|
|
80
|
+
/**
|
|
81
|
+
* @type {Ref<UnwrapRef<string>>}
|
|
82
|
+
*/
|
|
83
|
+
const currentStep = inject('progress-current-step');
|
|
84
|
+
const isCurrent = computed(() => {
|
|
85
|
+
return uid.value === currentStep.value;
|
|
86
|
+
});
|
|
87
|
+
/**
|
|
88
|
+
* @type {Ref<UnwrapRef<Array<ProgressStepData>>>}
|
|
89
|
+
*/
|
|
90
|
+
const progressSteps = inject('progress-steps');
|
|
91
|
+
/**
|
|
92
|
+
* @type {Ref<UnwrapRef<Set<string>>>}
|
|
93
|
+
*/
|
|
94
|
+
const completedSteps = inject('progress-completed-steps');
|
|
95
|
+
function checkCurrentStep() {
|
|
96
|
+
if (props.disabled) internalState.value = STEP_DISABLED;
|
|
97
|
+
else if (isCurrent.value) internalState.value = STEP_CURRENT;
|
|
98
|
+
else if (props.complete) internalState.value = STEP_COMPLETE;
|
|
99
|
+
else internalState.value = STEP_INCOMPLETE;
|
|
100
|
+
|
|
101
|
+
const stepData = { uid: uid.value, state: internalState.value };
|
|
102
|
+
const index = progressSteps.value.findIndex(step => step.uid === uid.value);
|
|
103
|
+
if (index > -1) progressSteps.value.splice(index, 1, stepData);
|
|
104
|
+
else progressSteps.value.push(stepData);
|
|
105
|
+
}
|
|
106
|
+
onMounted(checkCurrentStep);
|
|
107
|
+
watch(currentStep, checkCurrentStep);
|
|
108
|
+
watch(completedSteps, checkCurrentStep);
|
|
109
|
+
|
|
110
|
+
onBeforeUnmount(() => {
|
|
111
|
+
const index = progressSteps.value.findIndex(step => step.uid === uid.value);
|
|
112
|
+
if (index > -1) progressSteps.value.splice(index, 1);
|
|
113
|
+
});
|
|
114
|
+
const stepClass = computed(() => {
|
|
115
|
+
return props.invalid ? `${carbonPrefix}--progress__warning` : '';
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
const stepIcon = computed(() => {
|
|
119
|
+
if (props.invalid) return Warning16;
|
|
120
|
+
else if (internalState.value === STEP_CURRENT) return Incomplete16;
|
|
121
|
+
else if (internalState.value === STEP_COMPLETE) return CheckmarkOutline16;
|
|
122
|
+
else return CircleDash16;
|
|
123
|
+
});
|
|
124
|
+
</script>
|