@carbon/vue 3.0.6-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.
Files changed (109) hide show
  1. package/README.md +7 -0
  2. package/dist/carbon-vue-3.common.js +16111 -9105
  3. package/dist/carbon-vue-3.common.js.map +1 -1
  4. package/dist/carbon-vue-3.umd.js +16111 -9105
  5. package/dist/carbon-vue-3.umd.js.map +1 -1
  6. package/dist/carbon-vue-3.umd.min.js +4 -4
  7. package/dist/carbon-vue-3.umd.min.js.map +1 -1
  8. package/package.json +9 -6
  9. package/src/components/CvAccordion/CvAccordion.stories.js +1 -0
  10. package/src/components/CvButton/CvButton.stories.js +3 -3
  11. package/src/components/CvButton/CvButtonSkeleton.stories.js +79 -0
  12. package/src/components/CvButton/CvButtonSkeleton.vue +19 -0
  13. package/src/components/CvButton/index.js +8 -1
  14. package/src/components/CvCheckbox/CvCheckbox.stories.js +18 -7
  15. package/src/components/CvCheckbox/CvCheckbox.vue +19 -3
  16. package/src/components/CvCheckbox/CvCheckboxSkeleton.vue +16 -0
  17. package/src/components/CvCheckbox/__tests__/__snapshots__/CvCheckboxSkeleton.spec.js.snap +3 -0
  18. package/src/components/CvCheckbox/index.js +2 -1
  19. package/src/components/CvDatePicker/CvDatePicker.vue +1 -1
  20. package/src/components/CvDropdown/CvDropdown.stories.mdx +407 -0
  21. package/src/components/CvDropdown/CvDropdown.vue +416 -0
  22. package/src/components/CvDropdown/CvDropdownItem.vue +86 -0
  23. package/src/components/CvDropdown/CvDropdownSkeleton.vue +17 -0
  24. package/src/components/CvDropdown/index.js +5 -0
  25. package/src/components/CvFileUploader/CvFileUploader.stories.mdx +333 -0
  26. package/src/components/CvFileUploader/CvFileUploader.vue +286 -0
  27. package/src/components/CvFileUploader/CvFileUploaderItem.vue +92 -0
  28. package/src/components/CvFileUploader/CvFileUploaderSkeleton.vue +16 -0
  29. package/src/components/CvFileUploader/const.js +10 -0
  30. package/src/components/CvFileUploader/index.js +5 -0
  31. package/src/components/CvForm/CvFormGroup.vue +1 -1
  32. package/src/components/CvInlineLoading/CvInlineLoading.stories.mdx +87 -0
  33. package/src/components/CvInlineLoading/CvInlineLoading.vue +144 -0
  34. package/src/components/CvInlineLoading/consts.js +9 -0
  35. package/src/components/CvInlineLoading/index.js +4 -0
  36. package/src/components/CvModal/CvModal.stories.mdx +4 -2
  37. package/src/components/CvModal/CvModal.vue +3 -5
  38. package/src/components/CvMultiSelect/CvMultiSelect.stories.mdx +333 -0
  39. package/src/components/CvMultiSelect/CvMultiSelect.vue +705 -0
  40. package/src/components/CvMultiSelect/consts.js +16 -0
  41. package/src/components/CvMultiSelect/index.js +3 -0
  42. package/src/components/CvNumberInput/CvNumberInput.stories.js +265 -0
  43. package/src/components/CvNumberInput/CvNumberInput.vue +227 -0
  44. package/src/components/CvNumberInput/CvNumberInputSkeleton.stories.js +30 -0
  45. package/src/components/CvNumberInput/CvNumberInputSkeleton.vue +10 -0
  46. package/src/components/CvNumberInput/StorybookGroupConst.js +1 -0
  47. package/src/components/CvNumberInput/__tests__/__snapshots__/CvNumberInput.spec.js.snap +21 -0
  48. package/src/components/CvNumberInput/index.js +5 -0
  49. package/src/components/CvProgress/CvProgress.stories.mdx +202 -0
  50. package/src/components/CvProgress/CvProgress.vue +78 -0
  51. package/src/components/CvProgress/CvProgressStep.vue +124 -0
  52. package/src/components/CvProgress/index.js +4 -0
  53. package/src/components/CvRadioButton/CvRadioButton.stories.js +166 -0
  54. package/src/components/CvRadioButton/CvRadioButton.vue +57 -0
  55. package/src/components/CvRadioButton/CvRadioGroup.vue +27 -0
  56. package/src/components/CvRadioButton/__tests__/__snapshots__/CvRadioButton.spec.js.snap +27 -0
  57. package/src/components/CvRadioButton/index.js +6 -0
  58. package/src/components/CvSearch/CvSearch.stories.mdx +168 -0
  59. package/src/components/CvSearch/CvSearch.vue +250 -0
  60. package/src/components/CvSearch/index.js +3 -0
  61. package/src/components/CvSelect/CvSelect.vue +27 -6
  62. package/src/components/CvSlider/CvSlider.stories.js +166 -0
  63. package/src/components/CvSlider/CvSlider.vue +324 -0
  64. package/src/components/CvSlider/CvSliderSkeleton.stories.js +26 -0
  65. package/src/components/CvSlider/CvSliderSkeleton.vue +18 -0
  66. package/src/components/CvSlider/__tests__/__snapshots__/CvSlider.spec.js.snap +13 -0
  67. package/src/components/CvSlider/__tests__/__snapshots__/CvSliderSkeleton.spec.js.snap +13 -0
  68. package/src/components/CvSlider/index.js +5 -0
  69. package/src/components/CvSlider/sbSliderPrefix.js +2 -0
  70. package/src/components/CvTabs/CvTab.vue +77 -0
  71. package/src/components/CvTabs/CvTabs.stories.mdx +175 -0
  72. package/src/components/CvTabs/CvTabs.vue +406 -0
  73. package/src/components/CvTabs/CvTabsSkeleton.vue +24 -0
  74. package/src/components/CvTabs/_SbContainer.vue +22 -0
  75. package/src/components/CvTabs/index.js +5 -0
  76. package/src/components/CvTextArea/CvTextArea.stories.js +2 -2
  77. package/src/components/CvTextArea/CvTextAreaSkeleton.stories.js +29 -0
  78. package/src/components/CvTextArea/CvTextAreaSkeleton.vue +10 -0
  79. package/src/components/CvTextArea/StorybookGroupConst.js +1 -0
  80. package/src/components/CvTextArea/__tests__/__snapshots__/CvTextAreaSkeleton.spec.js.snap +7 -0
  81. package/src/components/CvTextArea/index.js +2 -1
  82. package/src/components/CvTimePicker/CvTimePicker.stories.mdx +325 -0
  83. package/src/components/CvTimePicker/CvTimePicker.vue +217 -0
  84. package/src/components/CvTimePicker/index.js +21 -0
  85. package/src/components/CvToggle/CvToggle-Skeleton.vue +44 -0
  86. package/src/components/CvToggle/CvToggle.stories.js +249 -0
  87. package/src/components/CvToggle/CvToggle.vue +87 -0
  88. package/src/components/CvToggle/__tests__/__snapshots__/CvToggle.spec.js.snap +7 -0
  89. package/src/components/CvToggle/index.js +4 -0
  90. package/src/components/CvTooltip/CvDefinitionTooltip.stories.js +80 -0
  91. package/src/components/CvTooltip/CvDefinitionTooltip.vue +61 -0
  92. package/src/components/CvTooltip/CvInteractiveTooltip.stories.js +90 -0
  93. package/src/components/CvTooltip/CvInteractiveTooltip.vue +267 -0
  94. package/src/components/CvTooltip/CvTooltip.stories.js +128 -0
  95. package/src/components/CvTooltip/CvTooltip.vue +44 -0
  96. package/src/components/CvTooltip/__tests__/__snapshots__/CvTooltip.spec.js.snap +525 -0
  97. package/src/components/CvTooltip/consts.js +15 -0
  98. package/src/components/CvTooltip/index.js +6 -0
  99. package/src/components/CvTooltip/sbTooltipPrefix.js +2 -0
  100. package/src/components/CvUIShell/CvSideNav.vue +10 -1
  101. package/src/components/CvUIShell/CvUIShell.stories.mdx +116 -50
  102. package/src/global/storybook-utils/story-source-code.js +1 -0
  103. package/src/index.d.ts +6 -0
  104. package/src/index.js +11 -0
  105. package/src/use/cvCheck.js +3 -0
  106. package/src/use/cvInput.js +34 -0
  107. package/src/use/index.js +2 -0
  108. package/src/use/useMethods.js +18 -0
  109. package/src/use/useRadio.js +25 -0
