@rancher/shell 0.3.23 → 0.3.25

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 (149) hide show
  1. package/assets/styles/base/_variables.scss +1 -0
  2. package/assets/styles/themes/_dark.scss +1 -0
  3. package/assets/styles/themes/_light.scss +6 -5
  4. package/assets/translations/en-us.yaml +44 -17
  5. package/assets/translations/zh-hans.yaml +2 -2
  6. package/components/ClusterIconMenu.vue +143 -0
  7. package/components/CruResource.vue +7 -1
  8. package/components/ExplorerProjectsNamespaces.vue +11 -1
  9. package/components/FixedBanner.vue +17 -1
  10. package/components/Loading.vue +1 -1
  11. package/components/Markdown.vue +1 -1
  12. package/components/Questions/__tests__/Yaml.test.ts +3 -2
  13. package/components/SideNav.vue +1 -1
  14. package/components/SortableTable/index.vue +3 -2
  15. package/components/auth/RoleDetailEdit.vue +15 -2
  16. package/components/auth/login/saml.vue +12 -1
  17. package/components/form/LabeledSelect.vue +12 -5
  18. package/components/form/Members/ClusterPermissionsEditor.vue +1 -1
  19. package/components/form/Members/MembershipEditor.vue +6 -1
  20. package/components/form/SelectOrCreateAuthSecret.vue +7 -0
  21. package/components/form/__tests__/KeyValue.test.ts +6 -3
  22. package/components/form/__tests__/LabeledSelect.test.ts +18 -0
  23. package/components/formatter/PodsUsage.vue +11 -36
  24. package/components/formatter/PrincipalGroupBindings.vue +8 -5
  25. package/components/formatter/__tests__/PodsUsage.test.ts +36 -19
  26. package/components/nav/Group.vue +62 -34
  27. package/components/nav/Header.vue +13 -6
  28. package/components/nav/Pinned.vue +47 -0
  29. package/components/nav/TopLevelMenu.vue +673 -325
  30. package/components/nav/Type.vue +88 -8
  31. package/config/home-links.js +1 -1
  32. package/config/product/istio.js +15 -5
  33. package/config/router.js +3 -9
  34. package/config/table-headers.js +5 -6
  35. package/config/uiplugins.js +1 -0
  36. package/core/plugin-helpers.js +3 -0
  37. package/core/types.ts +6 -1
  38. package/creators/app/files/.vscode/settings.json +0 -1
  39. package/creators/pkg/init +2 -2
  40. package/detail/__tests__/autoscaling.horizontalpodautoscaler.test.ts +118 -0
  41. package/detail/autoscaling.horizontalpodautoscaler/index.vue +4 -4
  42. package/detail/provisioning.cattle.io.cluster.vue +7 -5
  43. package/edit/__tests__/management.cattle.io.clusterroletemplatebinding.test.ts +58 -0
  44. package/edit/__tests__/namespace.test.ts +5 -3
  45. package/edit/fleet.cattle.io.gitrepo.vue +43 -15
  46. package/edit/logging.banzaicloud.io.output/index.vue +7 -0
  47. package/edit/management.cattle.io.clusterroletemplatebinding.vue +3 -11
  48. package/edit/namespace.vue +8 -4
  49. package/edit/provisioning.cattle.io.cluster/Basics.vue +662 -0
  50. package/edit/provisioning.cattle.io.cluster/CustomCommand.vue +9 -8
  51. package/edit/provisioning.cattle.io.cluster/DrainOptions.vue +13 -8
  52. package/edit/provisioning.cattle.io.cluster/MachinePool.vue +11 -2
  53. package/edit/provisioning.cattle.io.cluster/MemberRoles.vue +40 -0
  54. package/edit/provisioning.cattle.io.cluster/__tests__/Basics.tests.ts +237 -0
  55. package/edit/provisioning.cattle.io.cluster/__tests__/CustomCommand.tests.ts +71 -23
  56. package/edit/provisioning.cattle.io.cluster/__tests__/DrainOptions.test.ts +52 -0
  57. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +65 -142
  58. package/edit/provisioning.cattle.io.cluster/rke2.vue +253 -582
  59. package/edit/workload/storage/ContainerMountPaths.vue +7 -5
  60. package/edit/workload/storage/__tests__/Storage.test.ts +2 -2
  61. package/edit/workload/storage/persistentVolumeClaim/__tests__/persistentvolumeclaim.test.ts +36 -0
  62. package/edit/workload/storage/persistentVolumeClaim/persistentvolumeclaim.vue +15 -7
  63. package/initialize/App.js +2 -0
  64. package/initialize/client.js +63 -51
  65. package/initialize/index.js +7 -5
  66. package/layouts/default.vue +10 -2
  67. package/layouts/home.vue +6 -2
  68. package/layouts/plain.vue +9 -2
  69. package/list/fleet.cattle.io.cluster.vue +2 -2
  70. package/list/management.cattle.io.feature.vue +1 -1
  71. package/machine-config/amazonec2.vue +1 -0
  72. package/machine-config/vmwarevsphere.vue +48 -7
  73. package/mixins/brand.js +0 -8
  74. package/mixins/child-hook.js +2 -2
  75. package/mixins/create-edit-view/impl.js +3 -3
  76. package/mixins/fetch.client.js +3 -3
  77. package/models/__tests__/management.cattle.io.node.ts +96 -0
  78. package/models/__tests__/node.ts +74 -0
  79. package/models/cluster/node.js +6 -5
  80. package/models/cluster.x-k8s.io.machinedeployment.js +2 -2
  81. package/models/management.cattle.io.cluster.js +22 -1
  82. package/models/management.cattle.io.clusterroletemplatebinding.js +3 -3
  83. package/models/management.cattle.io.globalrole.js +17 -2
  84. package/models/management.cattle.io.node.js +6 -4
  85. package/models/management.cattle.io.projectroletemplatebinding.js +3 -3
  86. package/models/management.cattle.io.roletemplate.js +17 -2
  87. package/package.json +2 -6
  88. package/pages/__tests__/prefs.test.ts +1 -1
  89. package/pages/about.vue +2 -0
  90. package/pages/auth/setup.vue +5 -4
  91. package/pages/c/_cluster/explorer/ConfigBadge.vue +1 -0
  92. package/pages/c/_cluster/monitoring/index.vue +8 -3
  93. package/pages/c/_cluster/uiplugins/CatalogList/CatalogLoadDialog.vue +9 -66
  94. package/pages/c/_cluster/uiplugins/CatalogList/CatalogUninstallDialog.vue +182 -0
  95. package/pages/c/_cluster/uiplugins/CatalogList/index.vue +15 -32
  96. package/pages/c/_cluster/uiplugins/UninstallDialog.vue +8 -46
  97. package/pages/c/_cluster/uiplugins/index.vue +64 -64
  98. package/pages/diagnostic.vue +0 -39
  99. package/pages/home.vue +1 -1
  100. package/pages/prefs.vue +3 -13
  101. package/plugins/dashboard-store/normalize.js +4 -4
  102. package/plugins/dashboard-store/resource-class.js +1 -1
  103. package/plugins/int-number.js +5 -2
  104. package/plugins/positive-int-number.js +19 -0
  105. package/plugins/steve/__tests__/getters.spec.ts +15 -0
  106. package/plugins/steve/getters.js +22 -10
  107. package/public/index.html +4 -2
  108. package/rancher-components/BadgeState/BadgeState.vue +5 -1
  109. package/rancher-components/Banner/Banner.test.ts +51 -1
  110. package/rancher-components/Banner/Banner.vue +134 -53
  111. package/rancher-components/Card/Card.test.ts +37 -0
  112. package/rancher-components/Card/Card.vue +24 -7
  113. package/rancher-components/Form/Checkbox/Checkbox.test.ts +20 -29
  114. package/rancher-components/Form/Checkbox/Checkbox.vue +45 -20
  115. package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +2 -8
  116. package/rancher-components/Form/LabeledInput/LabeledInput.vue +22 -10
  117. package/rancher-components/Form/Radio/RadioButton.test.ts +31 -0
  118. package/rancher-components/Form/Radio/RadioButton.vue +30 -13
  119. package/rancher-components/Form/Radio/RadioGroup.vue +26 -7
  120. package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +7 -6
  121. package/rancher-components/Form/ToggleSwitch/ToggleSwitch.test.ts +25 -38
  122. package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +23 -11
  123. package/rancher-components/LabeledTooltip/LabeledTooltip.vue +19 -5
  124. package/rancher-components/StringList/StringList.test.ts +453 -49
  125. package/rancher-components/StringList/StringList.vue +92 -58
  126. package/scripts/extension/parse-tag-name +0 -0
  127. package/store/index.js +4 -0
  128. package/store/prefs.js +4 -4
  129. package/store/type-map.js +2 -16
  130. package/types/shell/index.d.ts +26 -14
  131. package/utils/__tests__/cluster.test.ts +55 -0
  132. package/utils/__tests__/object.test.ts +21 -2
  133. package/utils/__tests__/sort.test.ts +61 -0
  134. package/utils/cluster.js +47 -1
  135. package/utils/object.js +12 -5
  136. package/utils/string.js +12 -0
  137. package/utils/validators/formRules/__tests__/index.test.ts +13 -1
  138. package/utils/validators/formRules/index.ts +4 -0
  139. package/utils/validators/role-template.js +9 -1
  140. package/utils/version.js +1 -1
  141. package/vue.config.js +1 -4
  142. package/yarn-error.log +200 -0
  143. package/content/docs/en-us/getting-started.md +0 -224
  144. package/content/docs/en-us/whats-new.md +0 -29
  145. package/content/docs/zh-hans/getting-started.md +0 -224
  146. package/content/docs/zh-hans/whats-new.md +0 -28
  147. package/pages/docs/_doc.vue +0 -345
  148. package/pages/docs/toc.js +0 -27
  149. package/plugins/console.js +0 -34
