@rancher/shell 2.0.0 → 2.0.2-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/translations/en-us.yaml +69 -29
- package/assets/translations/zh-hans.yaml +1 -0
- package/components/AlertTable.vue +17 -7
- package/components/AssignTo.vue +2 -0
- package/components/GrafanaDashboard.vue +6 -4
- package/components/PromptRemove.vue +1 -0
- package/components/Questions/index.vue +2 -2
- package/components/auth/RoleDetailEdit.vue +5 -4
- package/components/form/KeyValue.vue +1 -0
- package/components/form/Members/ClusterPermissionsEditor.vue +1 -1
- package/components/form/ProjectMemberEditor.vue +1 -1
- package/components/form/ResourceLabeledSelect.vue +11 -3
- package/components/form/Taints.vue +13 -7
- package/components/form/__tests__/Taints.test.ts +70 -0
- package/components/form/labeled-select-utils/labeled-select.utils.ts +1 -1
- package/components/nav/Header.vue +1 -1
- package/components/nav/TopLevelMenu.vue +1 -4
- package/config/pagination-table-headers.js +5 -4
- package/config/product/auth.js +1 -1
- package/config/roles.ts +34 -19
- package/config/router/navigation-guards/attempt-first-login.js +1 -1
- package/config/router/navigation-guards/authentication.js +1 -1
- package/config/router/navigation-guards/i18n.js +13 -0
- package/config/router/navigation-guards/index.js +3 -1
- package/config/router/navigation-guards/load-initial-settings.js +1 -1
- package/config/router/navigation-guards/runtime-extension-route.js +31 -0
- package/config/router/routes.js +10 -1
- package/config/uiplugins.js +130 -61
- package/core/plugin.ts +5 -0
- package/core/plugins.js +7 -1
- package/detail/__tests__/provisioning.cattle.io.cluster.test.ts +42 -0
- package/detail/provisioning.cattle.io.cluster.vue +4 -4
- package/dialog/DeactivateDriverDialog.vue +30 -11
- package/edit/auth/__tests__/oidc.test.ts +2 -2
- package/edit/provisioning.cattle.io.cluster/__tests__/Basics.test.ts +86 -13
- package/edit/provisioning.cattle.io.cluster/__tests__/DirectoryConfig.test.ts +3 -134
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +209 -0
- package/edit/provisioning.cattle.io.cluster/index.vue +8 -4
- package/edit/provisioning.cattle.io.cluster/rke2.vue +115 -17
- package/edit/provisioning.cattle.io.cluster/tabs/AddOnAdditionalManifest.vue +50 -0
- package/edit/provisioning.cattle.io.cluster/tabs/AddOnConfig.vue +29 -64
- package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +42 -3
- package/edit/provisioning.cattle.io.cluster/tabs/DirectoryConfig.vue +22 -86
- package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +8 -2
- package/edit/provisioning.cattle.io.cluster/tabs/registries/__tests__/RegistryConfigs.test.ts +61 -0
- package/edit/token.vue +2 -1
- package/initialize/entry-helpers.js +4 -24
- package/list/management.cattle.io.feature.vue +4 -2
- package/middleware/authenticated.js +0 -19
- package/mixins/__tests__/chart.test.ts +4 -1
- package/mixins/auth-config.js +1 -1
- package/mixins/chart.js +30 -14
- package/models/__tests__/apps.deployment.test.ts +93 -0
- package/models/apps.deployment.js +18 -4
- package/models/driver.js +3 -2
- package/models/kontainerdriver.js +30 -13
- package/models/management.cattle.io.authconfig.js +2 -2
- package/models/management.cattle.io.cluster.js +2 -2
- package/models/management.cattle.io.user.js +3 -3
- package/models/nodedriver.js +35 -13
- package/models/provisioning.cattle.io.cluster.js +4 -0
- package/package.json +3 -2
- package/pages/404.vue +15 -0
- package/pages/auth/login.vue +4 -1
- package/pages/auth/setup.vue +4 -1
- package/pages/c/_cluster/apps/charts/install.vue +3 -2
- package/pages/c/_cluster/explorer/index.vue +5 -0
- package/pages/c/_cluster/manager/drivers/kontainerDriver/index.vue +0 -3
- package/pages/c/_cluster/manager/drivers/nodeDriver/index.vue +1 -4
- package/pages/c/_cluster/manager/jwt.authentication/index.vue +10 -4
- package/pages/c/_cluster/settings/performance.vue +2 -2
- package/pages/c/_cluster/uiplugins/InstallDialog.vue +2 -1
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +7 -10
- package/pages/c/_cluster/uiplugins/index.vue +24 -16
- package/pages/home.vue +1 -13
- package/plugins/dashboard-store/actions.js +1 -1
- package/plugins/dashboard-store/getters.js +1 -1
- package/plugins/steve/__tests__/getters.test.ts +5 -5
- package/plugins/steve/getters.js +6 -4
- package/plugins/steve/hybrid-class.js +1 -5
- package/promptRemove/pod.vue +15 -7
- package/scripts/extension/helm/charts/ui-plugin-server/Chart.yaml +1 -1
- package/scripts/publish-shell.sh +54 -55
- package/scripts/test-plugins-build.sh +45 -39
- package/shell/types/shell/index.d.ts +2 -0
- package/store/auth.js +1 -1
- package/store/index.js +1 -1
- package/store/type-map.js +4 -2
- package/types/store/pagination.types.ts +1 -1
- package/utils/__tests__/kontainer.test.ts +89 -1
- package/utils/auth.js +1 -1
- package/utils/cluster.js +9 -0
- package/utils/kontainer.ts +5 -1
- package/utils/settings.ts +3 -1
- package/utils/version.js +2 -1
- package/creators/app/app.package.json +0 -13
- package/creators/app/files/.eslintignore +0 -16
- package/creators/app/files/.eslintrc.js +0 -173
- package/creators/app/files/.gitignore +0 -70
- package/creators/app/files/.gitlab-ci.yml +0 -14
- package/creators/app/files/.vscode/settings.json +0 -21
- package/creators/app/files/babel.config.js +0 -1
- package/creators/app/files/tsconfig.json +0 -42
- package/creators/app/files/vue.config.js +0 -6
- package/creators/app/init +0 -120
- package/creators/app/package.json +0 -25
- package/creators/pkg/files/.github/workflows/build-extension-catalog.yml +0 -24
- package/creators/pkg/files/.github/workflows/build-extension-charts.yml +0 -22
- package/creators/pkg/files/babel.config.js +0 -1
- package/creators/pkg/files/index.ts +0 -14
- package/creators/pkg/files/tsconfig.json +0 -53
- package/creators/pkg/files/vue.config.js +0 -1
- package/creators/pkg/init +0 -286
- package/creators/pkg/package.json +0 -19
- package/creators/pkg/pkg.package.json +0 -21
- package/creators/pkg/vue-shim.ts +0 -4
- package/creators/update/init +0 -56
- package/creators/update/package.json +0 -20
- package/creators/update/upgrade +0 -56
- package/rancher-components/components/Accordion/Accordion.test.ts +0 -45
- package/rancher-components/components/Accordion/Accordion.vue +0 -86
- package/rancher-components/components/Accordion/index.ts +0 -1
- package/rancher-components/components/BadgeState/BadgeState.test.ts +0 -12
- package/rancher-components/components/BadgeState/BadgeState.vue +0 -111
- package/rancher-components/components/BadgeState/index.ts +0 -1
- package/rancher-components/components/Banner/Banner.test.ts +0 -59
- package/rancher-components/components/Banner/Banner.vue +0 -244
- package/rancher-components/components/Banner/index.ts +0 -1
- package/rancher-components/components/Card/Card.test.ts +0 -37
- package/rancher-components/components/Card/Card.vue +0 -167
- package/rancher-components/components/Card/index.ts +0 -1
- package/rancher-components/components/Form/Checkbox/Checkbox.test.ts +0 -68
- package/rancher-components/components/Form/Checkbox/Checkbox.vue +0 -421
- package/rancher-components/components/Form/Checkbox/index.ts +0 -1
- package/rancher-components/components/Form/LabeledInput/LabeledInput.test.ts +0 -40
- package/rancher-components/components/Form/LabeledInput/LabeledInput.vue +0 -402
- package/rancher-components/components/Form/LabeledInput/index.ts +0 -1
- package/rancher-components/components/Form/Radio/RadioButton.test.ts +0 -33
- package/rancher-components/components/Form/Radio/RadioButton.vue +0 -293
- package/rancher-components/components/Form/Radio/RadioGroup.test.ts +0 -30
- package/rancher-components/components/Form/Radio/RadioGroup.vue +0 -259
- package/rancher-components/components/Form/Radio/index.ts +0 -2
- package/rancher-components/components/Form/TextArea/TextAreaAutoGrow.vue +0 -172
- package/rancher-components/components/Form/TextArea/index.ts +0 -1
- package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.test.ts +0 -94
- package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.vue +0 -152
- package/rancher-components/components/Form/ToggleSwitch/index.ts +0 -1
- package/rancher-components/components/Form/index.ts +0 -5
- package/rancher-components/components/LabeledTooltip/LabeledTooltip.vue +0 -156
- package/rancher-components/components/LabeledTooltip/index.ts +0 -1
- package/rancher-components/components/StringList/StringList.test.ts +0 -754
- package/rancher-components/components/StringList/StringList.vue +0 -650
- package/rancher-components/components/StringList/index.ts +0 -1
- package/types/shell/index.d.ts +0 -4585
|
@@ -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
|
-
});
|
|
@@ -1,259 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { PropType, defineComponent } from 'vue';
|
|
3
|
-
import { _VIEW } from '@shell/config/query-params';
|
|
4
|
-
import RadioButton from '@components/Form/Radio/RadioButton.vue';
|
|
5
|
-
|
|
6
|
-
interface Option {
|
|
7
|
-
value: unknown,
|
|
8
|
-
label: string,
|
|
9
|
-
description?: string,
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export default defineComponent({
|
|
13
|
-
components: { RadioButton },
|
|
14
|
-
props: {
|
|
15
|
-
/**
|
|
16
|
-
* Name for the checkbox grouping, must be unique on page.
|
|
17
|
-
*/
|
|
18
|
-
name: {
|
|
19
|
-
type: String,
|
|
20
|
-
required: true
|
|
21
|
-
},
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Options can be an array of {label, value}, or just values.
|
|
25
|
-
*/
|
|
26
|
-
options: {
|
|
27
|
-
type: Array as PropType<Option[] | string[]>,
|
|
28
|
-
required: true
|
|
29
|
-
},
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* If options are just values, then labels can be a corresponding display
|
|
33
|
-
* value.
|
|
34
|
-
*/
|
|
35
|
-
labels: {
|
|
36
|
-
type: Array as PropType<string[]>,
|
|
37
|
-
default: null
|
|
38
|
-
},
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* The selected value.
|
|
42
|
-
*/
|
|
43
|
-
value: {
|
|
44
|
-
type: [Boolean, String, Object],
|
|
45
|
-
default: null
|
|
46
|
-
},
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Disable the radio group.
|
|
50
|
-
*/
|
|
51
|
-
disabled: {
|
|
52
|
-
type: Boolean,
|
|
53
|
-
default: false
|
|
54
|
-
},
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* The radio group editing mode.
|
|
58
|
-
* @values _EDIT, _VIEW
|
|
59
|
-
*/
|
|
60
|
-
mode: {
|
|
61
|
-
type: String,
|
|
62
|
-
default: 'edit'
|
|
63
|
-
},
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Label for above the radios.
|
|
67
|
-
*/
|
|
68
|
-
label: {
|
|
69
|
-
type: String,
|
|
70
|
-
default: null
|
|
71
|
-
},
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* The i18n key to use for the radio group label.
|
|
75
|
-
*/
|
|
76
|
-
labelKey: {
|
|
77
|
-
type: String,
|
|
78
|
-
default: null
|
|
79
|
-
},
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Radio group tooltip.
|
|
83
|
-
*/
|
|
84
|
-
tooltip: {
|
|
85
|
-
type: [String, Object],
|
|
86
|
-
default: null
|
|
87
|
-
},
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* The i18n key to use for the radio group tooltip.
|
|
91
|
-
*/
|
|
92
|
-
tooltipKey: {
|
|
93
|
-
type: String,
|
|
94
|
-
default: null
|
|
95
|
-
},
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Show radio buttons in column or row.
|
|
99
|
-
*/
|
|
100
|
-
row: {
|
|
101
|
-
type: Boolean,
|
|
102
|
-
default: false
|
|
103
|
-
}
|
|
104
|
-
},
|
|
105
|
-
|
|
106
|
-
computed: {
|
|
107
|
-
/**
|
|
108
|
-
* Creates a collection of Options from the provided props.
|
|
109
|
-
*/
|
|
110
|
-
normalizedOptions(): Option[] {
|
|
111
|
-
const out: Option[] = [];
|
|
112
|
-
|
|
113
|
-
for (let i = 0; i < this.options.length; i++) {
|
|
114
|
-
const opt = this.options[i];
|
|
115
|
-
|
|
116
|
-
if (typeof opt === 'object' && opt) {
|
|
117
|
-
out.push(opt);
|
|
118
|
-
} else if (this.labels) {
|
|
119
|
-
out.push({
|
|
120
|
-
label: this.labels[i],
|
|
121
|
-
value: opt
|
|
122
|
-
});
|
|
123
|
-
} else {
|
|
124
|
-
out.push({
|
|
125
|
-
label: opt,
|
|
126
|
-
value: opt
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
return out;
|
|
132
|
-
},
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Determines the view mode for the radio group.
|
|
136
|
-
*/
|
|
137
|
-
isView(): boolean {
|
|
138
|
-
return this.mode === _VIEW;
|
|
139
|
-
},
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Determines if the radio group is disabled.
|
|
143
|
-
*/
|
|
144
|
-
isDisabled(): boolean {
|
|
145
|
-
return (this.disabled || this.isView);
|
|
146
|
-
}
|
|
147
|
-
},
|
|
148
|
-
|
|
149
|
-
methods: {
|
|
150
|
-
/**
|
|
151
|
-
* Keyboard left/right event listener to select next/previous option. Emits
|
|
152
|
-
* the input event.
|
|
153
|
-
*/
|
|
154
|
-
clickNext(direction: number): void {
|
|
155
|
-
const opts = this.normalizedOptions;
|
|
156
|
-
const selected = opts.find((x) => x.value === this.value);
|
|
157
|
-
let newIndex = (selected ? opts.indexOf(selected) : -1) + direction;
|
|
158
|
-
|
|
159
|
-
if (newIndex >= opts.length) {
|
|
160
|
-
newIndex = opts.length - 1;
|
|
161
|
-
} else if (newIndex < 0) {
|
|
162
|
-
newIndex = 0;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
this.$emit('input', opts[newIndex].value);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
});
|
|
169
|
-
</script>
|
|
170
|
-
|
|
171
|
-
<template>
|
|
172
|
-
<div>
|
|
173
|
-
<!-- Label -->
|
|
174
|
-
<div
|
|
175
|
-
v-if="label || labelKey || tooltip || tooltipKey || $slots.label"
|
|
176
|
-
class="radio-group label"
|
|
177
|
-
>
|
|
178
|
-
<slot name="label">
|
|
179
|
-
<h3>
|
|
180
|
-
<t
|
|
181
|
-
v-if="labelKey"
|
|
182
|
-
:k="labelKey"
|
|
183
|
-
/>
|
|
184
|
-
<template v-else-if="label">
|
|
185
|
-
{{ label }}
|
|
186
|
-
</template>
|
|
187
|
-
<i
|
|
188
|
-
v-if="tooltipKey"
|
|
189
|
-
v-clean-tooltip="t(tooltipKey)"
|
|
190
|
-
class="icon icon-info icon-lg"
|
|
191
|
-
/>
|
|
192
|
-
<i
|
|
193
|
-
v-else-if="tooltip"
|
|
194
|
-
v-clean-tooltip="tooltip"
|
|
195
|
-
class="icon icon-info icon-lg"
|
|
196
|
-
/>
|
|
197
|
-
</h3>
|
|
198
|
-
</slot>
|
|
199
|
-
</div>
|
|
200
|
-
|
|
201
|
-
<!-- Group -->
|
|
202
|
-
<div
|
|
203
|
-
class="radio-group"
|
|
204
|
-
:class="{'row':row}"
|
|
205
|
-
tabindex="0"
|
|
206
|
-
@keyup.down.stop="clickNext(1)"
|
|
207
|
-
@keyup.up.stop="clickNext(-1)"
|
|
208
|
-
>
|
|
209
|
-
<div
|
|
210
|
-
v-for="(option, i) in normalizedOptions"
|
|
211
|
-
:key="name+'-'+i"
|
|
212
|
-
>
|
|
213
|
-
<slot
|
|
214
|
-
:listeners="$listeners"
|
|
215
|
-
:option="option"
|
|
216
|
-
:is-disabled="isDisabled"
|
|
217
|
-
:name="i"
|
|
218
|
-
>
|
|
219
|
-
<!-- Default input -->
|
|
220
|
-
<RadioButton
|
|
221
|
-
:key="name+'-'+i"
|
|
222
|
-
:name="name"
|
|
223
|
-
:value="value"
|
|
224
|
-
:label="option.label"
|
|
225
|
-
:description="option.description"
|
|
226
|
-
:val="option.value"
|
|
227
|
-
:disabled="isDisabled"
|
|
228
|
-
:mode="mode"
|
|
229
|
-
v-on="$listeners"
|
|
230
|
-
/>
|
|
231
|
-
</slot>
|
|
232
|
-
</div>
|
|
233
|
-
</div>
|
|
234
|
-
</div>
|
|
235
|
-
</template>
|
|
236
|
-
|
|
237
|
-
<style lang='scss'>
|
|
238
|
-
.radio-group {
|
|
239
|
-
&:focus {
|
|
240
|
-
border:none;
|
|
241
|
-
outline:none;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
h3 {
|
|
245
|
-
position: relative;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
&.row {
|
|
249
|
-
display: flex;
|
|
250
|
-
.radio-container {
|
|
251
|
-
margin-right: 10px;
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
.label{
|
|
256
|
-
font-size: 14px !important;
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
</style>
|
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { defineComponent } from 'vue';
|
|
3
|
-
import debounce from 'lodash/debounce';
|
|
4
|
-
import { _EDIT, _VIEW } from '@shell/config/query-params';
|
|
5
|
-
|
|
6
|
-
declare module 'vue/types/vue' {
|
|
7
|
-
/* eslint-disable no-unused-vars */
|
|
8
|
-
interface Vue {
|
|
9
|
-
queueResize(): void;
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export default defineComponent({
|
|
14
|
-
inheritAttrs: false,
|
|
15
|
-
|
|
16
|
-
props: {
|
|
17
|
-
/**
|
|
18
|
-
* Sets the edit mode for Text Area.
|
|
19
|
-
* @values _EDIT, _VIEW
|
|
20
|
-
*/
|
|
21
|
-
mode: {
|
|
22
|
-
type: String,
|
|
23
|
-
default: _EDIT
|
|
24
|
-
},
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Sets the Minimum height for Text Area. Prevents the height from becoming
|
|
28
|
-
* smaller than the value specified in minHeight.
|
|
29
|
-
*/
|
|
30
|
-
minHeight: {
|
|
31
|
-
type: Number,
|
|
32
|
-
default: 25
|
|
33
|
-
},
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Sets the maximum height for Text Area. Prevents the height from becoming
|
|
37
|
-
* larger than the value specified in maxHeight.
|
|
38
|
-
*/
|
|
39
|
-
maxHeight: {
|
|
40
|
-
type: Number,
|
|
41
|
-
default: 200
|
|
42
|
-
},
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Text that appears in the Text Area when it has no value set.
|
|
46
|
-
*/
|
|
47
|
-
placeholder: {
|
|
48
|
-
type: String,
|
|
49
|
-
default: ''
|
|
50
|
-
},
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Specifies whether Text Area is subject to spell checking by the
|
|
54
|
-
* underlying browser/OS.
|
|
55
|
-
*/
|
|
56
|
-
spellcheck: {
|
|
57
|
-
type: Boolean,
|
|
58
|
-
default: true
|
|
59
|
-
},
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Disables the Text Area.
|
|
63
|
-
*/
|
|
64
|
-
disabled: {
|
|
65
|
-
type: Boolean,
|
|
66
|
-
default: false
|
|
67
|
-
}
|
|
68
|
-
},
|
|
69
|
-
|
|
70
|
-
data() {
|
|
71
|
-
return {
|
|
72
|
-
curHeight: this.minHeight,
|
|
73
|
-
overflow: 'hidden'
|
|
74
|
-
};
|
|
75
|
-
},
|
|
76
|
-
|
|
77
|
-
computed: {
|
|
78
|
-
/**
|
|
79
|
-
* Determines if the Text Area should be disabled.
|
|
80
|
-
*/
|
|
81
|
-
isDisabled(): boolean {
|
|
82
|
-
return this.disabled || this.mode === _VIEW;
|
|
83
|
-
},
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Sets the height to one-line for SSR pageload so that it's already right
|
|
87
|
-
* (unless the input is long)
|
|
88
|
-
*/
|
|
89
|
-
style(): string {
|
|
90
|
-
return `height: ${ this.curHeight }px; overflow: ${ this.overflow };`;
|
|
91
|
-
}
|
|
92
|
-
},
|
|
93
|
-
|
|
94
|
-
watch: {
|
|
95
|
-
$attrs: {
|
|
96
|
-
deep: true,
|
|
97
|
-
handler() {
|
|
98
|
-
this.queueResize();
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
},
|
|
102
|
-
|
|
103
|
-
created() {
|
|
104
|
-
this.queueResize = debounce(this.autoSize, 100);
|
|
105
|
-
},
|
|
106
|
-
|
|
107
|
-
mounted() {
|
|
108
|
-
(this.$refs.ta as HTMLElement).style.height = `${ this.curHeight }px`;
|
|
109
|
-
this.$nextTick(() => {
|
|
110
|
-
this.autoSize();
|
|
111
|
-
});
|
|
112
|
-
},
|
|
113
|
-
|
|
114
|
-
methods: {
|
|
115
|
-
/**
|
|
116
|
-
* Emits the input event and resizes the Text Area.
|
|
117
|
-
*/
|
|
118
|
-
onInput(event: Event): void {
|
|
119
|
-
const val = (event?.target as HTMLInputElement)?.value;
|
|
120
|
-
|
|
121
|
-
this.$emit('input', val);
|
|
122
|
-
this.queueResize();
|
|
123
|
-
},
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Gives focus to the Text Area.
|
|
127
|
-
*/
|
|
128
|
-
focus(): void {
|
|
129
|
-
(this.$refs?.ta as HTMLElement).focus();
|
|
130
|
-
},
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Sets the overflowY and height of the Text Area based on the content
|
|
134
|
-
* entered (calculated via scroll height).
|
|
135
|
-
*/
|
|
136
|
-
autoSize(): void {
|
|
137
|
-
const el = this.$refs.ta as HTMLElement;
|
|
138
|
-
|
|
139
|
-
if (!el) {
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
el.style.height = '1px';
|
|
144
|
-
|
|
145
|
-
const border = parseInt(getComputedStyle(el).getPropertyValue('borderTopWidth'), 10) || 0 + parseInt(getComputedStyle(el).getPropertyValue('borderBottomWidth'), 10) || 0;
|
|
146
|
-
const neu = Math.max(this.minHeight, Math.min(el.scrollHeight + border, this.maxHeight));
|
|
147
|
-
|
|
148
|
-
el.style.overflowY = el.scrollHeight > neu ? 'auto' : 'hidden';
|
|
149
|
-
el.style.height = `${ neu }px`;
|
|
150
|
-
|
|
151
|
-
this.curHeight = neu;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
});
|
|
155
|
-
</script>
|
|
156
|
-
|
|
157
|
-
<template>
|
|
158
|
-
<textarea
|
|
159
|
-
ref="ta"
|
|
160
|
-
:data-testid="$attrs['data-testid'] ? $attrs['data-testid'] : 'text-area-auto-grow'"
|
|
161
|
-
:disabled="isDisabled"
|
|
162
|
-
:style="style"
|
|
163
|
-
:placeholder="placeholder"
|
|
164
|
-
class="no-resize no-ease"
|
|
165
|
-
v-bind="$attrs"
|
|
166
|
-
:spellcheck="spellcheck"
|
|
167
|
-
@paste="$emit('paste', $event)"
|
|
168
|
-
@input="onInput($event)"
|
|
169
|
-
@focus="$emit('focus', $event)"
|
|
170
|
-
@blur="$emit('blur', $event)"
|
|
171
|
-
/>
|
|
172
|
-
</template>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default as TextAreaAutoGrow } from './TextAreaAutoGrow.vue';
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import { shallowMount, Wrapper } from '@vue/test-utils';
|
|
2
|
-
import { ToggleSwitch } from './index';
|
|
3
|
-
|
|
4
|
-
describe('toggleSwitch.vue', () => {
|
|
5
|
-
it('renders falsy by default', () => {
|
|
6
|
-
const wrapper = shallowMount(ToggleSwitch);
|
|
7
|
-
|
|
8
|
-
const toggleInput = wrapper.find('input[type="checkbox"]').element as HTMLInputElement;
|
|
9
|
-
|
|
10
|
-
expect(toggleInput.checked).toBeFalsy();
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
it('renders a true value', () => {
|
|
14
|
-
const wrapper = shallowMount(
|
|
15
|
-
ToggleSwitch,
|
|
16
|
-
{ propsData: { value: true } });
|
|
17
|
-
|
|
18
|
-
const toggleInput = wrapper.find('input[type="checkbox"]').element as HTMLInputElement;
|
|
19
|
-
|
|
20
|
-
expect(toggleInput.checked).toBe(true);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it('updates from falsy to truthy when props change', async() => {
|
|
24
|
-
const wrapper = shallowMount(ToggleSwitch);
|
|
25
|
-
|
|
26
|
-
const toggleInput = wrapper.find('input[type="checkbox"]').element as HTMLInputElement;
|
|
27
|
-
|
|
28
|
-
expect(toggleInput.checked).toBe(false);
|
|
29
|
-
|
|
30
|
-
await wrapper.setProps({ value: true });
|
|
31
|
-
|
|
32
|
-
expect(toggleInput.checked).toBe(true);
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it('emits an input event with a true value', async() => {
|
|
36
|
-
const wrapper: Wrapper<InstanceType<typeof ToggleSwitch>> = shallowMount(ToggleSwitch);
|
|
37
|
-
|
|
38
|
-
wrapper.vm.toggle(true);
|
|
39
|
-
|
|
40
|
-
await wrapper.vm.$nextTick();
|
|
41
|
-
|
|
42
|
-
expect(wrapper.emitted().input?.length).toBe(1);
|
|
43
|
-
expect(wrapper.emitted().input?.[0][0]).toBe(true);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it('emits an input event with a false value', async() => {
|
|
47
|
-
const wrapper: Wrapper<InstanceType<typeof ToggleSwitch>> = shallowMount(
|
|
48
|
-
ToggleSwitch,
|
|
49
|
-
{ propsData: { value: true } }
|
|
50
|
-
);
|
|
51
|
-
|
|
52
|
-
wrapper.vm.toggle(false);
|
|
53
|
-
|
|
54
|
-
await wrapper.vm.$nextTick();
|
|
55
|
-
|
|
56
|
-
expect(wrapper.emitted().input?.length).toBe(1);
|
|
57
|
-
expect(wrapper.emitted().input?.[0][0]).toBe(false);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it('emits an input event with a custom onValue', async() => {
|
|
61
|
-
const onValue = 'THE TRUTH';
|
|
62
|
-
|
|
63
|
-
const wrapper: Wrapper<InstanceType<typeof ToggleSwitch>> = shallowMount(
|
|
64
|
-
ToggleSwitch,
|
|
65
|
-
{ propsData: { onValue } });
|
|
66
|
-
|
|
67
|
-
wrapper.vm.toggle(true);
|
|
68
|
-
|
|
69
|
-
await wrapper.vm.$nextTick();
|
|
70
|
-
|
|
71
|
-
expect(wrapper.emitted().input?.length).toBe(1);
|
|
72
|
-
expect(wrapper.emitted().input?.[0][0]).toBe(onValue);
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it('emits an input event with a custom offValue', async() => {
|
|
76
|
-
const offValue = 'NOT THE TRUTH';
|
|
77
|
-
|
|
78
|
-
const wrapper: Wrapper<InstanceType<typeof ToggleSwitch>> = shallowMount(
|
|
79
|
-
ToggleSwitch,
|
|
80
|
-
{
|
|
81
|
-
propsData: {
|
|
82
|
-
value: true,
|
|
83
|
-
offValue,
|
|
84
|
-
}
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
wrapper.vm.toggle(false);
|
|
88
|
-
|
|
89
|
-
await wrapper.vm.$nextTick();
|
|
90
|
-
|
|
91
|
-
expect(wrapper.emitted().input?.length).toBe(1);
|
|
92
|
-
expect(wrapper.emitted().input?.[0][0]).toBe(offValue);
|
|
93
|
-
});
|
|
94
|
-
});
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { defineComponent } from 'vue';
|
|
3
|
-
|
|
4
|
-
type StateType = boolean | 'true' | 'false' | undefined;
|
|
5
|
-
|
|
6
|
-
export default defineComponent({
|
|
7
|
-
props: {
|
|
8
|
-
value: {
|
|
9
|
-
type: [Boolean, String, Number],
|
|
10
|
-
default: false
|
|
11
|
-
},
|
|
12
|
-
|
|
13
|
-
offValue: {
|
|
14
|
-
type: [Boolean, String, Number],
|
|
15
|
-
default: false,
|
|
16
|
-
},
|
|
17
|
-
|
|
18
|
-
onValue: {
|
|
19
|
-
type: [Boolean, String, Number],
|
|
20
|
-
default: true,
|
|
21
|
-
},
|
|
22
|
-
|
|
23
|
-
offLabel: {
|
|
24
|
-
type: String,
|
|
25
|
-
default: '',
|
|
26
|
-
},
|
|
27
|
-
|
|
28
|
-
onLabel: {
|
|
29
|
-
type: String,
|
|
30
|
-
default: '',
|
|
31
|
-
},
|
|
32
|
-
},
|
|
33
|
-
data() {
|
|
34
|
-
return { state: false as StateType };
|
|
35
|
-
},
|
|
36
|
-
|
|
37
|
-
watch: {
|
|
38
|
-
value: {
|
|
39
|
-
handler() {
|
|
40
|
-
this.state = this.value === this.onValue;
|
|
41
|
-
},
|
|
42
|
-
immediate: true
|
|
43
|
-
}
|
|
44
|
-
},
|
|
45
|
-
|
|
46
|
-
methods: {
|
|
47
|
-
toggle(neu: StateType | null) {
|
|
48
|
-
this.state = neu === null ? !this.state : neu;
|
|
49
|
-
this.$emit('input', this.state ? this.onValue : this.offValue);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
</script>
|
|
54
|
-
|
|
55
|
-
<template>
|
|
56
|
-
<span class="toggle-container">
|
|
57
|
-
<span
|
|
58
|
-
class="label no-select hand"
|
|
59
|
-
:class="{ active: !state}"
|
|
60
|
-
@click="toggle(false)"
|
|
61
|
-
>{{ offLabel }}</span>
|
|
62
|
-
<label class="switch hand">
|
|
63
|
-
<input
|
|
64
|
-
type="checkbox"
|
|
65
|
-
:checked="state"
|
|
66
|
-
@input="toggle(null)"
|
|
67
|
-
>
|
|
68
|
-
<span class="slider round" />
|
|
69
|
-
</label>
|
|
70
|
-
<span
|
|
71
|
-
class="label no-select hand"
|
|
72
|
-
:class="{ active: state}"
|
|
73
|
-
@click="toggle(true)"
|
|
74
|
-
>{{ onLabel }}</span>
|
|
75
|
-
</span>
|
|
76
|
-
</template>
|
|
77
|
-
|
|
78
|
-
<style lang="scss" scoped>
|
|
79
|
-
$toggle-height: 16px;
|
|
80
|
-
|
|
81
|
-
.toggle-container {
|
|
82
|
-
align-items: center;
|
|
83
|
-
display: flex;
|
|
84
|
-
|
|
85
|
-
span:first-child {
|
|
86
|
-
padding-right: 6px;
|
|
87
|
-
}
|
|
88
|
-
span:last-child {
|
|
89
|
-
padding-left: 6px;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
/* The switch - the box around the slider */
|
|
93
|
-
.switch {
|
|
94
|
-
position: relative;
|
|
95
|
-
display: inline-block;
|
|
96
|
-
width: 48px;
|
|
97
|
-
height: $toggle-height + 8px;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/* Hide default HTML checkbox */
|
|
101
|
-
.switch input {
|
|
102
|
-
opacity: 0;
|
|
103
|
-
width: 0;
|
|
104
|
-
height: 0;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/* The slider */
|
|
108
|
-
.slider {
|
|
109
|
-
position: absolute;
|
|
110
|
-
cursor: pointer;
|
|
111
|
-
top: 0;
|
|
112
|
-
left: 0;
|
|
113
|
-
right: 0;
|
|
114
|
-
bottom: 0;
|
|
115
|
-
background-color: var(--checkbox-disabled-bg);
|
|
116
|
-
-webkit-transition: .4s;
|
|
117
|
-
transition: .4s;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
.slider:before {
|
|
121
|
-
position: absolute;
|
|
122
|
-
content: "";
|
|
123
|
-
height: $toggle-height;
|
|
124
|
-
width: $toggle-height;
|
|
125
|
-
left: 4px;
|
|
126
|
-
bottom: 4px;
|
|
127
|
-
background-color: var(--checkbox-tick);
|
|
128
|
-
-webkit-transition: .4s;
|
|
129
|
-
transition: .4s;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
input:checked + .slider {
|
|
133
|
-
background-color: var(--checkbox-ticked-bg);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
input:focus + .slider {
|
|
137
|
-
box-shadow: 0 0 1px var(--checkbox-ticked-bg);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
input:checked + .slider:before {
|
|
141
|
-
transform: translateX(24px);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/* Rounded sliders */
|
|
145
|
-
.slider.round {
|
|
146
|
-
border-radius: 34px;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
.slider.round:before {
|
|
150
|
-
border-radius: 50%;
|
|
151
|
-
}
|
|
152
|
-
</style>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default as ToggleSwitch } from './ToggleSwitch.vue';
|