@@ -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>
@@ -0,0 +1,250 @@
1
+ <template>
2
+ <component
3
+ :is="formItem ? 'div' : CvEmpty"
4
+ :class="`cv-search ${carbonPrefix}--form-item`"
5
+ >
6
+ <div
7
+ :aria-label="internalAriaLabel"
8
+ :aria-labelledby="internalAriaLabelBy"
9
+ :class="[
10
+ `${carbonPrefix}--search`,
11
+ `${carbonPrefix}--search--${size}`,
12
+ {
13
+ [`${carbonPrefix}--search--expandable`]: expandable,
14
+ [`${carbonPrefix}--search--expanded`]: isExpanded,
15
+ [`${carbonPrefix}--search--disabled`]: disabled,
16
+ [`${carbonPrefix}--search--light`]: isLight,
17
+ 'cv-search': !formItem,
18
+ },
19
+ ]"
20
+ role="search"
21
+ ref="elSearch"
22
+ >
23
+ <div
24
+ :class="`${carbonPrefix}--search-magnifier`"
25
+ @click="toggleActive(true)"
26
+ @blur="checkFocus"
27
+ >
28
+ <search-icon :class="`${carbonPrefix}--search-magnifier-icon`" />
29
+ </div>
30
+
31
+ <label v-show="label" :for="uid" :class="`${carbonPrefix}--label`">{{
32
+ label
33
+ }}</label>
34
+
35
+ <input
36
+ role="searchbox"
37
+ :id="uid"
38
+ :class="`${carbonPrefix}--search-input`"
39
+ v-bind="$attrs"
40
+ v-model="internalSearchText"
41
+ @input="onInput"
42
+ type="text"
43
+ ref="elInput"
44
+ :placeholder="placeholder"
45
+ :aria-labelledby="uid"
46
+ @blur="checkFocus"
47
+ @click="toggleActive"
48
+ @keydown.esc="onClearClick"
49
+ :disabled="disabled ? 'true' : undefined"
50
+ />
51
+
52
+ <button
53
+ type="button"
54
+ :class="[
55
+ `${carbonPrefix}--search-close`,
56
+ { [`${carbonPrefix}--search-close--hidden`]: !clearVisible },
57
+ ]"
58
+ :title="clearAriaLabel"
59
+ :aria-label="clearAriaLabel"
60
+ @click="onClearClick"
61
+ >
62
+ <close-icon />
63
+ </button>
64
+ </div>
65
+ </component>
66
+ </template>
67
+
68
+ <script setup>
69
+ import { carbonPrefix } from '../../global/settings';
70
+ import { useIsLight, props as propsTheme } from '../../use/cvTheme';
71
+ import { useCvId, props as propsCvId } from '../../use/cvId';
72
+ import SearchIcon from '@carbon/icons-vue/es/search/16';
73
+ import CloseIcon from '@carbon/icons-vue/es/close/16';
74
+ import { computed, ref, watch } from 'vue';
75
+ import { SEARCH_SIZES } from '.';
76
+ import CvEmpty from '../CvEmpty/_CvEmpty.vue';
77
+
78
+ defineOptions({
79
+ inheritAttrs: false,
80
+ });
81
+
82
+ const props = defineProps({
83
+ ariaLabel: { type: String, default: 'search input' },
84
+ /**
85
+ * Specify a label to be read by screen readers on the "close" button
86
+ */
87
+ clearAriaLabel: { type: String, default: 'Clear search input' },
88
+ /**
89
+ * Specify whether the `<input>` should be disabled
90
+ */
91
+ disabled: { type: Boolean, default: false },
92
+ /**
93
+ * Do no show full control until it has focus. Similar to deprecated toolbar search.
94
+ */
95
+ expandable: { type: Boolean, default: false },
96
+ /**
97
+ * Wrap search in `<div>` if part of a form
98
+ */
99
+ formItem: { type: Boolean, default: true },
100
+ /**
101
+ * @deprecated use expandable
102
+ */
103
+ kind: {
104
+ type: String,
105
+ default: undefined,
106
+ validator: () => {
107
+ console.warn('Deprecated: probably you want expandable=true');
108
+ return true;
109
+ },
110
+ },
111
+ /**
112
+ * Provide the label text for the Search icon
113
+ */
114
+ label: String,
115
+ /**
116
+ * Specify the search size ('sm', 'md', 'lg', 'xl')
117
+ */
118
+ size: {
119
+ type: String,
120
+ default: 'xl',
121
+ validator: val => SEARCH_SIZES.includes(val),
122
+ },
123
+ /**
124
+ * @deprecated use size
125
+ */
126
+ small: {
127
+ type: Boolean,
128
+ default: undefined,
129
+ validator: val => {
130
+ if (val !== undefined) {
131
+ console.error('Error: Use size property: sm, lg or xl (default)');
132
+ return false;
133
+ }
134
+ return true;
135
+ },
136
+ },
137
+ /**
138
+ * @deprecated use size
139
+ */
140
+ large: {
141
+ type: Boolean,
142
+ default: undefined,
143
+ validator: val => {
144
+ if (val !== undefined) {
145
+ console.error('Error: Use size property: sm, lg or xl (default)');
146
+ return false;
147
+ }
148
+ return true;
149
+ },
150
+ },
151
+ /**
152
+ * Optionally provide the default value of the `<input>`
153
+ */
154
+ value: String,
155
+ /**
156
+ * @deprecated use value
157
+ */
158
+ modelValue: {
159
+ type: String,
160
+ default: undefined,
161
+ validator: () => {
162
+ console.warn('Deprecated: use v-model:value instead');
163
+ return true;
164
+ },
165
+ },
166
+ /**
167
+ * Provide an optional placeholder text for the Search. Note: if the label and placeholder differ, VoiceOver on Mac will read both
168
+ */
169
+ placeholder: { type: String, default: 'Search' },
170
+ /**
171
+ * @deprecated
172
+ */
173
+ toolbarAriaLabel: {
174
+ type: String,
175
+ validator: () => {
176
+ console.warn('Deprecated: probably you want expandable=true');
177
+ return true;
178
+ },
179
+ },
180
+ ...propsTheme,
181
+ ...propsCvId,
182
+ });
183
+ const uid = useCvId(props, true);
184
+ const isLight = useIsLight(props);
185
+
186
+ const clearVisible = ref(props.value ? props.value.length : false);
187
+ const internalSearchText = ref(props.value || props.modelValue);
188
+ const searchActive = ref(false);
189
+ watch(
190
+ () => props.value,
191
+ () => {
192
+ clearVisible.value = props.value ? props.value.length : false;
193
+ internalSearchText.value = props.value;
194
+ }
195
+ );
196
+
197
+ const internalAriaLabel = computed(() => {
198
+ if (!props.label) return props.ariaLabel;
199
+ else return undefined;
200
+ });
201
+ const internalAriaLabelBy = computed(() => {
202
+ if (props.label) return uid.value;
203
+ else return undefined;
204
+ });
205
+
206
+ const emit = defineEmits(['input', 'update:value', 'update:modelValue']);
207
+ watch(internalSearchText, () => {
208
+ emit('input', internalSearchText.value);
209
+ emit('update:value', internalSearchText.value);
210
+ if (props.modelValue) {
211
+ console.warn('Deprecated: use v-model:value instead');
212
+ emit('update:modelValue', internalSearchText.value);
213
+ }
214
+ });
215
+ function onClearClick() {
216
+ internalSearchText.value = '';
217
+ clearVisible.value = false;
218
+ if (props.expandable) {
219
+ elInput.value?.focus();
220
+ }
221
+ checkFocus();
222
+ }
223
+ function onInput() {
224
+ clearVisible.value = internalSearchText.value.length > 0;
225
+ }
226
+ const elInput = ref(null);
227
+ const isExpanded = computed(() => {
228
+ return props.expandable && searchActive.value;
229
+ });
230
+ function toggleActive(force) {
231
+ if (props.disabled) return;
232
+
233
+ if (typeof force === 'boolean') searchActive.value = force;
234
+ else if (internalSearchText.value?.length > 0) searchActive.value = true;
235
+ else searchActive.value = !searchActive.value;
236
+
237
+ if (searchActive.value) {
238
+ elInput.value?.focus();
239
+ }
240
+ }
241
+ const elSearch = ref(null);
242
+ function checkFocus() {
243
+ if (props.disabled) return;
244
+
245
+ if (props.expandable) {
246
+ if (elInput.value !== document.activeElement)
247
+ searchActive.value = internalSearchText.value?.length > 0;
248
+ }
249
+ }
250
+ </script>
@@ -0,0 +1,3 @@
1
+ import CvSearch from './CvSearch.vue';
2
+ const SEARCH_SIZES = ['sm', 'lg', 'xl'];
3
+ export { CvSearch, SEARCH_SIZES };
@@ -1,13 +1,14 @@
1
1
  <template>
