@carbon/vue 3.0.7-alpha.0 → 3.0.8-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 +3438 -177
- package/dist/carbon-vue-3.common.js.map +1 -1
- package/dist/carbon-vue-3.umd.js +3438 -177
- 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/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/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 +25 -0
|
@@ -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>
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { action } from '@storybook/addon-actions';
|
|
2
|
+
import { CvRadioButton, CvRadioGroup } from '.';
|
|
3
|
+
import {
|
|
4
|
+
sbCompPrefix,
|
|
5
|
+
storyParametersObject,
|
|
6
|
+
} from '../../global/storybook-utils';
|
|
7
|
+
import { ref } from 'vue';
|
|
8
|
+
|
|
9
|
+
export default {
|
|
10
|
+
title: `${sbCompPrefix}/CvRadioButton`,
|
|
11
|
+
component: CvRadioButton,
|
|
12
|
+
argTypes: {
|
|
13
|
+
checked: {
|
|
14
|
+
type: 'boolean',
|
|
15
|
+
control: false,
|
|
16
|
+
table: {
|
|
17
|
+
type: { summary: 'boolean' },
|
|
18
|
+
category: 'props',
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
label: {
|
|
22
|
+
description: 'radio-button label',
|
|
23
|
+
control: false,
|
|
24
|
+
},
|
|
25
|
+
hideLabel: {
|
|
26
|
+
description:
|
|
27
|
+
'makes the label visually hidden but still labels the radio input',
|
|
28
|
+
},
|
|
29
|
+
labelLeft: {
|
|
30
|
+
type: 'boolean',
|
|
31
|
+
table: {
|
|
32
|
+
type: { summary: 'boolean' },
|
|
33
|
+
category: 'props',
|
|
34
|
+
},
|
|
35
|
+
description: 'position label on left',
|
|
36
|
+
},
|
|
37
|
+
vertical: {
|
|
38
|
+
type: 'boolean',
|
|
39
|
+
table: {
|
|
40
|
+
type: { summary: 'boolean' },
|
|
41
|
+
category: 'props',
|
|
42
|
+
},
|
|
43
|
+
description:
|
|
44
|
+
'Property of CvRadioGroup component - stacks inside radio components vertically',
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const DefaultRadioItems = [
|
|
50
|
+
{
|
|
51
|
+
label: 'radio-1',
|
|
52
|
+
id: 'value-1',
|
|
53
|
+
checked: true,
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
label: 'radio-2',
|
|
57
|
+
id: 'value-2',
|
|
58
|
+
disabled: true,
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
label: 'radio-3',
|
|
62
|
+
id: 'value-3',
|
|
63
|
+
},
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
const DefaultStoryParameters = {
|
|
67
|
+
controls: {
|
|
68
|
+
exclude: ['change', 'update:modelValue', 'modelValue'],
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const defaultTemplate = `
|
|
73
|
+
<cv-radio-group v-bind="args" @change="onChange">
|
|
74
|
+
<cv-radio-button
|
|
75
|
+
v-for="({id, label, checked, disabled}, index) in DefaultRadioItems"
|
|
76
|
+
:key="index"
|
|
77
|
+
name="group-1"
|
|
78
|
+
:label="label"
|
|
79
|
+
:value="id"
|
|
80
|
+
:checked="checked"
|
|
81
|
+
:disabled="disabled"
|
|
82
|
+
:hide-label="hideLabel"
|
|
83
|
+
:label-left='labelLeft'
|
|
84
|
+
/>
|
|
85
|
+
</cv-radio-group>
|
|
86
|
+
`;
|
|
87
|
+
|
|
88
|
+
const Template = (args, { argTypes }) => {
|
|
89
|
+
return {
|
|
90
|
+
props: Object.keys(argTypes),
|
|
91
|
+
components: { CvRadioButton, CvRadioGroup },
|
|
92
|
+
template: defaultTemplate,
|
|
93
|
+
setup() {
|
|
94
|
+
return {
|
|
95
|
+
args,
|
|
96
|
+
hideLabel: args.hideLabel,
|
|
97
|
+
labelLeft: args.labelLeft,
|
|
98
|
+
onChange: action('change'),
|
|
99
|
+
DefaultRadioItems,
|
|
100
|
+
};
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export const Default = Template.bind({});
|
|
106
|
+
Default.args = {
|
|
107
|
+
vertical: false,
|
|
108
|
+
};
|
|
109
|
+
Default.parameters = storyParametersObject(
|
|
110
|
+
DefaultStoryParameters,
|
|
111
|
+
defaultTemplate,
|
|
112
|
+
Default.args
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
const vModelTemplate = `
|
|
116
|
+
<cv-radio-group v-bind="args" @change="onChange">
|
|
117
|
+
<cv-radio-button
|
|
118
|
+
v-for="({id, label, checked, disabled}, index) in DefaultRadioItems"
|
|
119
|
+
v-model="modelValue"
|
|
120
|
+
:key="index"
|
|
121
|
+
name="group-1"
|
|
122
|
+
:label="label"
|
|
123
|
+
:value="id"
|
|
124
|
+
:disabled="disabled"
|
|
125
|
+
:hide-label="hideLabel"
|
|
126
|
+
:label-left='labelLeft'
|
|
127
|
+
/>
|
|
128
|
+
</cv-radio-group>
|
|
129
|
+
|
|
130
|
+
<div style="margin-top:1rem; background-color: #888888; padding:1rem">
|
|
131
|
+
V-model:
|
|
132
|
+
<template
|
|
133
|
+
v-for="({id, label}, index) in DefaultRadioItems"
|
|
134
|
+
:key="index"
|
|
135
|
+
>
|
|
136
|
+
<input name="modelValue" :id="id" type="radio" @change="(ev) => {modelValue = ev.target.id}" :checked="id === modelValue" />
|
|
137
|
+
<label :for="id" style="margin-right: 16px;">{{label}}:</label>
|
|
138
|
+
</template>
|
|
139
|
+
|
|
140
|
+
<div style="margin-top: 16px;">Checked: <span style="font-weight: bold;">{{modelValue}}</span></div>
|
|
141
|
+
</div>
|
|
142
|
+
`;
|
|
143
|
+
|
|
144
|
+
const VModelTemplate = args => {
|
|
145
|
+
return {
|
|
146
|
+
components: { CvRadioButton, CvRadioGroup },
|
|
147
|
+
template: vModelTemplate,
|
|
148
|
+
setup() {
|
|
149
|
+
return {
|
|
150
|
+
args,
|
|
151
|
+
hideLabel: args.hideLabel,
|
|
152
|
+
labelLeft: args.labelLeft,
|
|
153
|
+
modelValue: ref(DefaultRadioItems[0].id),
|
|
154
|
+
onChange: action('change'),
|
|
155
|
+
DefaultRadioItems,
|
|
156
|
+
};
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
export const VModel = VModelTemplate.bind({});
|
|
162
|
+
VModel.parameters = storyParametersObject(
|
|
163
|
+
DefaultStoryParameters,
|
|
164
|
+
vModelTemplate,
|
|
165
|
+
VModel.args
|
|
166
|
+
);
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
:class="[
|
|
4
|
+
`cv-radio-button ${carbonPrefix}--radio-button-wrapper`,
|
|
5
|
+
{ [`${carbonPrefix}--radio-button-wrapper--label-left`]: labelLeft },
|
|
6
|
+
]"
|
|
7
|
+
>
|
|
8
|
+
<input
|
|
9
|
+
v-bind="$attrs"
|
|
10
|
+
:id="cvId"
|
|
11
|
+
:checked="isChecked"
|
|
12
|
+
:class="`${carbonPrefix}--radio-button`"
|
|
13
|
+
ref="input"
|
|
14
|
+
type="radio"
|
|
15
|
+
:value="value"
|
|
16
|
+
@change="onChange"
|
|
17
|
+
/>
|
|
18
|
+
<!-- symbol causes problem in codepen? -->
|
|
19
|
+
<label :for="cvId" :class="`${carbonPrefix}--radio-button__label`">
|
|
20
|
+
<span :class="`${carbonPrefix}--radio-button__appearance`"></span>
|
|
21
|
+
<span
|
|
22
|
+
v-if="label"
|
|
23
|
+
:class="{ [`${carbonPrefix}--visually-hidden`]: hideLabel }"
|
|
24
|
+
>
|
|
25
|
+
{{ label }}
|
|
26
|
+
</span>
|
|
27
|
+
</label>
|
|
28
|
+
</div>
|
|
29
|
+
</template>
|
|
30
|
+
|
|
31
|
+
<script setup>
|
|
32
|
+
import { carbonPrefix } from '../../global/settings';
|
|
33
|
+
import { useCvId, propsCvId, useMethods, useRadio } from '../../use';
|
|
34
|
+
|
|
35
|
+
const props = defineProps({
|
|
36
|
+
modelValue: String,
|
|
37
|
+
checked: Boolean,
|
|
38
|
+
label: String,
|
|
39
|
+
value: { type: String, required: true },
|
|
40
|
+
hideLabel: Boolean,
|
|
41
|
+
labelLeft: Boolean,
|
|
42
|
+
...propsCvId,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const cvId = useCvId(props);
|
|
46
|
+
|
|
47
|
+
const emit = defineEmits(['update:modelValue', 'change']);
|
|
48
|
+
|
|
49
|
+
useMethods({ input: ['blur', 'focus'] });
|
|
50
|
+
const { isChecked, onChange } = useRadio(props, emit);
|
|
51
|
+
</script>
|
|
52
|
+
|
|
53
|
+
<script>
|
|
54
|
+
export default {
|
|
55
|
+
inheritAttrs: false,
|
|
56
|
+
};
|
|
57
|
+
</script>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :class="`cv-radio-group ${carbonPrefix}--form-item`">
|
|
3
|
+
<div
|
|
4
|
+
:class="[
|
|
5
|
+
`${carbonPrefix}--radio-button-group`,
|
|
6
|
+
{ [`${carbonPrefix}--radio-button-group--vertical`]: vertical },
|
|
7
|
+
]"
|
|
8
|
+
>
|
|
9
|
+
<slot></slot>
|
|
10
|
+
</div>
|
|
11
|
+
</div>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script setup>
|
|
15
|
+
import { provide } from 'vue';
|
|
16
|
+
import { carbonPrefix } from '../../global/settings';
|
|
17
|
+
|
|
18
|
+
defineProps({
|
|
19
|
+
vertical: Boolean,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const emit = defineEmits(['change']);
|
|
23
|
+
|
|
24
|
+
provide('onRadioItemChange', clickedItemCvId => {
|
|
25
|
+
emit('change', clickedItemCvId);
|
|
26
|
+
});
|
|
27
|
+
</script>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`CvRadioButton matches render when checked 1`] = `<div class="cv-radio-button bx--radio-button-wrapper"><input id="1" class="bx--radio-button" type="radio" value=""><!-- symbol causes problem in codepen? --><label for="1" class="bx--radio-button__label"><span class="bx--radio-button__appearance"></span><span class="">test label</span></label></div>`;
|
|
4
|
+
|
|
5
|
+
exports[`CvRadioButton matches render when modelValue is equal to value 1`] = `<div class="cv-radio-button bx--radio-button-wrapper"><input id="1" class="bx--radio-button" type="radio" value="test value"><!-- symbol causes problem in codepen? --><label for="1" class="bx--radio-button__label"><span class="bx--radio-button__appearance"></span><span class="">test label</span></label></div>`;
|
|
6
|
+
|
|
7
|
+
exports[`CvRadioButton matches render when modelValue is not equal to value 1`] = `<div class="cv-radio-button bx--radio-button-wrapper"><input id="1" class="bx--radio-button" type="radio" value="test value"><!-- symbol causes problem in codepen? --><label for="1" class="bx--radio-button__label"><span class="bx--radio-button__appearance"></span><span class="">test label</span></label></div>`;
|
|
8
|
+
|
|
9
|
+
exports[`CvRadioButton matches render with left label 1`] = `<div class="cv-radio-button bx--radio-button-wrapper bx--radio-button-wrapper--label-left"><input id="1" class="bx--radio-button" type="radio" value=""><!-- symbol causes problem in codepen? --><label for="1" class="bx--radio-button__label"><span class="bx--radio-button__appearance"></span><span class="">left label</span></label></div>`;
|
|
10
|
+
|
|
11
|
+
exports[`CvRadioButton matches render with right label 1`] = `<div class="cv-radio-button bx--radio-button-wrapper"><input id="1" class="bx--radio-button" type="radio" value=""><!-- symbol causes problem in codepen? --><label for="1" class="bx--radio-button__label"><span class="bx--radio-button__appearance"></span><span class="">right label</span></label></div>`;
|
|
12
|
+
|
|
13
|
+
exports[`CvRadioGroup matches render when horizontal 1`] = `
|
|
14
|
+
<div class="cv-radio-group bx--form-item">
|
|
15
|
+
<div class="bx--radio-button-group">
|
|
16
|
+
<div class="cv-radio-button-stub">RadioButtonStub</div>
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
`;
|
|
20
|
+
|
|
21
|
+
exports[`CvRadioGroup matches render when vertical 1`] = `
|
|
22
|
+
<div class="cv-radio-group bx--form-item">
|
|
23
|
+
<div class="bx--radio-button-group bx--radio-button-group--vertical">
|
|
24
|
+
<div class="cv-radio-button-stub">RadioButtonStub</div>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
`;
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { Canvas, Meta, Story } from '@storybook/addon-docs';
|
|
2
|
+
import CvSearch from './CvSearch.vue';
|
|
3
|
+
import { sbCompPrefix } from '../../global/storybook-utils';
|
|
4
|
+
import { SEARCH_SIZES } from './index';
|
|
5
|
+
import { action } from '@storybook/addon-actions';
|
|
6
|
+
import { ref } from 'vue';
|
|
7
|
+
const myValue = ref('searching galaxies');
|
|
8
|
+
|
|
9
|
+
<Meta title={`${sbCompPrefix}/CvSearch`} component={CvSearch} />
|
|
10
|
+
|
|
11
|
+
export const Template = args => ({
|
|
12
|
+
// Components used in your story `template` are defined in the `components` object
|
|
13
|
+
components: {
|
|
14
|
+
CvSearch,
|
|
15
|
+
},
|
|
16
|
+
// The story's `args` need to be mapped into the template through the `setup()` method
|
|
17
|
+
setup() {
|
|
18
|
+
return {
|
|
19
|
+
light: args.light,
|
|
20
|
+
label: args.label,
|
|
21
|
+
placeholder: args.placeholder,
|
|
22
|
+
disabled: args.disabled,
|
|
23
|
+
size: args.size,
|
|
24
|
+
ariaLabel: args.ariaLabel,
|
|
25
|
+
clearAriaLabel: args.clearAriaLabel,
|
|
26
|
+
formItem: args.formItem,
|
|
27
|
+
expandable: args.expandable,
|
|
28
|
+
value: args.value,
|
|
29
|
+
myValue: myValue,
|
|
30
|
+
onInput: action('input'),
|
|
31
|
+
};
|
|
32
|
+
},
|
|
33
|
+
template: args.template,
|
|
34
|
+
});
|
|
35
|
+
const defaultTemplate = `
|
|
36
|
+
<cv-search
|
|
37
|
+
:light="light"
|
|
38
|
+
:label="label"
|
|
39
|
+
:placeholder="placeholder"
|
|
40
|
+
:disabled="disabled"
|
|
41
|
+
:size="size"
|
|
42
|
+
:expandable="expandable"
|
|
43
|
+
:value="value"
|
|
44
|
+
:form-item="formItem"
|
|
45
|
+
:aria-label="ariaLabel"
|
|
46
|
+
:clear-aria-label="clearAriaLabel"
|
|
47
|
+
@input="onInput"
|
|
48
|
+
>
|
|
49
|
+
</cv-search>
|
|
50
|
+
`;
|
|
51
|
+
const vModelTemplate = `
|
|
52
|
+
<div>
|
|
53
|
+
<cv-search
|
|
54
|
+
v-model:value="myValue"
|
|
55
|
+
:light="light"
|
|
56
|
+
:label="label"
|
|
57
|
+
:placeholder="placeholder"
|
|
58
|
+
:disabled="disabled"
|
|
59
|
+
:size="size"
|
|
60
|
+
:expandable="expandable"
|
|
61
|
+
:form-item="formItem"
|
|
62
|
+
:aria-label="ariaLabel"
|
|
63
|
+
:clear-aria-label="clearAriaLabel"
|
|
64
|
+
>
|
|
65
|
+
</cv-search>
|
|
66
|
+
<div style="margin-top:1rem; background-color: #888888; padding:1rem">
|
|
67
|
+
<div style="padding:1rem">v-model value: {{ myValue }}</div>
|
|
68
|
+
<input type="search" v-model="myValue"/>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
`;
|
|
72
|
+
|
|
73
|
+
# CvSearch
|
|
74
|
+
|
|
75
|
+
Migration notes:
|
|
76
|
+
|
|
77
|
+
- The `v-model` is different in Vue 3 than Vue 2. If you specify it you will see an error deprecation message in the log.
|
|
78
|
+
Please use `v-model:value=something` instead.
|
|
79
|
+
- The "toolbar" mode is removed in this version. Please use the `expandable` mode instead.
|
|
80
|
+
|
|
81
|
+
<Canvas>
|
|
82
|
+
<Story
|
|
83
|
+
name="Default"
|
|
84
|
+
parameters={{
|
|
85
|
+
controls: {
|
|
86
|
+
exclude: [
|
|
87
|
+
'input',
|
|
88
|
+
'modelValue',
|
|
89
|
+
'template',
|
|
90
|
+
'update:modelValue',
|
|
91
|
+
'update:value',
|
|
92
|
+
'large',
|
|
93
|
+
'small',
|
|
94
|
+
'toolbarAriaLabel',
|
|
95
|
+
'kind',
|
|
96
|
+
],
|
|
97
|
+
},
|
|
98
|
+
docs: { source: { code: defaultTemplate } },
|
|
99
|
+
}}
|
|
100
|
+
args={{
|
|
101
|
+
template: defaultTemplate,
|
|
102
|
+
light: false,
|
|
103
|
+
disabled: false,
|
|
104
|
+
placeholder: 'JWST: search for light from the first stars',
|
|
105
|
+
}}
|
|
106
|
+
argTypes={{
|
|
107
|
+
light: {
|
|
108
|
+
description: '`true` to use the light version.',
|
|
109
|
+
table: { category: 'props', defaultValue: { summary: false } },
|
|
110
|
+
},
|
|
111
|
+
size: {
|
|
112
|
+
control: 'select',
|
|
113
|
+
default: 'xl',
|
|
114
|
+
options: SEARCH_SIZES,
|
|
115
|
+
table: { defaultValue: { summary: 'xl' } },
|
|
116
|
+
},
|
|
117
|
+
}}
|
|
118
|
+
>
|
|
119
|
+
{Template.bind({})}
|
|
120
|
+
</Story>
|
|
121
|
+
</Canvas>
|
|
122
|
+
|
|
123
|
+
# v-model
|
|
124
|
+
|
|
125
|
+
- The `v-model` is different in Vue 3 than Vue 2.If you specify it you will see an error deprecation message in the log.
|
|
126
|
+
Please use `v-model:value=something` instead.
|
|
127
|
+
|
|
128
|
+
<Canvas>
|
|
129
|
+
<Story
|
|
130
|
+
name="v-model"
|
|
131
|
+
parameters={{
|
|
132
|
+
controls: {
|
|
133
|
+
exclude: [
|
|
134
|
+
'input',
|
|
135
|
+
'modelValue',
|
|
136
|
+
'template',
|
|
137
|
+
'update:modelValue',
|
|
138
|
+
'update:value',
|
|
139
|
+
'large',
|
|
140
|
+
'small',
|
|
141
|
+
'toolbarAriaLabel',
|
|
142
|
+
'kind',
|
|
143
|
+
],
|
|
144
|
+
},
|
|
145
|
+
docs: { source: { code: vModelTemplate } },
|
|
146
|
+
}}
|
|
147
|
+
args={{
|
|
148
|
+
template: vModelTemplate,
|
|
149
|
+
light: false,
|
|
150
|
+
disabled: false,
|
|
151
|
+
placeholder: 'JWST: search for light from the first stars',
|
|
152
|
+
}}
|
|
153
|
+
argTypes={{
|
|
154
|
+
light: {
|
|
155
|
+
description: '`true` to use the light version.',
|
|
156
|
+
table: { category: 'props', defaultValue: { summary: false } },
|
|
157
|
+
},
|
|
158
|
+
size: {
|
|
159
|
+
control: 'select',
|
|
160
|
+
default: 'xl',
|
|
161
|
+
options: SEARCH_SIZES,
|
|
162
|
+
table: { defaultValue: { summary: 'xl' } },
|
|
163
|
+
},
|
|
164
|
+
}}
|
|
165
|
+
>
|
|
166
|
+
{Template.bind({})}
|
|
167
|
+
</Story>
|
|
168
|
+
</Canvas>
|