@carbon/vue 3.0.6-alpha.0 → 3.0.7-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.
Files changed (49) hide show
  1. package/dist/carbon-vue-3.common.js +11880 -8135
  2. package/dist/carbon-vue-3.common.js.map +1 -1
  3. package/dist/carbon-vue-3.umd.js +11880 -8135
  4. package/dist/carbon-vue-3.umd.js.map +1 -1
  5. package/dist/carbon-vue-3.umd.min.js +4 -4
  6. package/dist/carbon-vue-3.umd.min.js.map +1 -1
  7. package/package.json +4 -4
  8. package/src/components/CvAccordion/CvAccordion.stories.js +1 -0
  9. package/src/components/CvButton/CvButton.stories.js +3 -3
  10. package/src/components/CvButton/CvButtonSkeleton.stories.js +79 -0
  11. package/src/components/CvButton/CvButtonSkeleton.vue +19 -0
  12. package/src/components/CvButton/index.js +8 -1
  13. package/src/components/CvDatePicker/CvDatePicker.vue +1 -1
  14. package/src/components/CvDropdown/CvDropdown.stories.mdx +407 -0
  15. package/src/components/CvDropdown/CvDropdown.vue +418 -0
  16. package/src/components/CvDropdown/CvDropdownItem.vue +86 -0
  17. package/src/components/CvDropdown/CvDropdownSkeleton.vue +17 -0
  18. package/src/components/CvDropdown/index.js +5 -0
  19. package/src/components/CvForm/CvFormGroup.vue +1 -1
  20. package/src/components/CvInlineLoading/CvInlineLoading.stories.mdx +87 -0
  21. package/src/components/CvInlineLoading/CvInlineLoading.vue +144 -0
  22. package/src/components/CvInlineLoading/consts.js +9 -0
  23. package/src/components/CvInlineLoading/index.js +4 -0
  24. package/src/components/CvModal/CvModal.stories.mdx +4 -2
  25. package/src/components/CvModal/CvModal.vue +3 -5
  26. package/src/components/CvMultiSelect/CvMultiSelect.stories.mdx +333 -0
  27. package/src/components/CvMultiSelect/CvMultiSelect.vue +705 -0
  28. package/src/components/CvMultiSelect/consts.js +16 -0
  29. package/src/components/CvMultiSelect/index.js +3 -0
  30. package/src/components/CvNumberInput/CvNumberInput.stories.js +265 -0
  31. package/src/components/CvNumberInput/CvNumberInput.vue +227 -0
  32. package/src/components/CvNumberInput/CvNumberInputSkeleton.stories.js +30 -0
  33. package/src/components/CvNumberInput/CvNumberInputSkeleton.vue +10 -0
  34. package/src/components/CvNumberInput/StorybookGroupConst.js +1 -0
  35. package/src/components/CvNumberInput/__tests__/__snapshots__/CvNumberInput.spec.js.snap +21 -0
  36. package/src/components/CvNumberInput/index.js +5 -0
  37. package/src/components/CvTabs/CvTab.vue +77 -0
  38. package/src/components/CvTabs/CvTabs.stories.mdx +175 -0
  39. package/src/components/CvTabs/CvTabs.vue +406 -0
  40. package/src/components/CvTabs/CvTabsSkeleton.vue +24 -0
  41. package/src/components/CvTabs/_SbContainer.vue +22 -0
  42. package/src/components/CvTabs/index.js +5 -0
  43. package/src/components/CvToggle/CvToggle-Skeleton.vue +29 -0
  44. package/src/components/CvToggle/CvToggle.stories.js +232 -0
  45. package/src/components/CvToggle/CvToggle.vue +70 -0
  46. package/src/components/CvToggle/__tests__/__snapshots__/CvToggle.spec.js.snap +7 -0
  47. package/src/components/CvToggle/index.js +4 -0
  48. package/src/global/storybook-utils/story-source-code.js +1 -0
  49. package/src/use/cvInput.js +34 -0
