@rancher/shell 1.2.0 → 1.2.2

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 (57) hide show
  1. package/package.json +1 -1
  2. package/rancher-components/BadgeState/BadgeState.vue +3 -3
  3. package/rancher-components/Banner/Banner.test.ts +5 -1
  4. package/rancher-components/Banner/Banner.vue +2 -2
  5. package/rancher-components/Card/Card.vue +4 -4
  6. package/rancher-components/Form/Checkbox/Checkbox.vue +3 -4
  7. package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +1 -18
  8. package/rancher-components/Form/LabeledInput/LabeledInput.vue +37 -65
  9. package/rancher-components/Form/Radio/RadioButton.test.ts +3 -1
  10. package/rancher-components/Form/Radio/RadioButton.vue +7 -13
  11. package/rancher-components/Form/Radio/RadioGroup.vue +3 -4
  12. package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +4 -6
  13. package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +4 -7
  14. package/rancher-components/LabeledTooltip/LabeledTooltip.vue +4 -9
  15. package/rancher-components/StringList/StringList.test.ts +0 -270
  16. package/rancher-components/StringList/StringList.vue +26 -65
  17. package/scripts/publish-shell.sh +1 -0
  18. package/types/shell/index.d.ts +5 -5
  19. package/rancher-components/Accordion/Accordion.test.ts +0 -45
  20. package/rancher-components/Accordion/Accordion.vue +0 -86
  21. package/rancher-components/Accordion/index.ts +0 -1
  22. package/rancher-components/BadgeState/BadgeState.test.ts +0 -12
  23. package/rancher-components/components/Accordion/Accordion.test.ts +0 -45
  24. package/rancher-components/components/Accordion/Accordion.vue +0 -86
  25. package/rancher-components/components/Accordion/index.ts +0 -1
  26. package/rancher-components/components/BadgeState/BadgeState.test.ts +0 -12
  27. package/rancher-components/components/BadgeState/BadgeState.vue +0 -111
  28. package/rancher-components/components/BadgeState/index.ts +0 -1
  29. package/rancher-components/components/Banner/Banner.test.ts +0 -63
  30. package/rancher-components/components/Banner/Banner.vue +0 -244
  31. package/rancher-components/components/Banner/index.ts +0 -1
  32. package/rancher-components/components/Card/Card.test.ts +0 -37
  33. package/rancher-components/components/Card/Card.vue +0 -167
  34. package/rancher-components/components/Card/index.ts +0 -1
  35. package/rancher-components/components/Form/Checkbox/Checkbox.test.ts +0 -68
  36. package/rancher-components/components/Form/Checkbox/Checkbox.vue +0 -420
  37. package/rancher-components/components/Form/Checkbox/index.ts +0 -1
  38. package/rancher-components/components/Form/LabeledInput/LabeledInput.test.ts +0 -23
  39. package/rancher-components/components/Form/LabeledInput/LabeledInput.vue +0 -369
  40. package/rancher-components/components/Form/LabeledInput/index.ts +0 -1
  41. package/rancher-components/components/Form/Radio/RadioButton.test.ts +0 -35
  42. package/rancher-components/components/Form/Radio/RadioButton.vue +0 -287
  43. package/rancher-components/components/Form/Radio/RadioGroup.test.ts +0 -30
  44. package/rancher-components/components/Form/Radio/RadioGroup.vue +0 -258
  45. package/rancher-components/components/Form/Radio/index.ts +0 -2
  46. package/rancher-components/components/Form/TextArea/TextAreaAutoGrow.vue +0 -170
  47. package/rancher-components/components/Form/TextArea/index.ts +0 -1
  48. package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.test.ts +0 -94
  49. package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.vue +0 -149
  50. package/rancher-components/components/Form/ToggleSwitch/index.ts +0 -1
  51. package/rancher-components/components/Form/index.ts +0 -5
  52. package/rancher-components/components/LabeledTooltip/LabeledTooltip.vue +0 -151
  53. package/rancher-components/components/LabeledTooltip/index.ts +0 -1
  54. package/rancher-components/components/StringList/StringList.test.ts +0 -484
  55. package/rancher-components/components/StringList/StringList.vue +0 -611
  56. package/rancher-components/components/StringList/index.ts +0 -1
  57. /package/rancher-components/{components/BadgeState → BadgeState}/BadgeState.spec.ts +0 -0
