vueless 1.4.7-beta.0 → 1.4.7-beta.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.
- package/icons/storybook/cloud_sync.svg +1 -0
- package/icons/storybook/date_range.svg +1 -0
- package/icons/storybook/event.svg +1 -0
- package/icons/storybook/folder.svg +1 -0
- package/icons/storybook/format_quote.svg +1 -0
- package/icons/storybook/local_shipping.svg +1 -0
- package/icons/storybook/location_city.svg +1 -0
- package/icons/storybook/mark_email_unread.svg +1 -0
- package/icons/storybook/notifications.svg +1 -0
- package/icons/storybook/shield.svg +1 -0
- package/icons/storybook/workspace_premium.svg +1 -0
- package/package.json +1 -1
- package/ui.container-col/config.ts +4 -2
- package/ui.container-col/tests/UCol.test.ts +24 -16
- package/ui.container-row/config.ts +4 -2
- package/ui.container-row/tests/URow.test.ts +24 -16
- package/ui.form-checkbox/UCheckbox.vue +0 -5
- package/ui.form-checkbox/storybook/stories.ts +56 -18
- package/ui.form-checkbox/tests/UCheckbox.test.ts +0 -17
- package/ui.form-checkbox-group/storybook/stories.ts +61 -0
- package/ui.form-date-picker/storybook/stories.ts +85 -37
- package/ui.form-date-picker-range/storybook/stories.ts +97 -38
- package/ui.form-input/storybook/stories.ts +75 -37
- package/ui.form-input-file/storybook/stories.ts +44 -5
- package/ui.form-input-number/storybook/stories.ts +66 -28
- package/ui.form-input-password/storybook/stories.ts +94 -50
- package/ui.form-input-search/storybook/stories.ts +40 -4
- package/ui.form-label/ULabel.vue +0 -6
- package/ui.form-label/storybook/stories.ts +46 -24
- package/ui.form-label/tests/ULabel.test.ts +0 -12
- package/ui.form-radio/URadio.vue +0 -5
- package/ui.form-radio/storybook/stories.ts +65 -25
- package/ui.form-radio/tests/URadio.test.ts +0 -17
- package/ui.form-radio-group/storybook/stories.ts +67 -0
- package/ui.form-select/storybook/stories.ts +99 -44
- package/ui.form-switch/storybook/stories.ts +35 -11
- package/ui.form-textarea/storybook/stories.ts +61 -20
- package/ui.text-files/storybook/stories.ts +30 -13
|
@@ -10,6 +10,9 @@ import {
|
|
|
10
10
|
|
|
11
11
|
import UInputPassword from "../UInputPassword.vue";
|
|
12
12
|
import UCol from "../../ui.container-col/UCol.vue";
|
|
13
|
+
import UText from "../../ui.text-block/UText.vue";
|
|
14
|
+
import ULink from "../../ui.button-link/ULink.vue";
|
|
15
|
+
import UIcon from "../../ui.image-icon/UIcon.vue";
|
|
13
16
|
import URow from "../../ui.container-row/URow.vue";
|
|
14
17
|
import UButton from "../../ui.button/UButton.vue";
|
|
15
18
|
import UDropdownButton from "../../ui.dropdown-button/UDropdownButton.vue";
|
|
@@ -139,69 +142,110 @@ export const IconProps: StoryFn<UInputPasswordArgs> = (args) => ({
|
|
|
139
142
|
});
|
|
140
143
|
|
|
141
144
|
export const Slots: StoryFn<UInputPasswordArgs> = (args) => ({
|
|
142
|
-
components: { UInputPassword, URow, UButton, UDropdownButton },
|
|
145
|
+
components: { UInputPassword, URow, UCol, UButton, UDropdownButton, UText, ULink, UIcon },
|
|
143
146
|
setup() {
|
|
144
147
|
const wifiTypes = [
|
|
145
148
|
{ label: "WPA2", value: "wpa2" },
|
|
146
149
|
{ label: "WPA3", value: "wpa3" },
|
|
147
150
|
];
|
|
148
151
|
|
|
149
|
-
|
|
152
|
+
const descriptionSlotValue = ref("");
|
|
153
|
+
const errorSlotValue = ref("");
|
|
154
|
+
|
|
155
|
+
return { args, wifiTypes, descriptionSlotValue, errorSlotValue };
|
|
150
156
|
},
|
|
151
157
|
template: `
|
|
152
|
-
<
|
|
153
|
-
<
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
{
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
<
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
{
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
<
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
158
|
+
<UCol gap="3xl">
|
|
159
|
+
<URow block>
|
|
160
|
+
<UInputPassword
|
|
161
|
+
v-bind="args"
|
|
162
|
+
v-model="args.modelValue"
|
|
163
|
+
label="Enter your password"
|
|
164
|
+
:config="{ passwordInput: { wrapper: 'pl-0' } }"
|
|
165
|
+
>
|
|
166
|
+
<template #label="{ label }">
|
|
167
|
+
{{ label }}
|
|
168
|
+
<span class="text-red-500">*</span>
|
|
169
|
+
</template>
|
|
170
|
+
|
|
171
|
+
<template #left>
|
|
172
|
+
<UDropdownButton
|
|
173
|
+
v-model="args.wifiType"
|
|
174
|
+
:options="wifiTypes"
|
|
175
|
+
label="Wifi type"
|
|
176
|
+
size="sm"
|
|
177
|
+
variant="soft"
|
|
178
|
+
class="rounded-r-none h-[49px]"
|
|
179
|
+
/>
|
|
180
|
+
</template>
|
|
181
|
+
</UInputPassword>
|
|
182
|
+
|
|
183
|
+
<UInputPassword
|
|
184
|
+
v-bind="args"
|
|
185
|
+
v-model="args.modelValue"
|
|
186
|
+
label="Enter your password"
|
|
187
|
+
:config="{ passwordInput: { wrapper: 'pr-0' } }"
|
|
188
|
+
>
|
|
189
|
+
<template #label="{ label }">
|
|
190
|
+
{{ label }}
|
|
191
|
+
<span class="text-red-500">*</span>
|
|
192
|
+
</template>
|
|
193
|
+
|
|
194
|
+
<template #right="{ visible, toggle }">
|
|
195
|
+
<UButton
|
|
196
|
+
:label="visible ? 'Hide' : 'Show'"
|
|
197
|
+
color="neutral"
|
|
198
|
+
variant="ghost"
|
|
199
|
+
size="sm"
|
|
200
|
+
class="rounded-l-none h-[49px] min-w-[69px]"
|
|
201
|
+
@click="toggle"
|
|
202
|
+
/>
|
|
203
|
+
</template>
|
|
204
|
+
</UInputPassword>
|
|
205
|
+
</URow>
|
|
206
|
+
|
|
207
|
+
<URow block>
|
|
208
|
+
<UInputPassword
|
|
209
|
+
v-model="descriptionSlotValue"
|
|
210
|
+
label="Password"
|
|
211
|
+
>
|
|
212
|
+
<template #description>
|
|
213
|
+
<URow align="center" gap="2xs" class="text-neutral">
|
|
214
|
+
<UIcon name="shield" size="xs" color="primary" />
|
|
215
|
+
<UText size="sm">
|
|
216
|
+
Minimum 8 characters.
|
|
217
|
+
<ULink label="Password rules" underlined size="sm" />.
|
|
218
|
+
</UText>
|
|
219
|
+
</URow>
|
|
220
|
+
</template>
|
|
221
|
+
</UInputPassword>
|
|
222
|
+
|
|
223
|
+
<UInputPassword
|
|
224
|
+
v-model="errorSlotValue"
|
|
225
|
+
label="Password"
|
|
226
|
+
:error="true"
|
|
227
|
+
>
|
|
228
|
+
<template #error>
|
|
229
|
+
<URow align="center" gap="2xs">
|
|
230
|
+
<UIcon name="error" size="xs" color="error" />
|
|
231
|
+
<UText size="sm" color="error">
|
|
232
|
+
<ul>
|
|
233
|
+
<li>Password does not meet strength requirements</li>
|
|
234
|
+
<li>Use at least 8 characters with mixed case and numbers</li>
|
|
235
|
+
<li>Avoid common words and repeated characters</li>
|
|
236
|
+
</ul>
|
|
237
|
+
</UText>
|
|
238
|
+
</URow>
|
|
239
|
+
</template>
|
|
240
|
+
</UInputPassword>
|
|
241
|
+
</URow>
|
|
242
|
+
</UCol>
|
|
199
243
|
`,
|
|
200
244
|
});
|
|
201
245
|
Slots.parameters = {
|
|
202
246
|
docs: {
|
|
203
247
|
story: {
|
|
204
|
-
height: "
|
|
248
|
+
height: "300px",
|
|
205
249
|
},
|
|
206
250
|
},
|
|
207
251
|
};
|
|
@@ -14,6 +14,7 @@ import UCol from "../../ui.container-col/UCol.vue";
|
|
|
14
14
|
import URow from "../../ui.container-row/URow.vue";
|
|
15
15
|
import UDropdownButton from "../../ui.dropdown-button/UDropdownButton.vue";
|
|
16
16
|
import UText from "../../ui.text-block/UText.vue";
|
|
17
|
+
import ULink from "../../ui.button-link/ULink.vue";
|
|
17
18
|
|
|
18
19
|
import type { Meta, StoryFn } from "@storybook/vue3-vite";
|
|
19
20
|
import type { Props } from "../types";
|
|
@@ -152,7 +153,7 @@ export const IconProps: StoryFn<UInputSearchArgs> = (args) => ({
|
|
|
152
153
|
});
|
|
153
154
|
|
|
154
155
|
export const Slots: StoryFn<UInputSearchArgs> = (args) => ({
|
|
155
|
-
components: { UInputSearch, UCol, URow, UIcon, UDropdownButton, UText },
|
|
156
|
+
components: { UInputSearch, UCol, URow, UIcon, UDropdownButton, UText, ULink },
|
|
156
157
|
setup() {
|
|
157
158
|
const aiVersions = [
|
|
158
159
|
{ label: "GPT-4o", value: "gpt-4o" },
|
|
@@ -160,10 +161,13 @@ export const Slots: StoryFn<UInputSearchArgs> = (args) => ({
|
|
|
160
161
|
{ label: "GPT-4", value: "gpt-4" },
|
|
161
162
|
];
|
|
162
163
|
|
|
163
|
-
|
|
164
|
+
const descriptionSlotValue = ref("");
|
|
165
|
+
const errorSlotValue = ref("");
|
|
166
|
+
|
|
167
|
+
return { args, aiVersions, descriptionSlotValue, errorSlotValue };
|
|
164
168
|
},
|
|
165
169
|
template: `
|
|
166
|
-
<UCol>
|
|
170
|
+
<UCol gap="3xl">
|
|
167
171
|
<UInputSearch placeholder="Search by rental district...">
|
|
168
172
|
<template #right>
|
|
169
173
|
<URow align="center" gap="xs">
|
|
@@ -188,13 +192,45 @@ export const Slots: StoryFn<UInputSearchArgs> = (args) => ({
|
|
|
188
192
|
/>
|
|
189
193
|
</template>
|
|
190
194
|
</UInputSearch>
|
|
195
|
+
|
|
196
|
+
<UInputSearch v-model="descriptionSlotValue" label="Search products">
|
|
197
|
+
<template #description>
|
|
198
|
+
<URow align="center" gap="2xs" class="text-neutral">
|
|
199
|
+
<UIcon name="travel_explore" size="xs" color="primary" />
|
|
200
|
+
<UText size="sm">
|
|
201
|
+
Tip: use
|
|
202
|
+
<ULink label="filters" underlined size="sm" />
|
|
203
|
+
for exact matches.
|
|
204
|
+
</UText>
|
|
205
|
+
</URow>
|
|
206
|
+
</template>
|
|
207
|
+
</UInputSearch>
|
|
208
|
+
|
|
209
|
+
<UInputSearch
|
|
210
|
+
v-model="errorSlotValue"
|
|
211
|
+
label="Search"
|
|
212
|
+
:error="true"
|
|
213
|
+
>
|
|
214
|
+
<template #error>
|
|
215
|
+
<URow align="center" gap="2xs">
|
|
216
|
+
<UIcon name="error" size="xs" color="error" />
|
|
217
|
+
<UText size="sm" color="error">
|
|
218
|
+
<ul>
|
|
219
|
+
<li>Search query is too short</li>
|
|
220
|
+
<li>Remove unsupported symbols from your search</li>
|
|
221
|
+
<li>Try different keywords and search again</li>
|
|
222
|
+
</ul>
|
|
223
|
+
</UText>
|
|
224
|
+
</URow>
|
|
225
|
+
</template>
|
|
226
|
+
</UInputSearch>
|
|
191
227
|
</UCol>
|
|
192
228
|
`,
|
|
193
229
|
});
|
|
194
230
|
Slots.parameters = {
|
|
195
231
|
docs: {
|
|
196
232
|
story: {
|
|
197
|
-
height: "
|
|
233
|
+
height: "500px",
|
|
198
234
|
},
|
|
199
235
|
},
|
|
200
236
|
};
|
package/ui.form-label/ULabel.vue
CHANGED
|
@@ -170,9 +170,6 @@ const { getDataTest, wrapperAttrs, contentAttrs, labelAttrs, descriptionAttrs, e
|
|
|
170
170
|
{{ description }}
|
|
171
171
|
</slot>
|
|
172
172
|
</div>
|
|
173
|
-
|
|
174
|
-
<!-- @slot Use it to add something below the label content. -->
|
|
175
|
-
<slot name="bottom" />
|
|
176
173
|
</div>
|
|
177
174
|
</div>
|
|
178
175
|
|
|
@@ -226,8 +223,5 @@ const { getDataTest, wrapperAttrs, contentAttrs, labelAttrs, descriptionAttrs, e
|
|
|
226
223
|
{{ description }}
|
|
227
224
|
</slot>
|
|
228
225
|
</div>
|
|
229
|
-
|
|
230
|
-
<!-- @slot Use it to add something below the label content. -->
|
|
231
|
-
<slot name="bottom" />
|
|
232
226
|
</div>
|
|
233
227
|
</template>
|
|
@@ -114,29 +114,51 @@ Sizes.args = { enum: "size" };
|
|
|
114
114
|
export const LabelAlign = EnumTemplate.bind({});
|
|
115
115
|
LabelAlign.args = { enum: "align" };
|
|
116
116
|
|
|
117
|
-
export const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
<
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
117
|
+
export const Slots: StoryFn<ULabelArgs> = () => ({
|
|
118
|
+
components: { ULabel, UText, URow, ULink, UIcon, UCol, UChip },
|
|
119
|
+
template: `
|
|
120
|
+
<UCol gap="3xl">
|
|
121
|
+
<ULabel label="Work email">
|
|
122
|
+
<UText label="johndoe@example.com" />
|
|
123
|
+
<template #label="{ label }">
|
|
124
|
+
<URow align="center" gap="xs">
|
|
125
|
+
<UIcon name="mail" size="sm" class="text-primary" />
|
|
126
|
+
<UChip icon="asterisk" color="error" size="xs">
|
|
127
|
+
<UText :label="label" class="mr-2" />
|
|
128
|
+
</UChip>
|
|
129
|
+
</URow>
|
|
130
|
+
</template>
|
|
131
|
+
</ULabel>
|
|
131
132
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
133
|
+
<ULabel label="Work email">
|
|
134
|
+
<UText label="johndoe@example.com" />
|
|
135
|
+
<template #description>
|
|
136
|
+
<URow align="center" gap="2xs" class="text-neutral">
|
|
137
|
+
<UIcon name="mark_email_unread" size="xs" color="primary" />
|
|
138
|
+
<UText size="sm">
|
|
139
|
+
We will send a
|
|
140
|
+
<ULink label="confirmation link" underlined size="sm" />
|
|
141
|
+
to this address.
|
|
142
|
+
</UText>
|
|
143
|
+
</URow>
|
|
144
|
+
</template>
|
|
145
|
+
</ULabel>
|
|
146
|
+
|
|
147
|
+
<ULabel label="Email" :error="true">
|
|
148
|
+
<UText label="not-an-email" />
|
|
149
|
+
<template #error>
|
|
150
|
+
<URow align="center" gap="2xs">
|
|
151
|
+
<UIcon name="error" size="xs" color="error" />
|
|
152
|
+
<UText size="sm" color="error">
|
|
153
|
+
<ul>
|
|
154
|
+
<li>Email address format is invalid</li>
|
|
155
|
+
<li>Use a name@domain.com style address</li>
|
|
156
|
+
<li>Remove spaces and special characters from the local part</li>
|
|
157
|
+
</ul>
|
|
158
|
+
</UText>
|
|
159
|
+
</URow>
|
|
160
|
+
</template>
|
|
161
|
+
</ULabel>
|
|
162
|
+
</UCol>
|
|
141
163
|
`,
|
|
142
|
-
};
|
|
164
|
+
});
|
|
@@ -369,18 +369,6 @@ describe("ULabel.vue", () => {
|
|
|
369
369
|
|
|
370
370
|
expect(component.find("[vl-key='label']").text()).toBe(slotContent);
|
|
371
371
|
});
|
|
372
|
-
|
|
373
|
-
it("Bottom – renders content from bottom slot", () => {
|
|
374
|
-
const testClass = "custom-bottom";
|
|
375
|
-
|
|
376
|
-
const component = mount(ULabel, {
|
|
377
|
-
slots: {
|
|
378
|
-
bottom: `<div class="${testClass}">Bottom Slot Content</div>`,
|
|
379
|
-
},
|
|
380
|
-
});
|
|
381
|
-
|
|
382
|
-
expect(component.find(`.${testClass}`).exists()).toBe(true);
|
|
383
|
-
});
|
|
384
372
|
});
|
|
385
373
|
|
|
386
374
|
describe("Events", () => {
|
package/ui.form-radio/URadio.vue
CHANGED
|
@@ -151,10 +151,5 @@ const { getDataTest, radioLabelAttrs, radioAttrs } = useUI<Config>(defaultConfig
|
|
|
151
151
|
:data-test="getDataTest()"
|
|
152
152
|
@change="onChange"
|
|
153
153
|
/>
|
|
154
|
-
|
|
155
|
-
<template #bottom>
|
|
156
|
-
<!-- @slot Use it to add something below the radio. -->
|
|
157
|
-
<slot name="bottom" />
|
|
158
|
-
</template>
|
|
159
154
|
</ULabel>
|
|
160
155
|
</template>
|
|
@@ -15,6 +15,8 @@ import UIcon from "../../ui.image-icon/UIcon.vue";
|
|
|
15
15
|
|
|
16
16
|
import type { Meta, StoryFn } from "@storybook/vue3-vite";
|
|
17
17
|
import type { Props } from "../types";
|
|
18
|
+
import { ref } from "vue";
|
|
19
|
+
import UCol from "../../ui.container-col/UCol.vue";
|
|
18
20
|
|
|
19
21
|
interface URadioArgs extends Props {
|
|
20
22
|
slotTemplate?: string;
|
|
@@ -107,30 +109,68 @@ Sizes.args = { name: "Sizes", enum: "size", label: "{enumValue}", modelValue: 1
|
|
|
107
109
|
export const Colors = EnumTemplate.bind({});
|
|
108
110
|
Colors.args = { name: "Colors", enum: "color", label: "{enumValue}", modelValue: 1 };
|
|
109
111
|
|
|
110
|
-
export const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
112
|
+
export const Slots: StoryFn<URadioArgs> = (args) => ({
|
|
113
|
+
components: { URadio, UCol, UText, URow, ULink, UIcon },
|
|
114
|
+
setup: () => ({
|
|
115
|
+
args,
|
|
116
|
+
labelModel: ref(""),
|
|
117
|
+
descriptionModel: ref(""),
|
|
118
|
+
errorModel: ref(""),
|
|
119
|
+
}),
|
|
120
|
+
template: `
|
|
121
|
+
<UCol gap="3xl">
|
|
122
|
+
<URadio
|
|
123
|
+
v-bind="args"
|
|
124
|
+
v-model="labelModel"
|
|
125
|
+
name="LabelSlot"
|
|
126
|
+
value="courier"
|
|
127
|
+
>
|
|
128
|
+
<template #label>
|
|
129
|
+
<URow align="center" gap="2xs">
|
|
130
|
+
<UText>Courier delivery</UText>
|
|
131
|
+
<UIcon name="local_shipping" size="xs" color="neutral" />
|
|
132
|
+
</URow>
|
|
133
|
+
</template>
|
|
134
|
+
</URadio>
|
|
124
135
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
136
|
+
<URadio
|
|
137
|
+
v-bind="args"
|
|
138
|
+
v-model="descriptionModel"
|
|
139
|
+
name="DescriptionSlot"
|
|
140
|
+
value="pro"
|
|
141
|
+
>
|
|
142
|
+
<template #description>
|
|
143
|
+
<URow align="center" gap="2xs" class="text-neutral">
|
|
144
|
+
<UIcon name="workspace_premium" size="xs" class="mt-0.5" color="primary" />
|
|
145
|
+
<UText size="sm">
|
|
146
|
+
Includes all core features.
|
|
147
|
+
<ULink label="Compare plans" underlined size="sm" />.
|
|
148
|
+
</UText>
|
|
149
|
+
</URow>
|
|
150
|
+
</template>
|
|
151
|
+
</URadio>
|
|
152
|
+
|
|
153
|
+
<URadio
|
|
154
|
+
v-bind="args"
|
|
155
|
+
v-model="errorModel"
|
|
156
|
+
name="ErrorSlot"
|
|
157
|
+
label="Select"
|
|
158
|
+
value="1"
|
|
159
|
+
:error="true"
|
|
160
|
+
>
|
|
161
|
+
<template #error>
|
|
162
|
+
<URow align="center" gap="2xs">
|
|
163
|
+
<UIcon name="error" size="xs" color="error" />
|
|
164
|
+
<UText size="sm" color="error">
|
|
165
|
+
<ul>
|
|
166
|
+
<li>You must select one of the available options</li>
|
|
167
|
+
<li>This field is required to proceed</li>
|
|
168
|
+
<li>Choose an option above to clear this error</li>
|
|
169
|
+
</ul>
|
|
170
|
+
</UText>
|
|
171
|
+
</URow>
|
|
172
|
+
</template>
|
|
173
|
+
</URadio>
|
|
174
|
+
</UCol>
|
|
135
175
|
`,
|
|
136
|
-
};
|
|
176
|
+
});
|
|
@@ -241,22 +241,5 @@ describe("URadio.vue", () => {
|
|
|
241
241
|
|
|
242
242
|
expect(errorElement.text()).toBe(customError);
|
|
243
243
|
});
|
|
244
|
-
|
|
245
|
-
it("Bottom – renders custom content from bottom slot", () => {
|
|
246
|
-
const customBottomContent = "Custom Bottom Content";
|
|
247
|
-
|
|
248
|
-
const component = mount(URadio, {
|
|
249
|
-
props: {
|
|
250
|
-
label: "Test Label",
|
|
251
|
-
},
|
|
252
|
-
slots: {
|
|
253
|
-
bottom: customBottomContent,
|
|
254
|
-
},
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
const labelComponent = component.getComponent(ULabel);
|
|
258
|
-
|
|
259
|
-
expect(labelComponent.text()).toContain(customBottomContent);
|
|
260
|
-
});
|
|
261
244
|
});
|
|
262
245
|
});
|
|
@@ -13,9 +13,12 @@ import UCol from "../../ui.container-col/UCol.vue";
|
|
|
13
13
|
import URow from "../../ui.container-row/URow.vue";
|
|
14
14
|
import UBadge from "../../ui.text-badge/UBadge.vue";
|
|
15
15
|
import UText from "../../ui.text-block/UText.vue";
|
|
16
|
+
import ULink from "../../ui.button-link/ULink.vue";
|
|
17
|
+
import UIcon from "../../ui.image-icon/UIcon.vue";
|
|
16
18
|
|
|
17
19
|
import type { Meta, StoryFn } from "@storybook/vue3-vite";
|
|
18
20
|
import type { Props } from "../types";
|
|
21
|
+
import { ref } from "vue";
|
|
19
22
|
|
|
20
23
|
interface URadioGroupArgs extends Props {
|
|
21
24
|
slotTemplate?: string;
|
|
@@ -170,3 +173,67 @@ CustomKeys.parameters = {
|
|
|
170
173
|
},
|
|
171
174
|
},
|
|
172
175
|
};
|
|
176
|
+
|
|
177
|
+
export const Slots: StoryFn<URadioGroupArgs> = (args) => ({
|
|
178
|
+
components: { URadioGroup, UCol, UText, URow, ULink, UIcon },
|
|
179
|
+
setup: () => ({
|
|
180
|
+
args,
|
|
181
|
+
modelValueLabel: ref(null),
|
|
182
|
+
modelValueDescription: ref(null),
|
|
183
|
+
modelValueError: ref(null),
|
|
184
|
+
}),
|
|
185
|
+
template: `
|
|
186
|
+
<UCol gap="3xl">
|
|
187
|
+
<URadioGroup
|
|
188
|
+
v-bind="args"
|
|
189
|
+
v-model="modelValueLabel"
|
|
190
|
+
name="LabelSlot"
|
|
191
|
+
>
|
|
192
|
+
<template #label>
|
|
193
|
+
<URow align="center" gap="2xs">
|
|
194
|
+
<UText>Choose a delivery option</UText>
|
|
195
|
+
<UIcon name="local_shipping" size="xs" color="neutral" />
|
|
196
|
+
</URow>
|
|
197
|
+
</template>
|
|
198
|
+
</URadioGroup>
|
|
199
|
+
|
|
200
|
+
<URadioGroup
|
|
201
|
+
v-bind="args"
|
|
202
|
+
v-model="modelValueDescription"
|
|
203
|
+
name="SlotsDescription"
|
|
204
|
+
label="Delivery"
|
|
205
|
+
>
|
|
206
|
+
<template #description>
|
|
207
|
+
<URow align="center" gap="2xs" class="text-neutral">
|
|
208
|
+
<UIcon name="local_shipping" size="xs" color="primary" />
|
|
209
|
+
<UText size="sm">
|
|
210
|
+
Shipping times are estimates.
|
|
211
|
+
<ULink label="Full policy" underlined size="sm" />.
|
|
212
|
+
</UText>
|
|
213
|
+
</URow>
|
|
214
|
+
</template>
|
|
215
|
+
</URadioGroup>
|
|
216
|
+
|
|
217
|
+
<URadioGroup
|
|
218
|
+
v-bind="args"
|
|
219
|
+
v-model="modelValueError"
|
|
220
|
+
name="SlotsError"
|
|
221
|
+
label="Delivery"
|
|
222
|
+
:error="true"
|
|
223
|
+
>
|
|
224
|
+
<template #error>
|
|
225
|
+
<URow align="center" gap="2xs">
|
|
226
|
+
<UIcon name="error" size="xs" color="error" />
|
|
227
|
+
<UText size="sm" color="error">
|
|
228
|
+
<ul>
|
|
229
|
+
<li>Please choose one option from the group</li>
|
|
230
|
+
<li>At least one selection is required</li>
|
|
231
|
+
<li>Review the labels and pick a valid answer</li>
|
|
232
|
+
</ul>
|
|
233
|
+
</UText>
|
|
234
|
+
</URow>
|
|
235
|
+
</template>
|
|
236
|
+
</URadioGroup>
|
|
237
|
+
</UCol>
|
|
238
|
+
`,
|
|
239
|
+
});
|