@@ -0,0 +1,144 @@
1
+ <template>
2
+ <div
3
+ data-inline-loading
4
+ :class="`${carbonPrefix}--inline-loading`"
5
+ role="alert"
6
+ aria-live="assertive"
7
+ >
8
+ <div
9
+ :class="[
10
+ `${carbonPrefix}--inline-loading__animation`,
11
+ { [`${carbonPrefix}--loading--stop`]: internalState === STATES.ENDING },
12
+ ]"
13
+ @animationend="onLoadingEnd"
14
+ >
15
+ <div
16
+ v-show="internalActive"
17
+ :class="`${carbonPrefix}--loading ${carbonPrefix}--loading--small`"
18
+ >
19
+ <cv-loading
20
+ :class="`${carbonPrefix}--inline-loading__animation`"
21
+ :description="description"
22
+ :active="undefined"
23
+ :small="true"
24
+ />
25
+ </div>
26
+ <checkmark-filled16
27
+ v-if="internalState === STATES.LOADED"
28
+ :class="`${carbonPrefix}--inline-loading__checkmark-container`"
29
+ />
30
+ <error-filled16
31
+ v-if="internalState === STATES.ERROR"
32
+ :class="`${carbonPrefix}--inline-loading--error`"
33
+ />
34
+ </div>
35
+ <p :class="`${carbonPrefix}--inline-loading__text`">{{ stateText }}</p>
36
+ </div>
37
+ </template>
38
+
39
+ <script setup>
40
+ import { STATES } from './consts';
41
+ import ErrorFilled16 from '@carbon/icons-vue/lib/error--filled/16';
42
+ import CheckmarkFilled16 from '@carbon/icons-vue/lib/checkmark--filled/16';
43
+ import { carbonPrefix } from '../../global/settings';
44
+ import CvLoading from '../CvLoading/CvLoading.vue';
45
+ import { computed, ref, watch } from 'vue';
46
+
47
+ const props = defineProps({
48
+ /**
49
+ * Deprecated: Please use state property
50
+ * @deprecated
51
+ */
52
+ active: {
53
+ type: Boolean,
54
+ default: undefined,
55
+ deprecated: true,
56
+ validator: val => {
57
+ if (val !== undefined && process.env.NODE_ENV === 'development') {
58
+ console.warn(
59
+ 'CvInlineLoading: active prop deprecated in favour of state prop'
60
+ );
61
+ }
62
+ return true;
63
+ },
64
+ },
65
+ /**
66
+ * Specify the description for the inline loading text
67
+ */
68
+ description: { type: String, default: 'Loading' },
69
+ /**
70
+ * Specify the text to show while the loading is ending (state: 'ending')
71
+ */
72
+ endingText: { type: String, default: 'Load ending...' },
73
+ /**
74
+ * Specify the text to show for the error state (state: 'error')
75
+ */
76
+ errorText: { type: String, default: 'Loading data failed.' },
77
+ /**
78
+ * Specify the text to show while loading (state: 'loading')
79
+ */
80
+ loadingText: { type: String, default: 'Loading data...' },
81
+ /**
82
+ * Specify the text to show while loading (state: 'loaded')
83
+ */
84
+ loadedText: { type: String, default: 'Data loaded.' },
85
+ /**
86
+ * Specify the loading status
87
+ * @values ['loading','ending','loaded','error']
88
+ */
89
+ state: {
90
+ type: String,
91
+ default: STATES.LOADING,
92
+ required: true,
93
+ validator: val => {
94
+ if (Object.values(STATES).includes(val)) {
95
+ return true;
96
+ } else {
97
+ console.error(
98
+ `CvInlineLoading: Valid states are ${Object.values(STATES)}`
99
+ );
100
+ return false;
101
+ }
102
+ },
103
+ },
104
+ });
105
+ const internalState = ref(stateFromProps());
106
+ function stateFromProps() {
107
+ if (props.state.includes(':')) {
108
+ return props.state.split(':')[0];
109
+ } else {
110
+ return props.state;
111
+ }
112
+ }
113
+ watch(
114
+ () => props.state,
115
+ () => {
116
+ internalState.value = stateFromProps();
117
+ }
118
+ );
119
+ function onLoadingEnd(ev) {
120
+ if (ev.animationName === 'rotate-end-p2' && props.state.includes(':')) {
121
+ internalState.value = props.state.split(':')[1];
122
+ }
123
+ }
124
+ const internalActive = computed(() => {
125
+ if (props.active !== undefined) {
126
+ return props.active;
127
+ } else {
128
+ return [STATES.LOADING, STATES.ENDING].includes(internalState.value);
129
+ }
130
+ });
131
+
132
+ const stateText = computed(() => {
133
+ switch (internalState.value) {
134
+ case STATES.LOADED:
135
+ return props.loadedText;
136
+ case STATES.ERROR:
137
+ return props.errorText;
138
+ case STATES.ENDING:
139
+ return props.endingText;
140
+ default:
141
+ return props.loadingText;
142
+ }
143
+ });
144
+ </script>
@@ -0,0 +1,9 @@
1
+ const STATES = {
2
+ LOADED: 'loaded',
3
+ ERROR: 'error',
4
+ LOADING: 'loading',
5
+ ENDING: 'ending',
6
+ ENDING_LOADED: 'ending:loaded',
7
+ ENDING_ERROR: 'ending:error',
8
+ };
9
+ export { STATES };
@@ -0,0 +1,4 @@
1
+ import CvInlineLoading from './CvInlineLoading.vue';
2
+ import { STATES } from './consts';
3
+
4
+ export { CvInlineLoading, STATES };
@@ -3,8 +3,6 @@ import { sbCompPrefix } from '../../global/storybook-utils';
3
3
  import CvModal from './CvModal.vue';