@@ -1,369 +0,0 @@
1
- <script lang="ts">
2
- import Vue, { VueConstructor } from 'vue';
3
- import CompactInput from '@shell/mixins/compact-input';
4
- import LabeledFormElement from '@shell/mixins/labeled-form-element';
5
- import TextAreaAutoGrow from '@components/Form/TextArea/TextAreaAutoGrow.vue';
6
- import LabeledTooltip from '@components/LabeledTooltip/LabeledTooltip.vue';
7
- import { escapeHtml } from '@shell/utils/string';
8
- import cronstrue from 'cronstrue';
9
- import { isValidCron } from 'cron-validator';
10
- import { debounce } from 'lodash';
11
-
12
- export default (
13
- Vue as VueConstructor<Vue & InstanceType<typeof LabeledFormElement> & InstanceType<typeof CompactInput>>
14
- ).extend({
15
- components: { LabeledTooltip, TextAreaAutoGrow },
16
- mixins: [LabeledFormElement, CompactInput],
17
-
18
- props: {
19
- /**
20
- * The type of the Labeled Input.
21
- * @values text, cron, multiline, multiline-password
22
- */
23
- type: {
24
- type: String,
25
- default: 'text'
26
- },
27
-
28
- /**
29
- * The status class of the Labeled Input and tooltip.
30
- * @values info, success, warning, error
31
- */
32
- status: {
33
- type: String,
34
- default: null
35
- },
36
-
37
- /**
38
- * The sub-label for the Labeled Input.
39
- */
40
- subLabel: {
41
- type: String,
42
- default: null
43
- },
44
-
45
- /**
46
- * The tooltip to display for the Labeled Input.
47
- */
48
- tooltip: {
49
- default: null,
50
- type: [String, Object]
51
- },
52
-
53
- /**
54
- * Renders the tooltip when hovering the cursor over the Labeled Input.
55
- */
56
- hoverTooltip: {
57
- type: Boolean,
58
- default: true
59
- },
60
-
61
- /**
62
- * Disables the password manager prompt to save the contents of the Labeled
63
- * Input.
64
- */
65
- ignorePasswordManagers: {
66
- default: false,
67
- type: Boolean
68
- },
69
-
70
- /**
71
- * The max length of the Labeled Input.
72
- */
73
- maxlength: {
74
- type: Number,
75
- default: null
76
- },
77
-
78
- /**
79
- * Hides arrows on the Labeled Input.
80
- * @deprecated This doesn't appear to be in use for Labeled Input.
81
- */
82
- hideArrows: {
83
- type: Boolean,
84
- default: false
85
- },
86
-
87
- /**
88
- * Optionally delay on input while typing.
89
- */
90
- delay: {
91
- type: Number,
92
- default: 0
93
- }
94
- },
95
-
96
- data() {
97
- return {
98
- updated: false,
99
- validationErrors: ''
100
- };
101
- },
102
-
103
- computed: {
104
- /**
105
- * Determines if the Labeled Input @input event should be debounced.
106
- */
107
- onInput(): ((value: string) => void) | void {
108
- return this.delay ? debounce(this.delayInput, this.delay) : this.delayInput;
109
- },
110
-
111
- /**
112
- * Determines if the Labeled Input should display a label.
113
- */
114
- hasLabel(): boolean {
115
- return this.isCompact ? false : !!this.label || !!this.labelKey || !!this.$slots.label;
116
- },
117
-
118
- /**
119
- * Determines if the Labeled Input should display a tooltip.
120
- */
121
- hasTooltip(): boolean {
122
- return !!this.tooltip || !!this.tooltipKey;
123
- },
124
-
125
- tooltipValue(): string | undefined {
126
- if (this.hasTooltip) {
127
- return this.tooltipKey ? this.t(this.tooltipKey) : this.tooltip;
128
- }
129
-
130
- return undefined;
131
- },
132
-
133
- /**
134
- * Determines if the Labeled Input makes use of the suffix slot.
135
- */
136
- hasSuffix(): boolean {
137
- return !!this.$slots.suffix;
138
- },
139
-
140
- /**
141
- * Determines if the Labeled Input should display a cron hint.
142
- */
143
- cronHint(): string | undefined {
144
- if (this.type !== 'cron' || !this.value) {
145
- return;
146
- }
147
- if (!isValidCron(this.value)) {
148
- return this.t('generic.invalidCron');
149
- }
150
- try {
151
- const hint = cronstrue.toString(this.value);
152
-
153
- return hint;
154
- } catch (e) {
155
- return this.t('generic.invalidCron');
156
- }
157
- },
158
-
159
- /**
160
- * The placeholder value for the Labeled Input.
161
- */
162
- _placeholder(): string {
163
- if (this.placeholder) {
164
- return this.placeholder.toString();
165
- }
166
- if (this.placeholderKey) {
167
- return this.t(this.placeholderKey);
168
- }
169
-
170
- return '';
171
- },
172
-
173
- /**
174
- * The max length for the Labeled Input.
175
- */
176
- _maxlength(): number | null {
177
- if (this.type === 'text' && this.maxlength) {
178
- return this.maxlength;
179
- }
180
-
181
- return null;
182
- },
183
- },
184
-
185
- methods: {
186
- /**
187
- * Attempts to give the Labeled Input focus.
188
- */
189
- focus(): void {
190
- const comp = this.$refs.value as HTMLInputElement;
191
-
192
- if (comp) {
193
- comp.focus();
194
- }
195
- },
196
-
197
- /**
198
- * Attempts to select the Labeled Input.
199
- * @deprecated
200
- */
201
- select(): void {
202
- const comp = this.$refs.value as HTMLInputElement;
203
-
204
- if (comp) {
205
- comp.select();
206
- }
207
- },
208
-
209
- /**
210
- * Emit on input change
211
- */
212
- onChange(event: Event): void {
213
- this.$emit('change', event);
214
- },
215
-
216
- /**
217
- * Emit on input with delay. Note: Arrow function is avoided due context
218
- * binding.
219
- */
220
- delayInput(value: string): void {
221
- this.$emit('input', value);
222
- },
223
-
224
- /**
225
- * Handles the behavior of the Labeled Input when given focus.
226
- * @see labeled-form-element.ts mixin for onFocusLabeled()
227
- */
228
- onFocus(): void {
229
- this.onFocusLabeled();
230
- },
231
-
232
- /**
233
- * Handles the behavior of the Labeled Input when blurred and emits the blur
234
- * event.
235
- * @see labeled-form-element.ts mixin for onBlurLabeled()
236
- */
237
- onBlur(event: string): void {
238
- this.$emit('blur', event);
239
- this.onBlurLabeled();
240
- },
241
-
242
- escapeHtml
243
- }
244
- });
245
- </script>
246
-
247
- <template>
248
- <div
249
- :class="{
250
- 'labeled-input': true,
251
- focused,
252
- [mode]: true,
253
- disabled: isDisabled,
254
- [status]: status,
255
- suffix: hasSuffix,
256
- 'has-tooltip': hasTooltip,
257
- 'compact-input': isCompact,
258
- hideArrows
259
- }"
260
- >
261
- <slot name="label">
262
- <label v-if="hasLabel">
263
- <t
264
- v-if="labelKey"
265
- :k="labelKey"
266
- />
267
- <template v-else-if="label">{{ label }}</template>
268
-
269
- <span
270
- v-if="requiredField"
271
- class="required"
272
- >*</span>
273
- </label>
274
- </slot>
275
-
276
- <slot name="prefix" />
277
-
278
- <slot name="field">
279
- <TextAreaAutoGrow
280
- v-if="type === 'multiline' || type === 'multiline-password'"
281
- ref="value"
282
- v-bind="$attrs"
283
- :maxlength="_maxlength"
284
- :disabled="isDisabled"
285
- :value="value"
286
- :placeholder="_placeholder"
287
- autocapitalize="off"
288
- :class="{ conceal: type === 'multiline-password' }"
289
- @input="onInput($event)"
290
- @focus="onFocus"
291
- @blur="onBlur"
292
- />
293
- <input
294
- v-else
295
- ref="value"
296
- :class="{ 'no-label': !hasLabel }"
297
- v-bind="$attrs"
298
- :maxlength="_maxlength"
299
- :disabled="isDisabled"
300
- :type="type === 'cron' ? 'text' : type"
301
- :value="value"
302
- :placeholder="_placeholder"
303
- autocomplete="off"
304
- autocapitalize="off"
305
- :data-lpignore="ignorePasswordManagers"
306
- @input="onInput($event.target.value)"
307
- @focus="onFocus"
308
- @blur="onBlur"
309
- @change="onChange"
310
- >
311
- </slot>
312
-
313
- <slot name="suffix" />
314
- <LabeledTooltip
315
- v-if="hasTooltip && !focused"
316
- :hover="hoverTooltip"
317
- :value="tooltipValue"
318
- :status="status"
319
- />
320
- <LabeledTooltip
321
- v-if="!!validationMessage"
322
- :hover="hoverTooltip"
323
- :value="validationMessage"
324
- />
325
- <div
326
- v-if="cronHint || subLabel"
327
- class="sub-label"
328
- >
329
- <div
330
- v-if="cronHint"
331
- >
332
- {{ cronHint }}
333
- </div>
334
- <div
335
- v-if="subLabel"
336
- v-clean-html="subLabel"
337
- />
338
- </div>
339
- </div>
340
- </template>
341
- <style scoped lang="scss">
342
- .labeled-input.view {
343
- input {
344
- text-overflow: ellipsis;
345
- }
346
- }
347
-
348
- .hideArrows {
349
- /* Hide arrows on number input when it overlaps with the unit */
350
- /* Chrome, Safari, Edge, Opera */
351
- input::-webkit-outer-spin-button,
352
- input::-webkit-inner-spin-button {
353
- -webkit-appearance: none;
354
- margin: 0;
355
- }
356
-
357
- /* Firefox */
358
- input[type=number] {
359
- -moz-appearance: textfield;
360
- }
361
- }
362
- </style>
363
- <style>
364
- .validation-message {
365
- padding: 5px;
366
- position: absolute;
367
- bottom: -35px;
368
- }
369
- </style>
@@ -1 +0,0 @@
1
- export { default as LabeledInput } from './LabeledInput.vue';
@@ -1,35 +0,0 @@
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' }, propsData: { val: {}, value: {} } });
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: {
18
- label: 'Test Label', val: {}, value: {}
19
- }
20
- });
21
-
22
- expect(wrapper.find('.radio-label').text()).toBe('Test Label');
23
- });
24
-
25
- it('renders slot contents when both slot and label prop are provided', () => {
26
- const wrapper = shallowMount(RadioButton, {
27
- slots: { label: 'Test Label - Slot' },
28
- propsData: {
29
- label: 'Test Label - Props', val: {}, value: {}
30
- },
31
- });
32
-
33
- expect(wrapper.find('.radio-label').text()).toBe('Test Label - Slot');
34
- });
35
- });
@@ -1,287 +0,0 @@
1
- <script lang="ts">
2
- import Vue from 'vue';
3
- import { _VIEW } from '@shell/config/query-params';
4
-
5
- export default Vue.extend({
6
- props: {
7
- /**
8
- * The name of the input, for grouping.
9
- */
10
- name: {
11
- type: String,
12
- default: ''
13
- },
14
-
15
- /**
16
- * The value for this option.
17
- */
18
- val: {
19
- required: true,
20
- validator: () => true
21
- },
22
-
23
- /**
24
- * The selected value.
25
- */
26
- value: {
27
- required: true,
28
- validator: () => true
29
- },
30
-
31
- /**
32
- * The label shown next to the radio.
33
- */
34
- label: {
35
- type: String,
36
- default: ''
37
- },
38
-
39
- /**
40
- * Disable the radio.
41
- */
42
- disabled: {
43
- type: Boolean,
44
- default: false
45
- },
46
-
47
- /**
48
- * The radio editing mode.
49
- * @values _EDIT, _VIEW
50
- */
51
- mode: {
52
- type: String,
53
- default: 'edit'
54
- },
55
-
56
- /**
57
- * The i18n key to use for the radio description.
58
- */
59
- descriptionKey: {
60
- type: String,
61
- default: null
62
- },
63
-
64
- /**
65
- * The radio description.
66
- */
67
- description: {
68
- type: String,
69
- default: null
70
- }
71
- },
72
-
73
- data() {
74
- return { isChecked: this.value === this.val };
75
- },
76
-
77
- computed: {
78
- /**
79
- * Determines if the radio is disabled.
80
- */
81
- isDisabled(): boolean {
82
- return this.mode === _VIEW || this.disabled;
83
- },
84
-
85
- /**
86
- * Determines if the label for the radio should be muted.
87
- */
88
- muteLabel(): boolean {
89
- // Don't mute the label if the mode is view and the button is checked
90
- return this.disabled && !(this.mode === _VIEW && this.isChecked);
91
- },
92
-
93
- /**
94
- * Determines if the description slot is in use.
95
- */
96
- hasDescriptionSlot(): boolean {
97
- return !!this.$slots.description;
98
- },
99
-
100
- hasLabelSlot(): boolean {
101
- return !!this.$slots.label || !!this.$scopedSlots.label;
102
- }
103
- },
104
-
105
- watch: {
106
- value(neu) {
107
- this.isChecked = this.val === neu;
108
- if (this.isChecked) {
109
- (this.$refs.custom as HTMLElement).focus();
110
- }
111
- }
112
- },
113
-
114
- methods: {
115
- /**
116
- * Emits the input event.
117
- */
118
- clicked({ target }: { target?: HTMLElement }) {
119
- if (this.isDisabled || target?.tagName === 'A') {
120
- return;
121
- }
122
-
123
- this.$emit('input', this.val);
124
- }
125
- }
126
- });
127
- </script>
128
-
129
- <template>
130
- <label
131
- :class="{'disabled': isDisabled, 'radio-container': true}"
132
- @keydown.enter="clicked($event)"
133
- @keydown.space="clicked($event)"
134
- @click.stop="clicked($event)"
135
- >
136
- <input
137
- :id="_uid+'-radio'"
138
- :disabled="isDisabled"
139
- :name="name"
140
- :value="''+val"
141
- :checked="isChecked"
142
- type="radio"
143
- :tabindex="-1"
144
- @click.stop.prevent
145
- >
146
- <span
147
- ref="custom"
148
- :class="[ isDisabled ? 'text-muted' : '', 'radio-custom']"
149
- :tabindex="isDisabled ? -1 : 0"
150
- :aria-label="label"
151
- :aria-checked="isChecked"
152
- role="radio"
153
- />
154
- <div class="labeling">
155
- <label
156
- :class="[ muteLabel ? 'text-muted' : '', 'radio-label', 'm-0']"
157
- :for="name"
158
- >
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
- />
169
- </label>
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
- />
178
- <template v-else-if="description">
179
- {{ description }}
180
- </template>
181
- </div>
182
- <div
183
- v-else-if="hasDescriptionSlot"
184
- class="radio-button-outer-container-description"
185
- >
186
- <slot name="description" />
187
- </div>
188
- </div>
189
- </label>
190
- </template>
191
-
192
- <style lang='scss'>
193
- $fontColor: var(--input-label);
194
-
195
- .radio-view {
196
- display: flex;
197
- flex-direction: column;
198
- LABEL {
199
- color: var(--input-label);
200
- }
201
- }
202
-
203
- .radio-group {
204
- .text-label {
205
- display: block;
206
- padding-bottom: 5px;
207
- }
208
- }
209
-
210
- .radio-container {
211
- position: relative;
212
- display: inline-flex;
213
- align-items: flex-start;
214
- margin: 0;
215
- user-select: none;
216
- border-radius: var(--border-radius);
217
- padding-bottom: 5px;
218
-
219
- &,
220
- .radio-label,
221
- .radio-button-outer-container-description {
222
- cursor: pointer;
223
- }
224
-
225
- &.disabled,
226
- &.disabled .radio-label,
227
- &.disabled .radio-button-outer-container-description {
228
- cursor: not-allowed
229
- }
230
-
231
- .radio-custom {
232
- height: 14px;
233
- width: 14px;
234
- min-height: 14px;
235
- min-width: 14px;
236
- background-color: var(--input-bg);
237
- border-radius: 50%;
238
- transition: all 0.3s ease-out;
239
- border: 1.5px solid var(--border);
240
- margin-top: 5px;
241
-
242
- &:focus {
243
- outline: none;
244
- border-radius: 50%;
245
- }
246
- }
247
-
248
- input {
249
- display: none;
250
- }
251
-
252
- .radio-custom {
253
- &[aria-checked="true"] {
254
- background-color: var(--primary);
255
- -webkit-transform: rotate(0deg) scale(1);
256
- -ms-transform: rotate(0deg) scale(1);
257
- transform: rotate(0deg) scale(1);
258
- opacity:1;
259
- border: 1.5px solid var(--primary);
260
-
261
- // Ensure that checked radio buttons are muted but still visibly selected when muted
262
- &.text-muted {
263
- opacity: .25;
264
- }
265
- }
266
- }
267
-
268
- input:disabled ~ .radio-custom:not([aria-checked="true"]) {
269
- background-color: var(--disabled-bg);
270
- opacity: .25;
271
- }
272
-
273
- .radio-button-outer-container-description {
274
- color: $fontColor;
275
- font-size: 11px;
276
- margin-top: 5px;
277
- }
278
-
279
- .labeling {
280
- display: inline-flex;
281
- flex-direction: column;
282
-
283
- margin: 3px 10px 0px 5px;
284
- }
285
- }
286
-
287
- </style>
@@ -1,30 +0,0 @@
1
- import { mount } from '@vue/test-utils';
2
- import { RadioGroup } from './index';
3
-
4
- describe('component: RadioGroup', () => {
5
- describe('when disabled', () => {
6
- it.each([true, false])('should expose disabled slot prop for indexed slots for %p', (disabled) => {
7
- const wrapper = mount(RadioGroup, {
8
- propsData: {
9
- name: 'whatever',
10
- options: [{ label: 'whatever', value: 'whatever' }],
11
- disabled
12
- },
13
- scopedSlots: {
14
- 0(props: {isDisabled: boolean}) {
15
- return this.$createElement('input', {
16
- attrs: {
17
- id: 'test',
18
- disabled: props.isDisabled
19
- }
20
- });
21
- }
22
- }
23
- });
24
-
25
- const slot = wrapper.find('#test').element as HTMLInputElement;
26
-
27
- expect(slot.disabled).toBe(disabled);
28
- });
29
- });
30
- });