@@ -1,7 +1,13 @@
1
- import { shallowMount } from '@vue/test-utils';
1
+ import { shallowMount, Wrapper } from '@vue/test-utils';
2
2
  import { Checkbox } from './index';
3
3
 
4
- describe('Checkbox.vue', () => {
4
+ describe('checkbox.vue', () => {
5
+ const event = {
6
+ target: { tagName: 'input', href: null },
7
+ stopPropagation: () => { },
8
+ preventDefault: () => { }
9
+ } as unknown as MouseEvent;
10
+
5
11
  it('is unchecked by default', () => {
6
12
  const wrapper = shallowMount(Checkbox);
7
13
  const cbInput = wrapper.find('input[type="checkbox"]').element as HTMLInputElement;
@@ -16,7 +22,7 @@ describe('Checkbox.vue', () => {
16
22
  expect(cbInput.checked).toBe(true);
17
23
  });
18
24
 
19
- it('updates from false to true when props change', async () => {
25
+ it('updates from false to true when props change', async() => {
20
26
  const wrapper = shallowMount(Checkbox);
21
27
  const cbInput = wrapper.find('input[type="checkbox"]').element as HTMLInputElement;
22
28
 
@@ -27,51 +33,36 @@ describe('Checkbox.vue', () => {
27
33
  expect(cbInput.checked).toBe(true);
28
34
  });
29
35
 
30
- it('emits an input event with a true value', async () => {
31
- const wrapper = shallowMount(Checkbox);
32
- const event = {
33
- target: { tagName: 'input', href: null },
34
- stopPropagation: () => { },
35
- preventDefault: () => { }
36
- };
36
+ it('emits an input event with a true value', async() => {
37
+ const wrapper: Wrapper<InstanceType<typeof Checkbox>> = shallowMount(Checkbox);
37
38
 
38
- (wrapper.vm as any).clicked(event);
39
+ wrapper.vm.clicked(event);
39
40
  await wrapper.vm.$nextTick();
40
41
 
41
42
  expect(wrapper.emitted().input?.length).toBe(1);
42
43
  expect(wrapper.emitted().input?.[0][0]).toBe(true);
43
44
  });
44
45
 
45
- it('emits an input event with a custom valueWhenTrue', async () => {
46
+ it('emits an input event with a custom valueWhenTrue', async() => {
46
47
  const valueWhenTrue = 'BIG IF TRUE';
47
- const event = {
48
- target: { tagName: 'input', href: null },
49
- stopPropagation: () => { },
50
- preventDefault: () => { }
51
- };
52
48
 
53
- const wrapper = shallowMount(Checkbox, { propsData: { value: false, valueWhenTrue } });
49
+ const wrapper: Wrapper<InstanceType<typeof Checkbox>> = shallowMount(Checkbox, { propsData: { value: false, valueWhenTrue } });
54
50
 
55
- (wrapper.vm as any).clicked(event);
51
+ wrapper.vm.clicked(event);
56
52
  await wrapper.vm.$nextTick();
57
53
 
58
54
  expect(wrapper.emitted().input?.length).toBe(1);
59
55
  expect(wrapper.emitted().input?.[0][0]).toBe(valueWhenTrue);
60
56
  });
61
57
 
62
- it('updates from valueWhenTrue to falsy', async () => {
58
+ it('updates from valueWhenTrue to falsy', async() => {
63
59
  const valueWhenTrue = 'REAL HUGE IF FALSE';
64
- const event = {
65
- target: { tagName: 'input', href: null },
66
- stopPropagation: () => { },
67
- preventDefault: () => { }
68
- };
69
60
 
70
- const wrapper = shallowMount(Checkbox, { propsData: { value: valueWhenTrue, valueWhenTrue } });
61
+ const wrapper: Wrapper<InstanceType<typeof Checkbox>> = shallowMount(Checkbox, { propsData: { value: valueWhenTrue, valueWhenTrue } });
71
62
 
72
- (wrapper.vm as any).clicked(event);
63
+ wrapper.vm.clicked(event);
73
64
  await wrapper.vm.$nextTick();
74
65
 
75
- expect(wrapper.emitted().input?.[0][0]).toBe(null);
76
- })
66
+ expect(wrapper.emitted().input?.[0][0]).toBeNull();
67
+ });
77
68
  });
@@ -2,8 +2,11 @@
2
2
  import Vue, { PropType } from 'vue';
3
3
  import { _EDIT, _VIEW } from '@shell/config/query-params';
4
4
  import { addObject, removeObject } from '@shell/utils/array';
5
+ import cloneDeep from 'lodash/cloneDeep';
5
6
 
6
7
  export default Vue.extend({
8
+ name: 'Checkbox',
9
+
7
10
  props: {
8
11
  /**
9
12
  * The checkbox value.
@@ -46,8 +49,8 @@ export default Vue.extend({
46
49
  },
47
50
 
48
51
  /**
49
- * Display an indeterminate state. Useful for cases where a checkbox might
50
- * be the parent to child checkboxes, and we need to show that a subset of
52
+ * Display an indeterminate state. Useful for cases where a checkbox might
53
+ * be the parent to child checkboxes, and we need to show that a subset of
51
54
  * children are checked.
52
55
  */
53
56
  indeterminate: {
@@ -110,22 +113,22 @@ export default Vue.extend({
110
113
  primary: {
111
114
  type: Boolean,
112
115
  default: false
113
- },
116
+ },
114
117
  },
115
118
 
116
119
  computed: {
117
120
  /**
118
121
  * Determines if the checkbox is disabled.
119
- * @returns boolean: True when the disabled prop is true or when mode is
122
+ * @returns boolean: True when the disabled prop is true or when mode is
120
123
  * View.
121
124
  */
122
125
  isDisabled(): boolean {
123
126
  return (this.disabled || this.mode === _VIEW);
124
127
  },
125
128
  /**
126
- * Determines if the checkbox is checked when using custom values or
129
+ * Determines if the checkbox is checked when using custom values or
127
130
  * multiple values.
128
- * @returns boolean: True when at least one value is true in a collection or
131
+ * @returns boolean: True when at least one value is true in a collection or
129
132
  * when value matches `this.valueWhenTrue`.
130
133
  */
131
134
  isChecked(): boolean {
@@ -162,13 +165,15 @@ export default Vue.extend({
162
165
  const click = new CustomEvent('click', customEvent);
163
166
 
164
167
  // Flip the value
165
- if (this.isMulti(this.value)) {
168
+ const value = cloneDeep(this.value);
169
+
170
+ if (this.isMulti(value)) {
166
171
  if (this.isChecked) {
167
- removeObject(this.value, this.valueWhenTrue);
172
+ removeObject(value, this.valueWhenTrue);
168
173
  } else {
169
- addObject(this.value, this.valueWhenTrue);
174
+ addObject(value, this.valueWhenTrue);
170
175
  }
171
- this.$emit('input', this.value);
176
+ this.$emit('input', value);
172
177
  } else if (this.isString(this.valueWhenTrue)) {
173
178
  if (this.isChecked) {
174
179
  this.$emit('input', null);
@@ -176,7 +181,7 @@ export default Vue.extend({
176
181
  this.$emit('input', this.valueWhenTrue);
177
182
  }
178
183
  } else {
179
- this.$emit('input', !this.value);
184
+ this.$emit('input', !value);
180
185
  this.$el.dispatchEvent(click);
181
186
  }
182
187
  },
@@ -197,14 +202,17 @@ export default Vue.extend({
197
202
  * @param value A collection of values for the checkbox.
198
203
  */
199
204
  findTrueValues(value: boolean[]): boolean {
200
- return value.find(v => v === this.valueWhenTrue) || false;
205
+ return value.find((v) => v === this.valueWhenTrue) || false;
201
206
  }
202
207
  }
203
208
  });
204
209
  </script>
205
210
 
206
211
  <template>
207
- <div class="checkbox-outer-container" data-checkbox-ctrl>
212
+ <div
213
+ class="checkbox-outer-container"
214
+ data-checkbox-ctrl
215
+ >
208
216
  <label
209
217
  class="checkbox-container"
210
218
  :class="{ 'disabled': isDisabled}"
@@ -214,14 +222,13 @@ export default Vue.extend({
214
222
  @click="clicked($event)"
215
223
  >
216
224
  <input
217
- v-model="value"
218
225
  :checked="isChecked"
219
226
  :value="valueWhenTrue"
220
227
  type="checkbox"
221
228
  :tabindex="-1"
222
229
  :name="id"
223
230
  @click.stop.prevent
224
- />
231
+ >
225
232
  <span
226
233
  class="checkbox-custom"
227
234
  :class="{indeterminate: indeterminate}"
@@ -236,15 +243,33 @@ export default Vue.extend({
236
243
  :class="{ 'checkbox-primary': primary }"
237
244
  >
238
245
  <slot name="label">
239
- <t v-if="labelKey" :k="labelKey" :raw="true" />
246
+ <t
247
+ v-if="labelKey"
248
+ :k="labelKey"
249
+ :raw="true"
250
+ />
240
251
  <template v-else-if="label">{{ label }}</template>
241
- <i v-if="tooltipKey" v-tooltip="t(tooltipKey)" class="checkbox-info icon icon-info icon-lg" />
242
- <i v-else-if="tooltip" v-tooltip="tooltip" class="checkbox-info icon icon-info icon-lg" />
252
+ <i
253
+ v-if="tooltipKey"
254
+ v-clean-tooltip="t(tooltipKey)"
255
+ class="checkbox-info icon icon-info icon-lg"
256
+ />
257
+ <i
258
+ v-else-if="tooltip"
259
+ v-clean-tooltip="tooltip"
260
+ class="checkbox-info icon icon-info icon-lg"
261
+ />
243
262
  </slot>
244
263
  </span>
245
264
  </label>
246
- <div v-if="descriptionKey || description" class="checkbox-outer-container-description">
247
- <t v-if="descriptionKey" :k="descriptionKey" />
265
+ <div
266
+ v-if="descriptionKey || description"
267
+ class="checkbox-outer-container-description"
268
+ >
269
+ <t
270
+ v-if="descriptionKey"
271
+ :k="descriptionKey"
272
+ />
248
273
  <template v-else-if="description">
249
274
  {{ description }}
250
275
  </template>
@@ -6,15 +6,9 @@ describe('component: LabeledInput', () => {
6
6
  it('should emit input only once', () => {
7
7
  const value = '2';
8
8
  const delay = 1;
9
- const wrapper = mount(LabeledInput, {
9
+ const wrapper = mount(LabeledInput, {
10
10
  propsData: { delay },
11
- mocks: {
12
- $store: {
13
- getters: {
14
- 'i18n/t': jest.fn()
15
- }
16
- }
17
- }
11
+ mocks: { $store: { getters: { 'i18n/t': jest.fn() } } }
18
12
  });
19
13
 
20
14
  jest.useFakeTimers();
@@ -27,7 +27,7 @@ export default (
27
27
 
28
28
  /**
29
29
  * The status class of the Labeled Input and tooltip.
30
- * @values info, success, warning, error
30
+ * @values info, success, warning, error
31
31
  */
32
32
  status: {
33
33
  type: String,
@@ -59,7 +59,7 @@ export default (
59
59
  },
60
60
 
61
61
  /**
62
- * Disables the password manager prompt to save the contents of the Labeled
62
+ * Disables the password manager prompt to save the contents of the Labeled
63
63
  * Input.
64
64
  */
65
65
  ignorePasswordManagers: {
@@ -124,7 +124,7 @@ export default (
124
124
 
125
125
  tooltipValue(): string | undefined {
126
126
  if (this.hasTooltip) {
127
- return this.tooltipKey ? this.t(this.tooltipKey) : this.tooltip
127
+ return this.tooltipKey ? this.t(this.tooltipKey) : this.tooltip;
128
128
  }
129
129
 
130
130
  return undefined;
@@ -207,7 +207,7 @@ export default (
207
207
  },
208
208
 
209
209
  /**
210
- * Emit on input with delay. Note: Arrow function is avoided due context
210
+ * Emit on input with delay. Note: Arrow function is avoided due context
211
211
  * binding.
212
212
  */
213
213
  delayInput(value: string): void {
@@ -223,7 +223,7 @@ export default (
223
223
  },
224
224
 
225
225
  /**
226
- * Handles the behavior of the Labeled Input when blurred and emits the blur
226
+ * Handles the behavior of the Labeled Input when blurred and emits the blur
227
227
  * event.
228
228
  * @see labeled-form-element.ts mixin for onBlurLabeled()
229
229
  */
@@ -253,10 +253,16 @@ export default (
253
253
  >
254
254
  <slot name="label">
255
255
  <label v-if="hasLabel">
256
- <t v-if="labelKey" :k="labelKey" />
256
+ <t
257
+ v-if="labelKey"
258
+ :k="labelKey"
259
+ />
257
260
  <template v-else-if="label">{{ label }}</template>
258
261
 
259
- <span v-if="requiredField" class="required">*</span>
262
+ <span
263
+ v-if="requiredField"
264
+ class="required"
265
+ >*</span>
260
266
  </label>
261
267
  </slot>
262
268
 
@@ -293,7 +299,7 @@ export default (
293
299
  @input="onInput($event.target.value)"
294
300
  @focus="onFocus"
295
301
  @blur="onBlur"
296
- />
302
+ >
297
303
  </slot>
298
304
 
299
305
  <slot name="suffix" />
@@ -308,8 +314,14 @@ export default (
308
314
  :hover="hoverTooltip"
309
315
  :value="validationMessage"
310
316
  />
311
- <label v-if="cronHint" class="cron-label">{{ cronHint }}</label>
312
- <label v-if="subLabel" class="sub-label">{{ subLabel }}</label>
317
+ <label
318
+ v-if="cronHint"
319
+ class="cron-label"
320
+ >{{ cronHint }}</label>
321
+ <label
322
+ v-if="subLabel"
323
+ class="sub-label"
324
+ >{{ subLabel }}</label>
313
325
  </div>
314
326
  </template>
315
327
  <style scoped lang="scss">
@@ -0,0 +1,31 @@
1
+ import { shallowMount } from '@vue/test-utils';
2
+ import { RadioButton } from './index';
3
+ import { cleanHtmlDirective } from '@shell/plugins/clean-html-directive';
4
+
5
+ describe('radioButton.vue', () => {
6
+ it('renders label slot contents', () => {
7
+ const wrapper = shallowMount(RadioButton, { slots: { label: 'Test Label' } });
8
+
9
+ expect(wrapper.find('.radio-label').text()).toBe('Test Label');
10
+ });
11
+
12
+ it('renders label prop contents', () => {
13
+ const wrapper = shallowMount(
14
+ RadioButton,
15
+ {
16
+ directives: { cleanHtmlDirective },
17
+ propsData: { label: 'Test Label' }
18
+ });
19
+
20
+ expect(wrapper.find('.radio-label').text()).toBe('Test Label');
21
+ });
22
+
23
+ it('renders slot contents when both slot and label prop are provided', () => {
24
+ const wrapper = shallowMount(RadioButton, {
25
+ slots: { label: 'Test Label - Slot' },
26
+ propsData: { label: 'Test Label - Props' },
27
+ });
28
+
29
+ expect(wrapper.find('.radio-label').text()).toBe('Test Label - Slot');
30
+ });
31
+ });
@@ -12,25 +12,25 @@ export default Vue.extend({
12
12
  default: ''
13
13
  },
14
14
 
15
- /**
15
+ /**
16
16
  * The value for this option.
17
- */
17
+ */
18
18
  val: {
19
19
  required: true,
20
- validator: x => true
20
+ validator: () => true
21
21
  },
22
22
 
23
- /**
23
+ /**
24
24
  * The selected value.
25
- */
25
+ */
26
26
  value: {
27
27
  required: true,
28
- validator: x => true
28
+ validator: () => true
29
29
  },
30
30
 
31
31
  /**
32
32
  * The label shown next to the radio.
33
- */
33
+ */
34
34
  label: {
35
35
  type: String,
36
36
  default: ''
@@ -96,6 +96,10 @@ export default Vue.extend({
96
96
  hasDescriptionSlot(): boolean {
97
97
  return !!this.$slots.description;
98
98
  },
99
+
100
+ hasLabelSlot(): boolean {
101
+ return !!this.$slots.label || !!this.$scopedSlots.label;
102
+ }
99
103
  },
100
104
 
101
105
  watch: {
@@ -138,7 +142,7 @@ export default Vue.extend({
138
142
  type="radio"
139
143
  :tabindex="-1"
140
144
  @click.stop.prevent
141
- />
145
+ >
142
146
  <span
143
147
  ref="custom"
144
148
  :class="[ isDisabled ? 'text-muted' : '', 'radio-custom']"
@@ -149,15 +153,28 @@ export default Vue.extend({
149
153
  />
150
154
  <div class="labeling">
151
155
  <label
152
- v-if="label"
153
156
  :class="[ muteLabel ? 'text-muted' : '', 'radio-label', 'm-0']"
154
157
  :for="name"
155
- v-html="label"
156
158
  >
157
- <slot name="label">{{ label }}</slot>
159
+ <slot
160
+ v-if="hasLabelSlot"
161
+ name="label"
162
+ >
163
+ <!-- slot content -->
164
+ </slot>
165
+ <span
166
+ v-else-if="label"
167
+ v-clean-html="label"
168
+ />
158
169
  </label>
159
- <div v-if="descriptionKey || description" class="radio-button-outer-container-description">
160
- <t v-if="descriptionKey" :k="descriptionKey" />
170
+ <div
171
+ v-if="descriptionKey || description"
172
+ class="radio-button-outer-container-description"
173
+ >
174
+ <t
175
+ v-if="descriptionKey"
176
+ :k="descriptionKey"
177
+ />
161
178
  <template v-else-if="description">
162
179
  {{ description }}
163
180
  </template>
@@ -28,7 +28,7 @@ export default Vue.extend({
28
28
  },
29
29
 
30
30
  /**
31
- * If options are just values, then labels can be a corresponding display
31
+ * If options are just values, then labels can be a corresponding display
32
32
  * value.
33
33
  */
34
34
  labels: {
@@ -152,7 +152,7 @@ export default Vue.extend({
152
152
  */
153
153
  clickNext(direction: number): void {
154
154
  const opts = this.normalizedOptions;
155
- const selected = opts.find(x => x.value === this.value);
155
+ const selected = opts.find((x) => x.value === this.value);
156
156
  let newIndex = (selected ? opts.indexOf(selected) : -1) + direction;
157
157
 
158
158
  if (newIndex >= opts.length) {
@@ -169,15 +169,29 @@ export default Vue.extend({
169
169
 
170
170
  <template>
171
171
  <div>
172
- <div v-if="label || labelKey || tooltip || tooltipKey || $slots.label" class="radio-group label">
172
+ <div
173
+ v-if="label || labelKey || tooltip || tooltipKey || $slots.label"
174
+ class="radio-group label"
175
+ >
173
176
  <slot name="label">
174
177
  <h3>
175
- <t v-if="labelKey" :k="labelKey" />
178
+ <t
179
+ v-if="labelKey"
180
+ :k="labelKey"
181
+ />
176
182
  <template v-else-if="label">
177
183
  {{ label }}
178
184
  </template>
179
- <i v-if="tooltipKey" v-tooltip="t(tooltipKey)" class="icon icon-info icon-lg" />
180
- <i v-else-if="tooltip" v-tooltip="tooltip" class="icon icon-info icon-lg" />
185
+ <i
186
+ v-if="tooltipKey"
187
+ v-clean-tooltip="t(tooltipKey)"
188
+ class="icon icon-info icon-lg"
189
+ />
190
+ <i
191
+ v-else-if="tooltip"
192
+ v-clean-tooltip="tooltip"
193
+ class="icon icon-info icon-lg"
194
+ />
181
195
  </h3>
182
196
  </slot>
183
197
  </div>
@@ -192,7 +206,12 @@ export default Vue.extend({
192
206
  v-for="(option, i) in normalizedOptions"
193
207
  :key="name+'-'+i"
194
208
  >
195
- <slot :listeners="$listeners" :option="option" :name="i">
209
+ <slot
210
+ :listeners="$listeners"
211
+ :option="option"
212
+ :is-disabled="isDisabled"
213
+ :name="i"
214
+ >
196
215
  <RadioButton
197
216
  :key="name+'-'+i"
198
217
  :name="name"
@@ -24,14 +24,14 @@ export default Vue.extend({
24
24
  },
25
25
 
26
26
  /**
27
- * Sets the Minimum height for Text Area. Prevents the height from becoming
27
+ * Sets the Minimum height for Text Area. Prevents the height from becoming
28
28
  * smaller than the value specified in minHeight.
29
29
  */
30
30
  minHeight: {
31
31
  type: Number,
32
32
  default: 25
33
33
  },
34
-
34
+
35
35
  /**
36
36
  * Sets the maximum height for Text Area. Prevents the height from becoming
37
37
  * larger than the value specified in maxHeight.
@@ -50,7 +50,7 @@ export default Vue.extend({
50
50
  },
51
51
 
52
52
  /**
53
- * Specifies whether Text Area is subject to spell checking by the
53
+ * Specifies whether Text Area is subject to spell checking by the
54
54
  * underlying browser/OS.
55
55
  */
56
56
  spellcheck: {
@@ -83,7 +83,7 @@ export default Vue.extend({
83
83
  },
84
84
 
85
85
  /**
86
- * Sets the height to one-line for SSR pageload so that it's already right
86
+ * Sets the height to one-line for SSR pageload so that it's already right
87
87
  * (unless the input is long)
88
88
  */
89
89
  style(): string {
@@ -112,7 +112,7 @@ export default Vue.extend({
112
112
  },
113
113
 
114
114
  methods: {
115
- /**
115
+ /**
116
116
  * Emits the input event and resizes the Text Area.
117
117
  */
118
118
  onInput(val: string): void {
@@ -128,7 +128,7 @@ export default Vue.extend({
128
128
  },
129
129
 
130
130
  /**
131
- * Sets the overflowY and height of the Text Area based on the content
131
+ * Sets the overflowY and height of the Text Area based on the content
132
132
  * entered (calculated via scroll height).
133
133
  */
134
134
  autoSize(): void {
@@ -155,6 +155,7 @@ export default Vue.extend({
155
155
  <template>
156
156
  <textarea
157
157
  ref="ta"
158
+ data-testid="text-area-auto-grow"
158
159
  :disabled="isDisabled"
159
160
  :style="style"
160
161
  :placeholder="placeholder"