4
4
  import { action } from '@storybook/addon-actions';
5
5
  import { nextTick, ref } from 'vue';
6
- const visible = ref(false);
7
- const visible3btn = ref(false);
8
6
 
9
7
  <Meta title={`${sbCompPrefix}/CvModal`} component={CvModal} />
10
8
 
@@ -15,6 +13,8 @@ export const Template = args => ({
15
13
  },
16
14
  // The story's `args` need to be mapped into the template through the `setup()` method
17
15
  setup() {
16
+ const visible = ref(false);
17
+ const visible3btn = ref(false);
18
18
  return {
19
19
  ...args,
20
20
  props: args.props,
@@ -32,12 +32,14 @@ export const Template = args => ({
32
32
  primaryButtonDisabled: args.primaryButtonDisabled,
33
33
  disableTeleport: args.disableTeleport,
34
34
  show: () => {
35
+ if (visible3btn.value) visible3btn.value = false;
35
36
  if (visible.value) visible.value = false;
36
37
  nextTick(() => {
37
38
  visible.value = true;
38
39
  }).catch(() => console.warn('cannot show'));
39
40
  },
40
41
  show3btn: () => {
42
+ if (visible.value) visible.value = false;
41
43
  if (visible3btn.value) visible3btn.value = false;
42
44
  nextTick(() => {
43
45
  visible3btn.value = true;
@@ -262,7 +262,7 @@ function onShown() {
262
262
  } else {
263
263
  focusBeforeContent();
264
264
  }
265
- emit('modal-shown');
265
+ emit('modal-shown', uid.value);
266
266
 
267
267
  // check to see if content scrollable
268
268
  data.scrollable = content.value?.scrollHeight > content.value?.clientHeight;
@@ -306,10 +306,10 @@ function hide() {
306
306
 
307
307
  if (dataVisible.value) {
308
308
  el.value?.addEventListener('transitionend', afterHide);
309
+ emit('modal-hidden', uid.value);
309
310
  }
310
311
 
311
312
  dataVisible.value = false;
312
- emit('modal-hidden');
313
313
  }
314
314
  function afterHide(event) {
315
315
  if (event.propertyName === 'opacity') {
@@ -396,8 +396,6 @@ function onOtherBtnClick(ev) {
396
396
  onFooterButtonClick('other-btn-click', ev);
397
397
  }
398
398
  onBeforeUnmount(() => {
399
- if (dataVisible.value) {
400
- emit('after-modal-hidden');
401
- }
399
+ if (dataVisible.value) hide();
402
400
  });
403
401
  </script>
@@ -0,0 +1,333 @@
1
+ import { Canvas, Meta, Story } from '@storybook/addon-docs';
2
+ import CvMultiSelect from './CvMultiSelect.vue';
3
+ import { tagKinds } from '../CvTag/consts';
4
+ import { sbCompPrefix } from '../../global/storybook-utils';
5
+ import { DIRECTIONS, selectionFeedbackOptions } from './consts';
6
+ import { action } from '@storybook/addon-actions';
7
+ import { ref } from 'vue';
8
+ const myValue = ref(['iran_deckard']);
9
+ const pkdCharacters = [
10
+ 'Rick Deckard',
11
+ 'Garland',
12
+ 'Rachael Rosen',
13
+ 'Roy Batty',
14
+ 'Harry Bryant',
15
+ 'Hannibal Chew',
16
+ 'Dave Holden',
17
+ 'Leon Kowalski',
18
+ 'Taffey Lewis',
19
+ 'Pris Stratton',
20
+ 'J.F. Sebastian',
21
+ 'Dr. Eldon Rosen',
22
+ 'Zhora Salome',
23
+ 'John "J.R." Isidore',
24
+ 'Iran Deckard',
25
+ 'Wilbur Mercer',
26
+ 'Buster Friendly',
27
+ 'Phil Resch',
28
+ ];
29
+ const pkdOptions = pkdCharacters.map(item => {
30
+ const nameVal = item.replace(/\W+/g, '_').toLowerCase();
31
+ return {
32
+ name: nameVal,
33
+ label: item,
34
+ value: nameVal,
35
+ disabled: false,
36
+ };
37
+ });
38
+ const pkdValues = pkdOptions.map(item => item.value);
39
+
40
+ <Meta title={`${sbCompPrefix}/CvMultiSelect`} component={CvMultiSelect} />
41
+
42
+ export const Template = args => ({
43
+ // Components used in your story `template` are defined in the `components` object
44
+ components: {
45
+ CvMultiSelect,
46
+ },
47
+ // The story's `args` need to be mapped into the template through the `setup()` method
48
+ setup() {
49
+ return {
50
+ options: args.options,
51
+ autoFilter: args.autoFilter,
52
+ autoHighlight: args.autoHighlight,
53
+ disabled: args.disabled,
54
+ filterTagKind: args.filterTagKind,
55
+ inline: args.inline,
56
+ invalidMessage: args.invalidMessage,
57
+ helperText: args.helperText,
58
+ title: args.title,
59
+ label: args.label,
60
+ highlight: args.highlight,
61
+ value: args.value,
62
+ selectionFeedback: args.selectionFeedback,
63
+ filterable: args.filterable,
64
+ light: args.light,
65
+ direction: args.direction,
66
+ warningMessage: args.warningMessage,
67
+ slotInvalidText: args.slotInvalidText,
68
+ slotWarningText: args.slotWarningText,
69
+ slotHelperText: args.slotHelperText,
70
+ myValue: myValue,
71
+ onChange: action('change'),
72
+ onFilter: action('filter'),
73
+ onVmodel: action('update:value'),
74
+ };
75
+ },
76
+ template: args.template,
77
+ });
78
+ const defaultTemplate = `
79
+ <div :style="{width: '19rem', paddingTop: direction==='top' ? '90px' : undefined}">
80
+ <cv-multi-select
81
+ :autoFilter="autoFilter"
82
+ :autoHighlight="autoHighlight"
83
+ :direction="direction"
84
+ :disabled="disabled"
85
+ :filterable="filterable"
86
+ :filterTagKind="filterTagKind"
87
+ :helperText="helperText"
88
+ :highlight="highlight"
89
+ :inline="inline"
90
+ :invalidMessage="invalidMessage"
91
+ :label="label"
92
+ :light="light"
93
+ :options="options"
94
+ :selectionFeedback="selectionFeedback"
95
+ :title="title"
96
+ :value="value"
97
+ :warningMessage="warningMessage"
98
+ @change="onChange"
99
+ @filter="onFilter"
100
+ >
101
+ </cv-multi-select>
102
+ </div>
103
+ `;
104
+ const slotsTemplate = `
105
+ <div :style="{width: '19rem'}">
106
+ <cv-multi-select
107
+ :label="label"
108
+ :options="options"
109
+ :title="title"
110
+ @change="onChange"
111
+ @filter="onFilter"
112
+ >
113
+ <template v-if="slotInvalidText" v-slot:invalid-message>That is <span style="font-weight:900">NOT</span> a replicant</template>
114
+ <template v-if="slotWarningText" v-slot:warning-message>Are you sure that is a <span style="font-variant-caps: petite-caps;">Replicant</span></template>
115
+ <template v-if="slotHelperText" v-slot:helper-text>Help Rick Deckard <span style="font-variant: small-caps;">“retire”</span> rogue androids</template>
116
+ </cv-multi-select>
117
+ </div>
118
+ `;
119
+ const vModelTemplate = `
120
+ <div :style="{width: '19rem'}">
121
+ <div>current values: {{myValue}} </div>
122
+ <cv-multi-select
123
+ :label="label"
124
+ :options="options"
125
+ :title="title"
126
+ v-model:value="myValue"
127
+ @change="onChange"
128
+ @filter="onFilter"
129
+ >
130
+ </cv-multi-select>
131
+ <div style="margin-top:2rem">
132
+ <div>v-model:value</div>
133
+ <select name="cars" id="cars" v-model="myValue" multiple>
134
+ <option v-for="opt in options" :key="opt.value" :value="opt.value">{{opt.value}}</option>
135
+ </select>
136
+ </div>
137
+ </div>
138
+ `;
139
+
140
+ # CvMultiSelect
141
+
142
+ Migration notes:
143
+
144
+ - Added the `direction` option to match Carbon React. Note that in the similar dropdown component,
145
+ this property is named `up` and uses a boolean value. If you prefer the boolean here,
146
+ let us know in the Slack channel.
147
+ - Added the `warningMessage` option to match Carbon React
148
+ - Setting `autoFilter` to true now implies `filterable`. Previous versions required `filterable` to
149
+ be explicitly set to `true` for `autoFilter` to work properly.
150
+ - The `v-model` is different in Vue 3 than Vue 2.If you specify it you will see a error deprecation message in the log.
151
+ Please use `v-model:value=something` instead.
152
+
153
+ <Canvas>
154
+ <Story
155
+ name="Default"
156
+ parameters={{
157
+ controls: {
158
+ exclude: [
159
+ 'change',
160
+ 'filter',
161
+ 'helper-text',
162
+ 'invalid-message',
163
+ 'modelValue',
164
+ 'template',
165
+ 'update:modelValue',
166
+ 'update:value',
167
+ 'warning-message',
168
+ ],
169
+ },
170
+ docs: { source: { code: defaultTemplate } },
171
+ }}
172
+ args={{
173
+ template: defaultTemplate,
174
+ options: pkdOptions,
175
+ light: false,
176
+ label: 'Choose replicants',
177
+ helperText: 'Do Androids Dream of Electric Sheep?',
178
+ title: 'Characters',
179
+ }}
180
+ argTypes={{
181
+ filterTagKind: {
182
+ control: 'select',
183
+ default: 'high-contrast',
184
+ options: tagKinds,
185
+ },
186
+ highlight: {
187
+ control: 'select',
188
+ default: undefined,
189
+ options: ['', ...pkdValues],
190
+ },
191
+ selectionFeedback: {
192
+ control: 'select',
193
+ default: 'top-after-reopen',
194
+ options: selectionFeedbackOptions,
195
+ table: { defaultValue: { summary: 'top-after-reopen' } },
196
+ },
197
+ light: {
198
+ description: '`true` to use the light version.',
199
+ table: { category: 'props', defaultValue: { summary: false } },
200
+ },
201
+ direction: {
202
+ control: 'select',
203
+ default: 'bottom',
204
+ options: DIRECTIONS,
205
+ table: { defaultValue: { summary: 'bottom' } },
206
+ },
207
+ options: {
208
+ description: `options in the form [{ label: '', value: '', name: '', disabled: false}]`,
209
+ control: 'inline-radio',
210
+ options: [],
211
+ },
212
+ value: {
213
+ control: 'multi-select',
214
+ options: pkdValues,
215
+ },
216
+ }}
217
+ >
218
+ {Template.bind({})}
219
+ </Story>
220
+ </Canvas>
221
+
222
+ # Use slots with helper, invalid, & warning text
223
+
224
+ <Canvas>
225
+ <Story
226
+ name="Slots"
227
+ parameters={{
228
+ controls: {
229
+ exclude: [
230
+ 'autoFilter',
231
+ 'autoHighlight',
232
+ 'change',
233
+ 'direction',
234
+ 'disabled',
235
+ 'filter',
236
+ 'filterTagKind',
237
+ 'filterable',
238
+ 'helper-text',
239
+ 'helperText',
240
+ 'highlight',
241
+ 'inline',
242
+ 'invalid-message',
243
+ 'invalidMessage',
244
+ 'light',
245
+ 'modelValue',
246
+ 'options',
247
+ 'selectionFeedback',
248
+ 'template',
249
+ 'update:modelValue',
250
+ 'update:value',
251
+ 'value',
252
+ 'warning-message',
253
+ 'warningMessage',
254
+ ],
255
+ },
256
+ docs: { source: { code: slotsTemplate } },
257
+ }}
258
+ args={{
259
+ template: slotsTemplate,
260
+ options: pkdOptions,
261
+ label: 'Choose replicants',
262
+ title: 'Characters',
263
+ slotInvalidText: false,
264
+ slotWarningText: false,
265
+ slotHelperText: true,
266
+ }}
267
+ argTypes={{}}
268
+ >
269
+ {Template.bind({})}
270
+ </Story>
271
+ </Canvas>
272
+
273
+ # v-model
274
+
275
+ Note: Specifying `v-model="something"` will not work. Use `v-model:value=something` instead.
276
+
277
+ <Canvas>
278
+ <Story
279
+ name="v-model"
280
+ parameters={{
281
+ controls: {
282
+ exclude: [
283
+ 'autoFilter',
284
+ 'autoHighlight',
285
+ 'change',
286
+ 'direction',
287
+ 'disabled',
288
+ 'filter',
289
+ 'filterTagKind',
290
+ 'filterable',
291
+ 'helper-text',
292
+ 'helperText',
293
+ 'highlight',
294
+ 'inline',
295
+ 'invalid-message',
296
+ 'invalidMessage',
297
+ 'light',
298
+ 'modelValue',
299
+ 'options',
300
+ 'selectionFeedback',
301
+ 'template',
302
+ 'update:modelValue',
303
+ 'update:value',
304
+ 'value',
305
+ 'warning-message',
306
+ 'warningMessage',
307
+ ],
308
+ },
309
+ docs: { source: { code: vModelTemplate } },
310
+ }}
311
+ args={{
312
+ template: vModelTemplate,
313
+ options: pkdOptions,
314
+ light: false,
315
+ label: 'Choose replicants',
316
+ helperText: 'Do Androids Dream of Electric Sheep?',
317
+ title: 'Characters',
318
+ }}
319
+ argTypes={{
320
+ options: {
321
+ description: `options in the form [{ label: '', value: '', name: '', disabled: false}]`,
322
+ control: 'inline-radio',
323
+ options: [],
324
+ },
325
+ value: {
326
+ control: 'multi-select',
327
+ options: pkdValues,
328
+ },
329
+ }}
330
+ >
331
+ {Template.bind({})}
332
+ </Story>
333
+ </Canvas>