@carbon/vue 3.0.4-alpha.0 → 3.0.6-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 +16 -0
- package/dist/carbon-vue-3.common.js +11782 -2709
- package/dist/carbon-vue-3.common.js.map +1 -1
- package/dist/carbon-vue-3.css +1 -0
- package/dist/carbon-vue-3.umd.js +11782 -2709
- package/dist/carbon-vue-3.umd.js.map +1 -1
- package/dist/carbon-vue-3.umd.min.js +30 -2
- package/dist/carbon-vue-3.umd.min.js.map +1 -1
- package/package.json +3 -2
- package/src/components/CvCheckbox/CvCheckbox.vue +0 -2
- package/src/components/CvDatePicker/CvDatePicker-notes.md +86 -0
- package/src/components/CvDatePicker/CvDatePicker.stories.js +241 -0
- package/src/components/CvDatePicker/CvDatePicker.vue +402 -0
- package/src/components/CvDatePicker/CvDatePickerSkeleton.vue +106 -0
- package/src/components/CvDatePicker/index.js +4 -0
- package/src/components/CvDatePicker/plugins/appendToPlugin.js +64 -0
- package/src/components/CvDatePicker/plugins/fixEventsPlugin.js +79 -0
- package/src/components/CvDatePicker/plugins/monthSelectPlugin.js +86 -0
- package/src/components/CvDatePicker/plugins/rangePlugin.js +47 -0
- package/src/components/CvForm/CvForm.stories.mdx +193 -0
- package/src/components/CvForm/CvForm.vue +9 -0
- package/src/components/CvForm/CvFormGroup.vue +27 -0
- package/src/components/CvForm/CvFormItem.vue +9 -0
- package/src/components/CvForm/index.js +5 -0
- package/src/components/CvModal/CvModal.stories.mdx +234 -0
- package/src/components/CvModal/CvModal.vue +403 -0
- package/src/components/CvModal/index.js +3 -0
- package/src/components/CvTextArea/CvTextArea.stories.js +174 -0
- package/src/components/CvTextArea/CvTextArea.vue +107 -0
- package/src/components/CvTextArea/index.js +4 -0
- package/src/components/CvTextInput/CvTextInput.stories.js +245 -0
- package/src/components/CvTextInput/CvTextInput.vue +217 -0
- package/src/components/CvTextInput/const.js +2 -0
- package/src/components/CvTextInput/index.js +4 -0
- package/src/components/CvTile/CvTile.stories.mdx +156 -0
- package/src/components/CvTile/CvTile.vue +67 -0
- package/src/components/CvTile/CvTileClickable.vue +23 -0
- package/src/components/CvTile/CvTileExpandable.vue +103 -0
- package/src/components/CvTile/CvTileSelectable.vue +52 -0
- package/src/components/CvTile/CvTileStandard.vue +7 -0
- package/src/components/CvTile/index.js +4 -0
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import {
|
|
2
|
+
sbCompPrefix,
|
|
3
|
+
storyParametersObject,
|
|
4
|
+
} from '../../global/storybook-utils';
|
|
5
|
+
|
|
6
|
+
import CvTextInput from '.';
|
|
7
|
+
import { ref } from 'vue';
|
|
8
|
+
|
|
9
|
+
export default {
|
|
10
|
+
title: `${sbCompPrefix}/CvTextInput`,
|
|
11
|
+
component: CvTextInput,
|
|
12
|
+
argTypes: {
|
|
13
|
+
// attrs
|
|
14
|
+
disabled: {
|
|
15
|
+
type: 'boolean',
|
|
16
|
+
table: {
|
|
17
|
+
type: { summary: 'boolean' },
|
|
18
|
+
category: 'attributes',
|
|
19
|
+
},
|
|
20
|
+
description: 'Specify whether the `<input>` should be disabled',
|
|
21
|
+
},
|
|
22
|
+
placeholder: {
|
|
23
|
+
type: 'string',
|
|
24
|
+
table: {
|
|
25
|
+
type: { summary: 'string' },
|
|
26
|
+
category: 'attributes',
|
|
27
|
+
},
|
|
28
|
+
description: 'Specify the placeholder attribute for the `<input>`',
|
|
29
|
+
},
|
|
30
|
+
// props
|
|
31
|
+
helperText: {
|
|
32
|
+
type: 'string',
|
|
33
|
+
table: {
|
|
34
|
+
type: { summary: 'string' },
|
|
35
|
+
category: 'props',
|
|
36
|
+
},
|
|
37
|
+
description:
|
|
38
|
+
'Provide text that is used alongside the control label for additional help',
|
|
39
|
+
},
|
|
40
|
+
hideLabel: {
|
|
41
|
+
type: 'boolean',
|
|
42
|
+
table: {
|
|
43
|
+
type: { summary: 'boolean' },
|
|
44
|
+
category: 'props',
|
|
45
|
+
defaultValue: false,
|
|
46
|
+
},
|
|
47
|
+
description:
|
|
48
|
+
'Specify whether you want the underlying label to be visually hidden',
|
|
49
|
+
},
|
|
50
|
+
invalidMessage: {
|
|
51
|
+
type: 'string',
|
|
52
|
+
table: {
|
|
53
|
+
type: { summary: 'string' },
|
|
54
|
+
category: 'props',
|
|
55
|
+
},
|
|
56
|
+
description:
|
|
57
|
+
'Provide the text that is displayed when the control is in an invalid state',
|
|
58
|
+
},
|
|
59
|
+
label: {
|
|
60
|
+
type: 'string',
|
|
61
|
+
table: {
|
|
62
|
+
type: { summary: 'string' },
|
|
63
|
+
category: 'props',
|
|
64
|
+
},
|
|
65
|
+
description: "Input's label",
|
|
66
|
+
},
|
|
67
|
+
light: {
|
|
68
|
+
type: 'boolean',
|
|
69
|
+
table: {
|
|
70
|
+
type: { summary: 'boolean' },
|
|
71
|
+
category: 'props',
|
|
72
|
+
defaultValue: false,
|
|
73
|
+
},
|
|
74
|
+
description:
|
|
75
|
+
"Toggles light version. For use on `$ui-01` backgrounds only. Don't use this to make tile background color same as container background color.",
|
|
76
|
+
},
|
|
77
|
+
modelValue: {
|
|
78
|
+
type: 'string',
|
|
79
|
+
table: {
|
|
80
|
+
type: { summary: 'string' },
|
|
81
|
+
category: 'props',
|
|
82
|
+
},
|
|
83
|
+
description:
|
|
84
|
+
"Input's value, modelValue is the vue3 default 'prop' for two-way data binding with v-model",
|
|
85
|
+
},
|
|
86
|
+
passwordHideLabel: {
|
|
87
|
+
type: 'string',
|
|
88
|
+
table: {
|
|
89
|
+
type: { summary: 'string' },
|
|
90
|
+
category: 'props',
|
|
91
|
+
},
|
|
92
|
+
description: '"Hide password" tooltip text on password visibility toggle',
|
|
93
|
+
},
|
|
94
|
+
passwordShowLabel: {
|
|
95
|
+
type: 'string',
|
|
96
|
+
table: {
|
|
97
|
+
type: { summary: 'string' },
|
|
98
|
+
category: 'props',
|
|
99
|
+
},
|
|
100
|
+
description: '"Show password" tooltip text on password visibility toggle',
|
|
101
|
+
},
|
|
102
|
+
passwordVisible: {
|
|
103
|
+
type: 'boolean',
|
|
104
|
+
table: {
|
|
105
|
+
type: { summary: 'boolean' },
|
|
106
|
+
category: 'props',
|
|
107
|
+
},
|
|
108
|
+
description: 'Toggle password visibility.',
|
|
109
|
+
},
|
|
110
|
+
type: {
|
|
111
|
+
type: 'string',
|
|
112
|
+
table: {
|
|
113
|
+
type: { summary: 'string' },
|
|
114
|
+
category: 'props',
|
|
115
|
+
defaultValue: { summary: 'text' },
|
|
116
|
+
},
|
|
117
|
+
options: ['text', 'password'],
|
|
118
|
+
control: {
|
|
119
|
+
type: 'select',
|
|
120
|
+
},
|
|
121
|
+
description: 'Input type, only `text` and `password` are available',
|
|
122
|
+
},
|
|
123
|
+
warnText: {
|
|
124
|
+
type: 'string',
|
|
125
|
+
table: {
|
|
126
|
+
type: { summary: 'string' },
|
|
127
|
+
category: 'props',
|
|
128
|
+
},
|
|
129
|
+
description:
|
|
130
|
+
'Provide the text that is displayed when the control is in warning state',
|
|
131
|
+
},
|
|
132
|
+
// slots
|
|
133
|
+
'helper-text': {
|
|
134
|
+
type: 'string',
|
|
135
|
+
table: {
|
|
136
|
+
type: { summary: 'string | html | Component' },
|
|
137
|
+
category: 'slots',
|
|
138
|
+
},
|
|
139
|
+
description:
|
|
140
|
+
"Helper text slot. It isn't shown if invalid message or warn text, either props or slots, are available",
|
|
141
|
+
},
|
|
142
|
+
'invalid-message': {
|
|
143
|
+
type: 'string',
|
|
144
|
+
table: {
|
|
145
|
+
type: { summary: 'string | html | Component' },
|
|
146
|
+
category: 'slots',
|
|
147
|
+
},
|
|
148
|
+
description: 'Invalid message slot.',
|
|
149
|
+
},
|
|
150
|
+
'warn-text': {
|
|
151
|
+
type: 'string',
|
|
152
|
+
table: {
|
|
153
|
+
type: { summary: 'string | html | Component' },
|
|
154
|
+
category: 'slots',
|
|
155
|
+
},
|
|
156
|
+
description:
|
|
157
|
+
"Warn text slot. It isn't shown if invalid message, either prop or slot, is available",
|
|
158
|
+
},
|
|
159
|
+
// events
|
|
160
|
+
'update:modelValue': {
|
|
161
|
+
type: 'event',
|
|
162
|
+
table: {
|
|
163
|
+
type: { summary: 'event' },
|
|
164
|
+
category: 'events',
|
|
165
|
+
},
|
|
166
|
+
control: { type: null },
|
|
167
|
+
description:
|
|
168
|
+
"Triggered on textarea update. `update:modelValue` is the vue3 default 'event' for two-way data binding with v-model",
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
const template = `
|
|
174
|
+
<cv-text-input v-bind="args">
|
|
175
|
+
<template v-if="args['helper-text']" v-slot:helper-text />
|
|
176
|
+
<template v-if="args['warn-text']" v-slot:warn-text />
|
|
177
|
+
<template v-if="args['invalid-message']" v-slot:invalid-message />
|
|
178
|
+
</cv-text-input>
|
|
179
|
+
`;
|
|
180
|
+
const Template = args => {
|
|
181
|
+
return {
|
|
182
|
+
components: { CvTextInput },
|
|
183
|
+
setup: () => ({ args }),
|
|
184
|
+
template,
|
|
185
|
+
};
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
export const Default = Template.bind({});
|
|
189
|
+
Default.args = {
|
|
190
|
+
helperText: 'Same helper text',
|
|
191
|
+
label: 'Text input label',
|
|
192
|
+
placeholder: 'Sample placeholder',
|
|
193
|
+
};
|
|
194
|
+
Default.parameters = storyParametersObject(
|
|
195
|
+
Default.parameters,
|
|
196
|
+
template,
|
|
197
|
+
Default.args
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
export const Slots = Template.bind({});
|
|
201
|
+
Slots.args = {
|
|
202
|
+
'invalid-message': 'Same invalid message',
|
|
203
|
+
'warn-text': 'Same warn message',
|
|
204
|
+
'helper-text': 'Same help message',
|
|
205
|
+
label: 'Text input label',
|
|
206
|
+
placeholder: 'Sample placeholder',
|
|
207
|
+
};
|
|
208
|
+
Slots.parameters = storyParametersObject(
|
|
209
|
+
Slots.parameters,
|
|
210
|
+
template,
|
|
211
|
+
Slots.args
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
const vModelTemplate = `
|
|
215
|
+
<cv-text-input v-bind="args" v-model="value" />
|
|
216
|
+
<p style="margin-top: 1rem;">Value passed to v-model: {{ value }}</p>
|
|
217
|
+
`;
|
|
218
|
+
const VModelTemplate = args => {
|
|
219
|
+
return {
|
|
220
|
+
components: { CvTextInput },
|
|
221
|
+
setup: () => ({ args, value: ref('') }),
|
|
222
|
+
template: vModelTemplate,
|
|
223
|
+
};
|
|
224
|
+
};
|
|
225
|
+
export const vModel = VModelTemplate.bind({});
|
|
226
|
+
vModel.args = {
|
|
227
|
+
label: 'Text input label',
|
|
228
|
+
placeholder: 'Sample placeholder',
|
|
229
|
+
};
|
|
230
|
+
vModel.parameters = storyParametersObject(
|
|
231
|
+
vModel.parameters,
|
|
232
|
+
vModelTemplate,
|
|
233
|
+
vModel.args
|
|
234
|
+
);
|
|
235
|
+
|
|
236
|
+
export const Password = Template.bind({});
|
|
237
|
+
Password.args = {
|
|
238
|
+
label: 'Password input label',
|
|
239
|
+
type: 'password',
|
|
240
|
+
};
|
|
241
|
+
Password.parameters = storyParametersObject(
|
|
242
|
+
Password.parameters,
|
|
243
|
+
template,
|
|
244
|
+
Password.args
|
|
245
|
+
);
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
:class="[
|
|
4
|
+
'cv-text-input',
|
|
5
|
+
`${carbonPrefix}--form-item`,
|
|
6
|
+
`${carbonPrefix}--text-input-wrapper`,
|
|
7
|
+
{ [`${carbonPrefix}--password-input-wrapper`]: isPassword },
|
|
8
|
+
]"
|
|
9
|
+
>
|
|
10
|
+
<label
|
|
11
|
+
:for="cvId"
|
|
12
|
+
:class="[
|
|
13
|
+
`${carbonPrefix}--label`,
|
|
14
|
+
{
|
|
15
|
+
[`${carbonPrefix}--label--disabled`]: $attrs.disabled,
|
|
16
|
+
[`${carbonPrefix}--visually-hidden`]: hideLabel,
|
|
17
|
+
},
|
|
18
|
+
]"
|
|
19
|
+
>
|
|
20
|
+
{{ label }}
|
|
21
|
+
</label>
|
|
22
|
+
<div
|
|
23
|
+
:class="[
|
|
24
|
+
`${carbonPrefix}--text-input__field-wrapper`,
|
|
25
|
+
{ [`${carbonPrefix}--text-input__field-wrapper--warning`]: isWarn },
|
|
26
|
+
]"
|
|
27
|
+
:data-invalid="isInvalid"
|
|
28
|
+
>
|
|
29
|
+
<WarningFilled16
|
|
30
|
+
v-if="isInvalid"
|
|
31
|
+
:class="`${carbonPrefix}--text-input__invalid-icon`"
|
|
32
|
+
/>
|
|
33
|
+
<WarningAltFilled16
|
|
34
|
+
v-if="isWarn"
|
|
35
|
+
:class="`${carbonPrefix}--text-input__invalid-icon ${carbonPrefix}--text-input__invalid-icon--warning`"
|
|
36
|
+
/>
|
|
37
|
+
<input
|
|
38
|
+
ref="input"
|
|
39
|
+
:id="cvId"
|
|
40
|
+
:class="[
|
|
41
|
+
`${carbonPrefix}--text-input`,
|
|
42
|
+
{
|
|
43
|
+
[`${carbonPrefix}--text-input--invalid`]: isInvalid,
|
|
44
|
+
[`${carbonPrefix}--text-input--light`]: isLight,
|
|
45
|
+
[`${carbonPrefix}--text-input--warning`]: isWarn,
|
|
46
|
+
[`${carbonPrefix}--password-input`]: isPassword,
|
|
47
|
+
},
|
|
48
|
+
]"
|
|
49
|
+
v-bind="$attrs"
|
|
50
|
+
:type="dataType"
|
|
51
|
+
:value="modelValue"
|
|
52
|
+
:data-toggle-password-visibility="isPassword"
|
|
53
|
+
@input="$event => $emit('update:modelValue', $event.target.value)"
|
|
54
|
+
/>
|
|
55
|
+
<button
|
|
56
|
+
v-if="isPassword"
|
|
57
|
+
:class="[
|
|
58
|
+
`${carbonPrefix}--btn`,
|
|
59
|
+
`${carbonPrefix}--btn--icon-only`,
|
|
60
|
+
`${carbonPrefix}--text-input--password__visibility__toggle`,
|
|
61
|
+
`${carbonPrefix}--tooltip__trigger`,
|
|
62
|
+
`${carbonPrefix}--tooltip--a11y`,
|
|
63
|
+
`${carbonPrefix}--tooltip--bottom`,
|
|
64
|
+
`${carbonPrefix}--tooltip--align-center`,
|
|
65
|
+
{ [`${carbonPrefix}--btn--disabled`]: $attrs.disabled },
|
|
66
|
+
]"
|
|
67
|
+
@click="togglePasswordVisibility"
|
|
68
|
+
type="button"
|
|
69
|
+
:disabled="$attrs.disabled"
|
|
70
|
+
>
|
|
71
|
+
<span :class="`${carbonPrefix}--assistive-text`">
|
|
72
|
+
{{ passwordHideShowLabel }}
|
|
73
|
+
</span>
|
|
74
|
+
<ViewOff16
|
|
75
|
+
v-if="isPasswordVisible"
|
|
76
|
+
:class="`${carbonPrefix}--icon-visibility-off`"
|
|
77
|
+
/>
|
|
78
|
+
<View16 v-else :class="`${carbonPrefix}--icon-visibility-on`" />
|
|
79
|
+
</button>
|
|
80
|
+
</div>
|
|
81
|
+
<div v-if="isInvalid" :class="`${carbonPrefix}--form-requirement`">
|
|
82
|
+
<slot name="invalid-message">{{ invalidMessage }}</slot>
|
|
83
|
+
</div>
|
|
84
|
+
<div v-if="isWarn" :class="`${carbonPrefix}--form__requirement`">
|
|
85
|
+
<slot name="warn-text">{{ warnText }}</slot>
|
|
86
|
+
</div>
|
|
87
|
+
<div
|
|
88
|
+
v-if="isHelper"
|
|
89
|
+
:class="[
|
|
90
|
+
`${carbonPrefix}--form__helper-text`,
|
|
91
|
+
{ [`${carbonPrefix}--form__helper-text--disabled`]: $attrs.disabled },
|
|
92
|
+
]"
|
|
93
|
+
>
|
|
94
|
+
<slot name="helper-text">{{ helperText }}</slot>
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
</template>
|
|
98
|
+
|
|
99
|
+
<script setup>
|
|
100
|
+
import {
|
|
101
|
+
onBeforeMount,
|
|
102
|
+
onBeforeUpdate,
|
|
103
|
+
ref,
|
|
104
|
+
useSlots,
|
|
105
|
+
computed,
|
|
106
|
+
watch,
|
|
107
|
+
nextTick,
|
|
108
|
+
} from 'vue';
|
|
109
|
+
import {
|
|
110
|
+
WarningFilled16,
|
|
111
|
+
WarningAltFilled16,
|
|
112
|
+
ViewOff16,
|
|
113
|
+
View16,
|
|
114
|
+
} from '@carbon/icons-vue';
|
|
115
|
+
import { carbonPrefix } from '../../global/settings';
|
|
116
|
+
import { useCvId, props as propsCvId } from '../../use/cvId';
|
|
117
|
+
import { useIsLight, props as propsTheme } from '../../use/cvTheme';
|
|
118
|
+
import { inputTypes } from './const';
|
|
119
|
+
|
|
120
|
+
const props = defineProps({
|
|
121
|
+
helperText: { type: String, default: undefined },
|
|
122
|
+
hideLabel: { type: Boolean, default: false },
|
|
123
|
+
invalidMessage: { type: String, default: undefined },
|
|
124
|
+
label: String,
|
|
125
|
+
modelValue: String,
|
|
126
|
+
passwordHideLabel: { type: String, default: 'Hide password' },
|
|
127
|
+
passwordShowLabel: { type: String, default: 'Show password' },
|
|
128
|
+
passwordVisible: { type: Boolean, default: undefined },
|
|
129
|
+
type: {
|
|
130
|
+
type: String,
|
|
131
|
+
default: 'text',
|
|
132
|
+
validator: value => inputTypes.has(value),
|
|
133
|
+
},
|
|
134
|
+
warnText: { type: String, default: undefined },
|
|
135
|
+
...propsCvId,
|
|
136
|
+
...propsTheme,
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
const cvId = useCvId(props);
|
|
140
|
+
|
|
141
|
+
// DOM Elements
|
|
142
|
+
const input = ref();
|
|
143
|
+
const slots = useSlots();
|
|
144
|
+
|
|
145
|
+
// Data
|
|
146
|
+
const isInvalid = ref(false);
|
|
147
|
+
const isWarn = ref(false);
|
|
148
|
+
const isHelper = ref(false);
|
|
149
|
+
const isLight = useIsLight(props);
|
|
150
|
+
const dataType = ref(props.type);
|
|
151
|
+
const dataPasswordVisible = ref(false);
|
|
152
|
+
|
|
153
|
+
// Computed Values
|
|
154
|
+
const isPassword = computed(() => props.type === 'password');
|
|
155
|
+
const isPasswordVisible = computed(
|
|
156
|
+
() => isPassword.value && dataPasswordVisible.value
|
|
157
|
+
);
|
|
158
|
+
const passwordHideShowLabel = computed(() =>
|
|
159
|
+
isPasswordVisible.value ? props.passwordHideLabel : props.passwordShowLabel
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
// Watchers
|
|
163
|
+
watch(
|
|
164
|
+
() => props.passwordVisible,
|
|
165
|
+
newValue => {
|
|
166
|
+
if (newValue !== dataPasswordVisible.value) {
|
|
167
|
+
togglePasswordVisibility();
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
);
|
|
171
|
+
watch(
|
|
172
|
+
() => props.type,
|
|
173
|
+
newValue => {
|
|
174
|
+
dataType.value = newValue;
|
|
175
|
+
}
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
// Methods
|
|
179
|
+
function togglePasswordVisibility() {
|
|
180
|
+
const currentValue = input.value.value;
|
|
181
|
+
dataPasswordVisible.value = !dataPasswordVisible.value;
|
|
182
|
+
dataType.value = dataPasswordVisible.value ? 'text' : 'password';
|
|
183
|
+
nextTick(() => {
|
|
184
|
+
input.value.value = currentValue;
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function checkSlots() {
|
|
189
|
+
// NOTE: slots is not reactive so needs to be managed on updated
|
|
190
|
+
isInvalid.value = !!(
|
|
191
|
+
props.invalidMessage?.length || slots['invalid-message']
|
|
192
|
+
);
|
|
193
|
+
isWarn.value =
|
|
194
|
+
!isInvalid.value && !!(props.warnText?.length || slots['warn-text']);
|
|
195
|
+
isHelper.value =
|
|
196
|
+
!isInvalid.value &&
|
|
197
|
+
!isWarn.value &&
|
|
198
|
+
!!(props.helperText?.length || slots['helper-text']);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Lifecycle Hooks
|
|
202
|
+
onBeforeMount(() => {
|
|
203
|
+
checkSlots();
|
|
204
|
+
// update initial state for dataPasswordVisible & dataType
|
|
205
|
+
if (isPassword.value && props.passwordVisible) {
|
|
206
|
+
dataPasswordVisible.value = true;
|
|
207
|
+
dataType.value = 'text';
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
onBeforeUpdate(checkSlots);
|
|
211
|
+
</script>
|
|
212
|
+
|
|
213
|
+
<script>
|
|
214
|
+
export default {
|
|
215
|
+
inheritAttrs: false,
|
|
216
|
+
};
|
|
217
|
+
</script>
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { Canvas, Meta, Story } from '@storybook/addon-docs';
|
|
2
|
+
import CvTile from './CvTile.vue';
|
|
3
|
+
import CvTileStandard from './CvTileStandard.vue';
|
|
4
|
+
import CvTileClickable from './CvTileClickable.vue';
|
|
5
|
+
import { sbCompPrefix } from '../../global/storybook-utils';
|
|
6
|
+
import { action } from '@storybook/addon-actions';
|
|
7
|
+
|
|
8
|
+
<Meta title={`${sbCompPrefix}/CvTile`} component={CvTile} />
|
|
9
|
+
|
|
10
|
+
export const Template = args => ({
|
|
11
|
+
// Components used in your story `template` are defined in the `components` object
|
|
12
|
+
components: {
|
|
13
|
+
CvTile,
|
|
14
|
+
CvTileStandard,
|
|
15
|
+
CvTileClickable,
|
|
16
|
+
},
|
|
17
|
+
// The story's `args` need to be mapped into the template through the `setup()` method
|
|
18
|
+
setup() {
|
|
19
|
+
return {
|
|
20
|
+
args: {
|
|
21
|
+
light: args.light,
|
|
22
|
+
kind: args.kind,
|
|
23
|
+
disabled: args.disabled,
|
|
24
|
+
expanded: args.expanded,
|
|
25
|
+
tileCollapsedLabel: args.tileCollapsedLabel,
|
|
26
|
+
tileExpandedLabel: args.tileExpandedLabel,
|
|
27
|
+
},
|
|
28
|
+
onChange: action('change'),
|
|
29
|
+
onExpanded: action('expanded'),
|
|
30
|
+
onClick: action('click'),
|
|
31
|
+
};
|
|
32
|
+
},
|
|
33
|
+
// And then the `args` are bound to your component with `v-bind="args"`
|
|
34
|
+
template: args.template,
|
|
35
|
+
});
|
|
36
|
+
const defaultTemplate = `<cv-tile v-bind='args'>Hello!</cv-tile>`;
|
|
37
|
+
const defaultCode = defaultTemplate.replace("v-bind='args'", '');
|
|
38
|
+
const expandableTemplate = `<cv-tile v-bind='args' kind="expandable" @expanded="onExpanded">Hello expandable!<template #below><h1>More Content</h1><p>Expanded</p></template></cv-tile>`;
|
|
39
|
+
const expandableCode = expandableTemplate.replace("v-bind='args'", '');
|
|
40
|
+
const clickableTemplate = `<cv-tile v-bind='args' kind="clickable" @click="onClick" to="{name: 'something'}">Hello clickable!</cv-tile>`;
|
|
41
|
+
const clickableCode = clickableTemplate.replace("v-bind='args'", '');
|
|
42
|
+
const selectableTemplate = `<cv-tile v-bind='args' kind="selectable" value="my-selection" @change="onChange">Hello selectable! </cv-tile>`;
|
|
43
|
+
const selectableCode = selectableTemplate.replace("v-bind='args'", '');
|
|
44
|
+
|
|
45
|
+
# CvTile
|
|
46
|
+
|
|
47
|
+
**Migration notes:**
|
|
48
|
+
|
|
49
|
+
- The `light` and '`theme` options continue to be supported but the boolean `light` is preferred.
|
|
50
|
+
- The expandable tile now emits a `expanded` event with a Boolean value.
|
|
51
|
+
|
|
52
|
+
<Canvas>
|
|
53
|
+
<Story
|
|
54
|
+
name="Default"
|
|
55
|
+
parameters={{
|
|
56
|
+
controls: {
|
|
57
|
+
exclude: [
|
|
58
|
+
'default',
|
|
59
|
+
'selected',
|
|
60
|
+
'template',
|
|
61
|
+
'data',
|
|
62
|
+
'kind',
|
|
63
|
+
'expanded',
|
|
64
|
+
'tileExpandedLabel',
|
|
65
|
+
'tileCollapsedLabel',
|
|
66
|
+
],
|
|
67
|
+
},
|
|
68
|
+
docs: { source: { code: defaultCode } },
|
|
69
|
+
}}
|
|
70
|
+
args={{
|
|
71
|
+
kind: '',
|
|
72
|
+
light: false,
|
|
73
|
+
disabled: false,
|
|
74
|
+
template: defaultTemplate,
|
|
75
|
+
}}
|
|
76
|
+
>
|
|
77
|
+
{Template.bind({})}
|
|
78
|
+
</Story>
|
|
79
|
+
</Canvas>
|
|
80
|
+
|
|
81
|
+
<Canvas>
|
|
82
|
+
<Story
|
|
83
|
+
name="Expandable"
|
|
84
|
+
parameters={{
|
|
85
|
+
controls: {
|
|
86
|
+
exclude: ['default', 'selected', 'template', 'data', 'kind', 'slots'],
|
|
87
|
+
},
|
|
88
|
+
docs: { source: { code: expandableCode } },
|
|
89
|
+
}}
|
|
90
|
+
args={{
|
|
91
|
+
light: false,
|
|
92
|
+
disabled: false,
|
|
93
|
+
template: expandableTemplate,
|
|
94
|
+
}}
|
|
95
|
+
>
|
|
96
|
+
{Template.bind({})}
|
|
97
|
+
</Story>
|
|
98
|
+
</Canvas>
|
|
99
|
+
|
|
100
|
+
<Canvas>
|
|
101
|
+
<Story
|
|
102
|
+
name="Clickable"
|
|
103
|
+
parameters={{
|
|
104
|
+
controls: {
|
|
105
|
+
exclude: [
|
|
106
|
+
'default',
|
|
107
|
+
'selected',
|
|
108
|
+
'template',
|
|
109
|
+
'data',
|
|
110
|
+
'kind',
|
|
111
|
+
'slots',
|
|
112
|
+
'expanded',
|
|
113
|
+
'tileExpandedLabel',
|
|
114
|
+
'tileCollapsedLabel',
|
|
115
|
+
],
|
|
116
|
+
},
|
|
117
|
+
docs: { source: { code: clickableCode } },
|
|
118
|
+
}}
|
|
119
|
+
args={{
|
|
120
|
+
light: false,
|
|
121
|
+
disabled: false,
|
|
122
|
+
template: clickableTemplate,
|
|
123
|
+
}}
|
|
124
|
+
>
|
|
125
|
+
{Template.bind({})}
|
|
126
|
+
</Story>
|
|
127
|
+
</Canvas>
|
|
128
|
+
|
|
129
|
+
<Canvas>
|
|
130
|
+
<Story
|
|
131
|
+
name="Selectable"
|
|
132
|
+
parameters={{
|
|
133
|
+
controls: {
|
|
134
|
+
exclude: [
|
|
135
|
+
'default',
|
|
136
|
+
'selected',
|
|
137
|
+
'template',
|
|
138
|
+
'data',
|
|
139
|
+
'kind',
|
|
140
|
+
'slots',
|
|
141
|
+
'expanded',
|
|
142
|
+
'tileExpandedLabel',
|
|
143
|
+
'tileCollapsedLabel',
|
|
144
|
+
],
|
|
145
|
+
},
|
|
146
|
+
docs: { source: { code: selectableCode } },
|
|
147
|
+
}}
|
|
148
|
+
args={{
|
|
149
|
+
light: false,
|
|
150
|
+
disabled: false,
|
|
151
|
+
template: selectableTemplate,
|
|
152
|
+
}}
|
|
153
|
+
>
|
|
154
|
+
{Template.bind({})}
|
|
155
|
+
</Story>
|
|
156
|
+
</Canvas>
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<component
|
|
3
|
+
:is="tagType"
|
|
4
|
+
:checked="checkProp('checked', selected)"
|
|
5
|
+
:expanded="checkProp('expanded', expanded)"
|
|
6
|
+
:tileCollapsedLabel="checkProp('tileCollapsedLabel', tileCollapsedLabel)"
|
|
7
|
+
:tileExpandedLabel="checkProp('tileCollapsedLabel', tileExpandedLabel)"
|
|
8
|
+
:class="[
|
|
9
|
+
`cv-tile ${carbonPrefix}--tile`,
|
|
10
|
+
{ [`${carbonPrefix}--tile--light`]: isLight },
|
|
11
|
+
]"
|
|
12
|
+
>
|
|
13
|
+
<template v-for="(_, name) in $slots" v-slot:[name]="slotData"
|
|
14
|
+
><slot :name="name" v-bind="slotData"
|
|
15
|
+
/></template>
|
|
16
|
+
</component>
|
|
17
|
+
</template>
|
|
18
|
+
|
|
19
|
+
<script setup>
|
|
20
|
+
import { computed } from 'vue';
|
|
21
|
+
import { carbonPrefix } from '../../global/settings';
|
|
22
|
+
import { props as propsTheme, useIsLight } from '../../use/cvTheme';
|
|
23
|
+
import CvTileStandard from './CvTileStandard.vue';
|
|
24
|
+
import CvTileClickable from './CvTileClickable.vue';
|
|
25
|
+
import CvTileSelectable from './CvTileSelectable.vue';
|
|
26
|
+
import CvTileExpandable from './CvTileExpandable.vue';
|
|
27
|
+
|
|
28
|
+
const props = defineProps({
|
|
29
|
+
expanded: Boolean,
|
|
30
|
+
selected: Boolean,
|
|
31
|
+
tileCollapsedLabel: { type: String, default: 'Tile collapsed' },
|
|
32
|
+
tileExpandedLabel: { type: String, default: 'Tile expanded' },
|
|
33
|
+
kind: {
|
|
34
|
+
type: String,
|
|
35
|
+
default: '',
|
|
36
|
+
validator: value =>
|
|
37
|
+
['clickable', 'expandable', 'selectable', 'standard', ''].includes(value),
|
|
38
|
+
},
|
|
39
|
+
...propsTheme,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const tagType = computed(() => {
|
|
43
|
+
switch (props.kind) {
|
|
44
|
+
case 'clickable':
|
|
45
|
+
return CvTileClickable;
|
|
46
|
+
case 'selectable':
|
|
47
|
+
return CvTileSelectable;
|
|
48
|
+
case 'expandable':
|
|
49
|
+
return CvTileExpandable;
|
|
50
|
+
default:
|
|
51
|
+
return CvTileStandard;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
const isLight = useIsLight(props);
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* If the prop is defined on the tagType pass it along otherwise, discard it.
|
|
58
|
+
* @param {string} prop
|
|
59
|
+
* @param {any} value
|
|
60
|
+
* @returns {*|undefined}
|
|
61
|
+
*/
|
|
62
|
+
function checkProp(prop, value) {
|
|
63
|
+
return prop in (tagType.value.props || {}) ? value : undefined;
|
|
64
|
+
}
|
|
65
|
+
</script>
|
|
66
|
+
|
|
67
|
+
<style scoped></style>
|