2
2
  <cv-wrapper
3
+ ref="el"
3
4
  :tag-type="formItem ? 'div' : ''"
4
5
  :class="`cv-select ${carbonPrefix}--form-item`"
5
- ref="el"
6
6
  >
7
7
  <div
8
8
  :data-test="value"
9
9
  :class="[
10
10
  `${carbonPrefix}--select`,
11
+ `${carbonClasses}`,
11
12
  {
12
13
  'cv-select': !formItem,
13
14
  [`${carbonPrefix}--select--inline`]: inline,
@@ -48,9 +49,8 @@
48
49
  size || 'md',
49
50
  },
50
51
  ]"
51
- @change="onChange"
52
- ref="select"
53
52
  :value="internalValue"
53
+ @change="onChange"
54
54
  >
55
55
  <slot></slot>
56
56
  </select>
@@ -77,7 +77,6 @@
77
77
  >
78
78
  <slot name="helper-text">{{ helperText }}</slot>
79
79
  </div>
80
-
81
80
  <!-- cv-wrapper div ${carbonPrefix}--select-input--inline__wrapper -->
82
81
  </cv-wrapper>
83
82
  </div>
@@ -87,7 +86,15 @@
87
86
 
88
87
  <script setup>
89
88
  import { carbonPrefix } from '../../global/settings';
90
- import { computed, onMounted, onUpdated, ref, useSlots, watch } from 'vue';
89
+ import {
90
+ computed,
91
+ onMounted,
92
+ onUpdated,
93
+ ref,
94
+ useAttrs,
95
+ useSlots,
96
+ watch,
97
+ } from 'vue';
91
98
  import {
92
99
  WarningFilled16 as WarningFilled,
93
100
  ChevronDown16 as ChevronDown,
@@ -112,6 +119,7 @@ const props = defineProps({
112
119
  // multiple does not work with styling from carbon-components 9.20
113
120
  multiple: {
114
121
  type: String,
122
+ default: undefined,
115
123
  validator: () => {
116
124
  console.warn('property multiple not supported in CvSelect');
117
125
  return false;
@@ -123,7 +131,7 @@ const props = defineProps({
123
131
  default: 'md',
124
132
  validator: val => ['sm', 'md', 'lg'].includes(val),
125
133
  },
126
- modelValue: { type: String },
134
+ modelValue: { type: String, default: undefined },
127
135
  ...propsTheme,
128
136
  ...propsCvId,
129
137
  });
@@ -221,4 +229,17 @@ function updateWarning() {
221
229
  }
222
230
  onMounted(updateWarning);
223
231
  onUpdated(updateWarning);
232
+
233
+ // There is an oddity here with Vue2 vs Vue3. The Vue2 component uses CvWrapper to determine if this component
234
+ // is wrapped in a div or not. Either way the class attributes are applied in Vue2. In Vue3 the attributes are
235
+ // not applied. The CvTimePicker consumes this component and needs to apply styles in both the wrapped and
236
+ // unwrapped case. Here we apply any carbon styles to the outer div.
237
+ const attrs = useAttrs();
238
+ const carbonClasses = computed(() => {
239
+ if (props.formItem || !attrs.class) return '';
240
+ return attrs.class
241
+ ?.split(' ')
242
+ .filter(c => c.startsWith(`${carbonPrefix}--`))
243
+ .join(' ');
244
+ });
224
245
  </script>
@@ -0,0 +1,166 @@
1
+ import { ref } from 'vue';
2
+ import { action } from '@storybook/addon-actions';
3
+ import {
4
+ sbCompPrefix,
5
+ storyParametersObject,
6
+ } from '../../global/storybook-utils';
7
+ import { sbSliderPrefix } from './sbSliderPrefix';
8
+ import { CvSlider } from '.';
9
+
10
+ export default {
11
+ title: `${sbCompPrefix}/${sbSliderPrefix}/CvSlider`,
12
+ component: CvSlider,
13
+ argTypes: {
14
+ disabled: {
15
+ type: 'boolean',
16
+ table: {
17
+ type: { summary: 'boolean' },
18
+ category: 'attributes',
19
+ },
20
+ },
21
+ value: {
22
+ type: 'string',
23
+ table: {
24
+ type: { summary: 'string' },
25
+ category: 'props',
26
+ },
27
+ },
28
+ label: {
29
+ type: 'string',
30
+ table: {
31
+ type: { summary: 'string' },
32
+ category: 'props',
33
+ },
34
+ description: 'Slider top label',
35
+ },
36
+ light: {
37
+ type: 'boolean',
38
+ table: {
39
+ type: { summary: 'boolean' },
40
+ category: 'props',
41
+ },
42
+ },
43
+ min: {
44
+ type: 'string',
45
+ table: {
46
+ type: { summary: 'string' },
47
+ category: 'props',
48
+ },
49
+ description: 'Slider input min value',
50
+ },
51
+ max: {
52
+ type: 'string',
53
+ table: {
54
+ type: { summary: 'string' },
55
+ category: 'props',
56
+ },
57
+ description: 'Slider input max value',
58
+ },
59
+ minLabel: {
60
+ type: 'string',
61
+ table: {
62
+ type: { summary: 'string' },
63
+ category: 'props',
64
+ },
65
+ description: 'Label for min side of slider, otherwise min value used',
66
+ },
67
+ maxLabel: {
68
+ type: 'string',
69
+ table: {
70
+ type: { summary: 'string' },
71
+ category: 'props',
72
+ },
73
+ description: 'Label for max side of slider, otherwise max value used',
74
+ },
75
+ step: {
76
+ type: 'string',
77
+ table: {
78
+ type: { summary: 'string' },
79
+ category: 'props',
80
+ },
81
+ description: 'Slider input step value',
82
+ },
83
+ stepMultiplier: {
84
+ type: 'string',
85
+ table: {
86
+ type: { summary: 'string' },
87
+ category: 'props',
88
+ },
89
+ description: 'multiplier > 1',
90
+ },
91
+ },
92
+
93
+ // events
94
+ change: {
95
+ type: 'event',
96
+ table: {
97
+ type: { summary: 'event' },
98
+ category: 'events',
99
+ },
100
+ control: { type: null },
101
+ },
102
+ 'update:modelValue': {
103
+ type: 'event',
104
+ table: {
105
+ type: { summary: 'event' },
106
+ category: 'events',
107
+ },
108
+ control: { type: null },
109
+ },
110
+ };
111
+
112
+ const template = `<cv-slider v-bind="args" @change="onChange"/>`;
113
+ const Template = args => {
114
+ return {
115
+ components: { CvSlider },
116
+ setup: () => ({
117
+ args,
118
+ onChange: action('change'),
119
+ }),
120
+ template,
121
+ };
122
+ };
123
+
124
+ export const Default = Template.bind({});
125
+ Default.args = {};
126
+ Default.parameters = storyParametersObject(
127
+ Default.parameters,
128
+ template,
129
+ Default.args
130
+ );
131
+
132
+ const vModelTemplate = `
133
+ <cv-slider v-bind="args" v-model="modelValue" />
134
+
135
+ <div style="margin-top:1rem; background-color: #888888; padding:1rem">
136
+ <div style="font-size: 150%">
137
+ Sample interaction
138
+ </div>
139
+
140
+ <input v-model="modelValue" type="string" />
141
+ <div>
142
+ Entered value:
143
+ <span style="font-weight: bold;">{{modelValue}}</span>
144
+ </div>
145
+ </div>
146
+ `;
147
+
148
+ const VModelTemplate = args => {
149
+ return {
150
+ components: { CvSlider },
151
+ setup: () => ({
152
+ args,
153
+ onChange: action('change'),
154
+ modelValue: ref('15'),
155
+ }),
156
+ template: vModelTemplate,
157
+ };
158
+ };
159
+
160
+ export const vModel = VModelTemplate.bind({});
161
+ vModel.args = {};
162
+ vModel.parameters = storyParametersObject(
163
+ vModel.parameters,
164
+ vModelTemplate,
165
+ vModel.args
166
+ );