vueless 1.2.8 → 1.2.10-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/constants.d.ts +4 -0
- package/constants.js +4 -0
- package/icons/storybook/rocket_launch.svg +1 -0
- package/index.d.ts +3 -1
- package/index.ts +3 -1
- package/package.json +9 -5
- package/plugin-vite.js +6 -1
- package/types.ts +14 -2
- package/ui.button/config.ts +4 -4
- package/ui.button/tests/UButton.test.ts +3 -3
- package/ui.button-toggle/config.ts +2 -2
- package/ui.container-accordion/UAccordion.vue +0 -1
- package/ui.container-accordion/config.ts +1 -1
- package/ui.container-accordion/storybook/stories.ts +13 -1
- package/ui.container-accordion-item/UAccordionItem.vue +17 -4
- package/ui.container-accordion-item/config.ts +1 -1
- package/ui.container-accordion-item/storybook/stories.ts +26 -1
- package/ui.container-accordion-item/tests/UAccordionItem.test.ts +186 -0
- package/ui.container-card/config.ts +1 -1
- package/ui.data-table/config.ts +4 -4
- package/ui.dropdown-badge/UDropdownBadge.vue +68 -3
- package/ui.dropdown-badge/config.ts +5 -1
- package/ui.dropdown-badge/storybook/stories.ts +280 -4
- package/ui.dropdown-badge/tests/UDropdownBadge.test.ts +194 -0
- package/ui.dropdown-badge/types.ts +30 -0
- package/ui.dropdown-button/UDropdownButton.vue +69 -6
- package/ui.dropdown-button/config.ts +5 -1
- package/ui.dropdown-button/storybook/stories.ts +288 -3
- package/ui.dropdown-button/tests/UDropdownButton.test.ts +190 -0
- package/ui.dropdown-button/types.ts +30 -0
- package/ui.dropdown-link/UDropdownLink.vue +69 -6
- package/ui.dropdown-link/config.ts +5 -1
- package/ui.dropdown-link/storybook/stories.ts +281 -4
- package/ui.dropdown-link/tests/UDropdownLink.test.ts +194 -0
- package/ui.dropdown-link/types.ts +30 -0
- package/ui.form-calendar/config.ts +4 -2
- package/ui.form-checkbox/config.ts +1 -1
- package/ui.form-checkbox/tests/UCheckbox.test.ts +2 -2
- package/ui.form-checkbox-group/tests/UCheckboxGroup.test.ts +2 -2
- package/ui.form-date-picker-range/config.ts +1 -1
- package/ui.form-input/UInput.vue +4 -2
- package/ui.form-input/config.ts +1 -1
- package/ui.form-input/tests/UInput.test.ts +2 -2
- package/ui.form-input-counter/UInputCounter.vue +25 -1
- package/ui.form-input-counter/config.ts +7 -2
- package/ui.form-input-counter/tests/UInputCounter.test.ts +85 -1
- package/ui.form-input-counter/types.ts +25 -0
- package/ui.form-input-file/tests/UInputFile.test.ts +2 -2
- package/ui.form-input-number/UInputNumber.vue +15 -3
- package/ui.form-input-number/utilFormat.ts +17 -7
- package/ui.form-input-password/UInputPassword.vue +23 -1
- package/ui.form-label/ULabel.vue +10 -4
- package/ui.form-label/tests/ULabel.test.ts +29 -12
- package/ui.form-listbox/UListbox.vue +21 -9
- package/ui.form-listbox/config.ts +1 -1
- package/ui.form-listbox/storybook/stories.ts +188 -1
- package/ui.form-listbox/tests/UListbox.test.ts +36 -0
- package/ui.form-listbox/types.ts +5 -0
- package/ui.form-radio/config.ts +1 -1
- package/ui.form-radio/tests/URadio.test.ts +2 -2
- package/ui.form-radio-group/tests/URadioGroup.test.ts +2 -2
- package/ui.form-select/USelect.vue +20 -2
- package/ui.form-select/config.ts +2 -1
- package/ui.form-select/storybook/stories.ts +31 -4
- package/ui.form-select/tests/USelect.test.ts +143 -0
- package/ui.form-select/types.ts +10 -0
- package/ui.form-textarea/config.ts +1 -1
- package/ui.form-textarea/tests/UTextarea.test.ts +2 -2
- package/ui.text-alert/config.ts +1 -1
- package/ui.text-badge/config.ts +1 -1
- package/utils/helper.ts +4 -0
- package/utils/node/dynamicProps.d.ts +5 -2
- package/utils/node/dynamicProps.js +126 -53
- package/utils/node/helper.d.ts +10 -7
- package/utils/node/helper.js +59 -2
- package/utils/node/tailwindSafelist.js +9 -2
- package/utils/theme.ts +75 -31
- package/utils/ui.ts +32 -3
|
@@ -36,6 +36,26 @@ export interface Props {
|
|
|
36
36
|
*/
|
|
37
37
|
valueKey?: string;
|
|
38
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Set a name of the property containing the group label.
|
|
41
|
+
*/
|
|
42
|
+
groupLabelKey?: string;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Set a name of the property containing the group values.
|
|
46
|
+
*/
|
|
47
|
+
groupValueKey?: string;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Number of options displayed in the dropdown.
|
|
51
|
+
*/
|
|
52
|
+
optionsLimit?: number;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Number of options you can see without a scroll.
|
|
56
|
+
*/
|
|
57
|
+
visibleOptions?: number;
|
|
58
|
+
|
|
39
59
|
/**
|
|
40
60
|
* Badge variant.
|
|
41
61
|
*/
|
|
@@ -70,6 +90,16 @@ export interface Props {
|
|
|
70
90
|
*/
|
|
71
91
|
searchable?: boolean;
|
|
72
92
|
|
|
93
|
+
/**
|
|
94
|
+
* Search input model value for the dropdown list.
|
|
95
|
+
*/
|
|
96
|
+
search?: string;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Close dropdown on option select.
|
|
100
|
+
*/
|
|
101
|
+
closeOnSelect?: boolean;
|
|
102
|
+
|
|
73
103
|
/**
|
|
74
104
|
* Allows multiple selection.
|
|
75
105
|
*/
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { nextTick, computed,
|
|
2
|
+
import { nextTick, computed, ref, useId, useTemplateRef } from "vue";
|
|
3
3
|
import { isEqual } from "lodash-es";
|
|
4
4
|
|
|
5
5
|
import useUI from "../composables/useUI";
|
|
@@ -55,13 +55,18 @@ const emit = defineEmits([
|
|
|
55
55
|
* @property {string} query
|
|
56
56
|
*/
|
|
57
57
|
"searchChange",
|
|
58
|
-
]);
|
|
59
58
|
|
|
60
|
-
|
|
59
|
+
/**
|
|
60
|
+
* Triggers when the search v-model updates.
|
|
61
|
+
* @property {string} query
|
|
62
|
+
*/
|
|
63
|
+
"update:search",
|
|
64
|
+
]);
|
|
61
65
|
|
|
62
66
|
type UListboxRef = InstanceType<typeof UListbox>;
|
|
63
67
|
|
|
64
68
|
const isShownOptions = ref(false);
|
|
69
|
+
const isClickingOption = ref(false);
|
|
65
70
|
const listboxRef = useTemplateRef<UListboxRef>("dropdown-list");
|
|
66
71
|
const wrapperRef = useTemplateRef<HTMLDivElement>("wrapper");
|
|
67
72
|
|
|
@@ -78,6 +83,11 @@ const dropdownValue = computed({
|
|
|
78
83
|
set: (value) => emit("update:modelValue", value),
|
|
79
84
|
});
|
|
80
85
|
|
|
86
|
+
const dropdownSearch = computed({
|
|
87
|
+
get: () => props.search ?? "",
|
|
88
|
+
set: (value: string) => emit("update:search", value),
|
|
89
|
+
});
|
|
90
|
+
|
|
81
91
|
const selectedOptions = computed(() => {
|
|
82
92
|
if (props.multiple) {
|
|
83
93
|
return props.options.filter((option) => {
|
|
@@ -137,9 +147,23 @@ function getFullOptionLabels(value: Option | Option[]) {
|
|
|
137
147
|
}
|
|
138
148
|
|
|
139
149
|
function onClickOption(option: Option) {
|
|
150
|
+
isClickingOption.value = true;
|
|
151
|
+
|
|
140
152
|
emit("clickOption", option);
|
|
141
153
|
|
|
142
|
-
if (!props.multiple) hideOptions();
|
|
154
|
+
if (!props.multiple && props.closeOnSelect) hideOptions();
|
|
155
|
+
|
|
156
|
+
nextTick(() => {
|
|
157
|
+
setTimeout(() => {
|
|
158
|
+
isClickingOption.value = false;
|
|
159
|
+
}, 10);
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function handleClickOutside() {
|
|
164
|
+
if (isClickingOption.value) return;
|
|
165
|
+
|
|
166
|
+
hideOptions();
|
|
143
167
|
}
|
|
144
168
|
|
|
145
169
|
function onClickButton() {
|
|
@@ -154,6 +178,7 @@ function onClickButton() {
|
|
|
154
178
|
|
|
155
179
|
function hideOptions() {
|
|
156
180
|
isShownOptions.value = false;
|
|
181
|
+
dropdownSearch.value = "";
|
|
157
182
|
|
|
158
183
|
emit("close");
|
|
159
184
|
}
|
|
@@ -188,7 +213,7 @@ const { getDataTest, config, dropdownButtonAttrs, listboxAttrs, toggleIconAttrs,
|
|
|
188
213
|
<template>
|
|
189
214
|
<div
|
|
190
215
|
ref="wrapper"
|
|
191
|
-
v-click-outside="
|
|
216
|
+
v-click-outside="handleClickOutside"
|
|
192
217
|
v-bind="wrapperAttrs"
|
|
193
218
|
:data-test="getDataTest('wrapper')"
|
|
194
219
|
>
|
|
@@ -245,16 +270,54 @@ const { getDataTest, config, dropdownButtonAttrs, listboxAttrs, toggleIconAttrs,
|
|
|
245
270
|
v-if="isShownOptions"
|
|
246
271
|
ref="dropdown-list"
|
|
247
272
|
v-model="dropdownValue"
|
|
273
|
+
v-model:search="dropdownSearch"
|
|
248
274
|
:searchable="searchable"
|
|
249
275
|
:multiple="multiple"
|
|
250
276
|
:color="color"
|
|
251
277
|
:options="options"
|
|
278
|
+
:options-limit="optionsLimit"
|
|
279
|
+
:visible-options="visibleOptions"
|
|
252
280
|
:label-key="labelKey"
|
|
253
281
|
:value-key="valueKey"
|
|
282
|
+
:group-label-key="groupLabelKey"
|
|
283
|
+
:group-value-key="groupValueKey"
|
|
254
284
|
v-bind="listboxAttrs"
|
|
255
285
|
:data-test="getDataTest('list')"
|
|
256
286
|
@click-option="onClickOption"
|
|
257
287
|
@search-change="onSearchChange"
|
|
258
|
-
|
|
288
|
+
@update:search="(value) => emit('update:search', value)"
|
|
289
|
+
>
|
|
290
|
+
<template #before-option="{ option, index }">
|
|
291
|
+
<!--
|
|
292
|
+
@slot Use it to add something before option.
|
|
293
|
+
@binding {object} option
|
|
294
|
+
@binding {number} index
|
|
295
|
+
-->
|
|
296
|
+
<slot name="before-option" :option="option" :index="index" />
|
|
297
|
+
</template>
|
|
298
|
+
|
|
299
|
+
<template #option="{ option, index }">
|
|
300
|
+
<!--
|
|
301
|
+
@slot Use it to customize the option.
|
|
302
|
+
@binding {object} option
|
|
303
|
+
@binding {number} index
|
|
304
|
+
-->
|
|
305
|
+
<slot name="option" :option="option" :index="index" />
|
|
306
|
+
</template>
|
|
307
|
+
|
|
308
|
+
<template #after-option="{ option, index }">
|
|
309
|
+
<!--
|
|
310
|
+
@slot Use it to add something after option.
|
|
311
|
+
@binding {object} option
|
|
312
|
+
@binding {number} index
|
|
313
|
+
-->
|
|
314
|
+
<slot name="after-option" :option="option" :index="index" />
|
|
315
|
+
</template>
|
|
316
|
+
|
|
317
|
+
<template #empty>
|
|
318
|
+
<!-- @slot Use it to add something instead of empty state. -->
|
|
319
|
+
<slot name="empty" />
|
|
320
|
+
</template>
|
|
321
|
+
</UListbox>
|
|
259
322
|
</div>
|
|
260
323
|
</template>
|
|
@@ -51,15 +51,19 @@ export default /*tw*/ {
|
|
|
51
51
|
variant: "solid",
|
|
52
52
|
labelKey: "label",
|
|
53
53
|
valueKey: "id",
|
|
54
|
+
groupLabelKey: "label",
|
|
54
55
|
yPosition: "bottom",
|
|
55
56
|
xPosition: "left",
|
|
57
|
+
optionsLimit: 0,
|
|
58
|
+
visibleOptions: 8,
|
|
59
|
+
labelDisplayCount: 2,
|
|
56
60
|
searchable: false,
|
|
57
61
|
round: false,
|
|
58
62
|
block: false,
|
|
59
63
|
square: false,
|
|
60
64
|
disabled: false,
|
|
61
65
|
multiple: false,
|
|
62
|
-
|
|
66
|
+
closeOnSelect: true,
|
|
63
67
|
/* icons */
|
|
64
68
|
toggleIcon: "keyboard_arrow_down",
|
|
65
69
|
},
|
|
@@ -12,10 +12,18 @@ import UCol from "../../ui.container-col/UCol.vue";
|
|
|
12
12
|
import UIcon from "../../ui.image-icon/UIcon.vue";
|
|
13
13
|
import ULink from "../../ui.button-link/ULink.vue";
|
|
14
14
|
import UAvatar from "../../ui.image-avatar/UAvatar.vue";
|
|
15
|
+
import UBadge from "../../ui.text-badge/UBadge.vue";
|
|
16
|
+
import UText from "../../ui.text-block/UText.vue";
|
|
17
|
+
import ULoader from "../../ui.loader/ULoader.vue";
|
|
15
18
|
|
|
16
19
|
import type { Meta, StoryFn } from "@storybook/vue3-vite";
|
|
17
20
|
import type { Props } from "../types";
|
|
18
21
|
|
|
22
|
+
import johnDoe from "../../ui.form-select/storybook/assets/images/john-doe.png";
|
|
23
|
+
import emilyDavis from "../../ui.form-select/storybook/assets/images/emily-davis.png";
|
|
24
|
+
import alexJohnson from "../../ui.form-select/storybook/assets/images/alex-johnson.png";
|
|
25
|
+
import patMorgan from "../../ui.form-select/storybook/assets/images/pat-morgan.png";
|
|
26
|
+
|
|
19
27
|
interface DefaultUDropdownButtonArgs extends Props {
|
|
20
28
|
slotTemplate?: string;
|
|
21
29
|
}
|
|
@@ -54,7 +62,7 @@ export default {
|
|
|
54
62
|
const DefaultTemplate: StoryFn<DefaultUDropdownButtonArgs> = (
|
|
55
63
|
args: DefaultUDropdownButtonArgs,
|
|
56
64
|
) => ({
|
|
57
|
-
components: { UDropdownButton, UIcon, ULink, UAvatar },
|
|
65
|
+
components: { UDropdownButton, UIcon, ULink, UAvatar, ULoader, URow, UText },
|
|
58
66
|
setup: () => ({ args, slots: getSlotNames(UDropdownButton.__name) }),
|
|
59
67
|
template: `
|
|
60
68
|
<UDropdownButton v-bind="args">
|
|
@@ -111,6 +119,35 @@ const MultiEnumTemplate: StoryFn<EnumUDropdownButtonArgs> = (
|
|
|
111
119
|
`,
|
|
112
120
|
});
|
|
113
121
|
|
|
122
|
+
const GroupValuesTemplate: StoryFn<DefaultUDropdownButtonArgs> = (
|
|
123
|
+
args: DefaultUDropdownButtonArgs,
|
|
124
|
+
) => ({
|
|
125
|
+
components: { UDropdownButton },
|
|
126
|
+
setup() {
|
|
127
|
+
return {
|
|
128
|
+
args,
|
|
129
|
+
};
|
|
130
|
+
},
|
|
131
|
+
template: `
|
|
132
|
+
<UDropdownButton
|
|
133
|
+
v-bind="args"
|
|
134
|
+
v-model="args.modelValue"
|
|
135
|
+
label="Single"
|
|
136
|
+
:config="{ listbox: 'min-w-[200px]' }"
|
|
137
|
+
class="max-w-96 mr-20"
|
|
138
|
+
/>
|
|
139
|
+
|
|
140
|
+
<UDropdownButton
|
|
141
|
+
v-bind="args"
|
|
142
|
+
v-model="args.modelValueMultiple"
|
|
143
|
+
label="Multiple"
|
|
144
|
+
multiple
|
|
145
|
+
:config="{ listbox: 'min-w-[200px]' }"
|
|
146
|
+
class="mt-5 max-w-96"
|
|
147
|
+
/>
|
|
148
|
+
`,
|
|
149
|
+
});
|
|
150
|
+
|
|
114
151
|
export const Default = DefaultTemplate.bind({});
|
|
115
152
|
Default.args = {};
|
|
116
153
|
Default.parameters = {
|
|
@@ -121,6 +158,9 @@ Default.parameters = {
|
|
|
121
158
|
},
|
|
122
159
|
};
|
|
123
160
|
|
|
161
|
+
export const Disabled = DefaultTemplate.bind({});
|
|
162
|
+
Disabled.args = { disabled: true };
|
|
163
|
+
|
|
124
164
|
export const Searchable = DefaultTemplate.bind({});
|
|
125
165
|
Searchable.args = { searchable: true };
|
|
126
166
|
Searchable.parameters = {
|
|
@@ -131,6 +171,27 @@ Searchable.parameters = {
|
|
|
131
171
|
},
|
|
132
172
|
};
|
|
133
173
|
|
|
174
|
+
export const SearchModelValue = DefaultTemplate.bind({});
|
|
175
|
+
SearchModelValue.args = { searchable: true, search: "Copy" };
|
|
176
|
+
SearchModelValue.parameters = {
|
|
177
|
+
docs: {
|
|
178
|
+
story: {
|
|
179
|
+
height: "250px",
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
export const NoCloseOnSelect = SelectableTemplate.bind({});
|
|
185
|
+
NoCloseOnSelect.args = {
|
|
186
|
+
modelValue: "pending",
|
|
187
|
+
options: [
|
|
188
|
+
{ label: "Active", id: "active" },
|
|
189
|
+
{ label: "Pending", id: "pending" },
|
|
190
|
+
{ label: "Archived", id: "archived" },
|
|
191
|
+
],
|
|
192
|
+
closeOnSelect: false,
|
|
193
|
+
};
|
|
194
|
+
|
|
134
195
|
export const OptionSelection = SelectableTemplate.bind({});
|
|
135
196
|
OptionSelection.args = {
|
|
136
197
|
label: "Select status",
|
|
@@ -176,8 +237,59 @@ ListboxYPosition.parameters = {
|
|
|
176
237
|
storyClasses: "h-[350px] flex items-center px-6 pt-8 pb-12",
|
|
177
238
|
};
|
|
178
239
|
|
|
179
|
-
export const
|
|
180
|
-
|
|
240
|
+
export const GroupValue = GroupValuesTemplate.bind({});
|
|
241
|
+
GroupValue.args = {
|
|
242
|
+
modelValue: "",
|
|
243
|
+
groupValueKey: "libs",
|
|
244
|
+
groupLabelKey: "language",
|
|
245
|
+
labelKey: "name",
|
|
246
|
+
valueKey: "name",
|
|
247
|
+
options: [
|
|
248
|
+
{
|
|
249
|
+
language: "Javascript",
|
|
250
|
+
libs: [{ name: "Vue.js" }, { name: "Adonis" }],
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
language: "Ruby",
|
|
254
|
+
libs: [
|
|
255
|
+
{ name: "Frameworks", isSubGroup: true, level: 2 },
|
|
256
|
+
{ name: "Rails", level: 3 },
|
|
257
|
+
{ name: "Sinatra", level: 3 },
|
|
258
|
+
],
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
language: "Other",
|
|
262
|
+
libs: [{ name: "Laravel" }, { name: "Phoenix" }],
|
|
263
|
+
},
|
|
264
|
+
],
|
|
265
|
+
};
|
|
266
|
+
GroupValue.parameters = {
|
|
267
|
+
docs: {
|
|
268
|
+
story: {
|
|
269
|
+
height: "400px",
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
export const OptionsLimit = DefaultTemplate.bind({});
|
|
275
|
+
OptionsLimit.args = { optionsLimit: 2 };
|
|
276
|
+
OptionsLimit.parameters = {
|
|
277
|
+
docs: {
|
|
278
|
+
description: {
|
|
279
|
+
story: "`optionsLimit` prop controls the number of options displayed in the dropdown.",
|
|
280
|
+
},
|
|
281
|
+
},
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
export const VisibleOptions = DefaultTemplate.bind({});
|
|
285
|
+
VisibleOptions.args = { visibleOptions: 2 };
|
|
286
|
+
VisibleOptions.parameters = {
|
|
287
|
+
docs: {
|
|
288
|
+
description: {
|
|
289
|
+
story: "`visibleOptions` prop controls the number of options you can see without a scroll.",
|
|
290
|
+
},
|
|
291
|
+
},
|
|
292
|
+
};
|
|
181
293
|
|
|
182
294
|
export const WithoutToggleIcon = Default.bind({});
|
|
183
295
|
WithoutToggleIcon.args = { toggleIcon: false };
|
|
@@ -228,3 +340,176 @@ ToggleSlot.args = {
|
|
|
228
340
|
</template>
|
|
229
341
|
`,
|
|
230
342
|
};
|
|
343
|
+
|
|
344
|
+
export const EmptySlot = DefaultTemplate.bind({});
|
|
345
|
+
EmptySlot.args = {
|
|
346
|
+
options: [],
|
|
347
|
+
slotTemplate: `
|
|
348
|
+
<template #empty>
|
|
349
|
+
<URow align="center">
|
|
350
|
+
<ULoader loading size="sm" />
|
|
351
|
+
<UText label="Loading, this may take a while..." />
|
|
352
|
+
</URow>
|
|
353
|
+
</template>
|
|
354
|
+
`,
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
export const OptionSlots: StoryFn<DefaultUDropdownButtonArgs> = (args) => ({
|
|
358
|
+
components: { UDropdownButton, URow, UCol, UAvatar, UIcon, UBadge, UText },
|
|
359
|
+
setup: () => ({ args, johnDoe, emilyDavis, alexJohnson, patMorgan }),
|
|
360
|
+
template: `
|
|
361
|
+
<URow>
|
|
362
|
+
<UDropdownButton
|
|
363
|
+
v-model="args.beforeOptionModel"
|
|
364
|
+
label="Before option slot"
|
|
365
|
+
:options="[
|
|
366
|
+
{
|
|
367
|
+
label: 'John Doe',
|
|
368
|
+
id: '1',
|
|
369
|
+
role: 'Developer',
|
|
370
|
+
avatar: johnDoe,
|
|
371
|
+
status: 'online',
|
|
372
|
+
statusColor: 'success',
|
|
373
|
+
},
|
|
374
|
+
{
|
|
375
|
+
label: 'Jane Smith',
|
|
376
|
+
id: '2',
|
|
377
|
+
role: 'Designer',
|
|
378
|
+
avatar: emilyDavis,
|
|
379
|
+
status: 'away',
|
|
380
|
+
statusColor: 'warning',
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
label: 'Mike Johnson',
|
|
384
|
+
id: '3',
|
|
385
|
+
role: 'Product Manager',
|
|
386
|
+
avatar: alexJohnson,
|
|
387
|
+
status: 'offline',
|
|
388
|
+
statusColor: 'grayscale',
|
|
389
|
+
},
|
|
390
|
+
{
|
|
391
|
+
label: 'Sarah Wilson',
|
|
392
|
+
id: '4',
|
|
393
|
+
role: 'QA Engineer',
|
|
394
|
+
avatar: patMorgan,
|
|
395
|
+
status: 'online',
|
|
396
|
+
statusColor: 'success',
|
|
397
|
+
},
|
|
398
|
+
]"
|
|
399
|
+
>
|
|
400
|
+
<template #before-option="{ option }">
|
|
401
|
+
<UAvatar :src="option.avatar" size="sm" />
|
|
402
|
+
</template>
|
|
403
|
+
</UDropdownButton>
|
|
404
|
+
|
|
405
|
+
<UDropdownButton
|
|
406
|
+
v-model="args.optionModel"
|
|
407
|
+
label="Option slot"
|
|
408
|
+
:options="[
|
|
409
|
+
{
|
|
410
|
+
label: 'John Doe',
|
|
411
|
+
id: '1',
|
|
412
|
+
role: 'Developer',
|
|
413
|
+
avatar: johnDoe,
|
|
414
|
+
status: 'online',
|
|
415
|
+
statusColor: 'success',
|
|
416
|
+
},
|
|
417
|
+
{
|
|
418
|
+
label: 'Jane Smith',
|
|
419
|
+
id: '2',
|
|
420
|
+
role: 'Designer',
|
|
421
|
+
avatar: emilyDavis,
|
|
422
|
+
status: 'away',
|
|
423
|
+
statusColor: 'warning',
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
label: 'Mike Johnson',
|
|
427
|
+
id: '3',
|
|
428
|
+
role: 'Product Manager',
|
|
429
|
+
avatar: alexJohnson,
|
|
430
|
+
status: 'offline',
|
|
431
|
+
statusColor: 'grayscale',
|
|
432
|
+
},
|
|
433
|
+
{
|
|
434
|
+
label: 'Sarah Wilson',
|
|
435
|
+
id: '4',
|
|
436
|
+
role: 'QA Engineer',
|
|
437
|
+
avatar: patMorgan,
|
|
438
|
+
status: 'online',
|
|
439
|
+
statusColor: 'success',
|
|
440
|
+
},
|
|
441
|
+
]"
|
|
442
|
+
>
|
|
443
|
+
<template #option="{ option }">
|
|
444
|
+
<URow align="center" gap="xs">
|
|
445
|
+
<UCol gap="none">
|
|
446
|
+
<UText size="sm">{{ option.label }}</UText>
|
|
447
|
+
<UText variant="lifted" size="xs">{{ option.role }}</UText>
|
|
448
|
+
</UCol>
|
|
449
|
+
<UBadge
|
|
450
|
+
:label="option.status"
|
|
451
|
+
:color="option.statusColor"
|
|
452
|
+
size="sm"
|
|
453
|
+
variant="subtle"
|
|
454
|
+
/>
|
|
455
|
+
</URow>
|
|
456
|
+
</template>
|
|
457
|
+
</UDropdownButton>
|
|
458
|
+
|
|
459
|
+
<UDropdownButton
|
|
460
|
+
v-model="args.afterOptionModel"
|
|
461
|
+
label="After option slot"
|
|
462
|
+
:options="[
|
|
463
|
+
{
|
|
464
|
+
label: 'John Doe',
|
|
465
|
+
id: '1',
|
|
466
|
+
role: 'Developer',
|
|
467
|
+
avatar: johnDoe,
|
|
468
|
+
status: 'online',
|
|
469
|
+
statusColor: 'success',
|
|
470
|
+
},
|
|
471
|
+
{
|
|
472
|
+
label: 'Jane Smith',
|
|
473
|
+
id: '2',
|
|
474
|
+
role: 'Designer',
|
|
475
|
+
avatar: emilyDavis,
|
|
476
|
+
status: 'away',
|
|
477
|
+
statusColor: 'warning',
|
|
478
|
+
},
|
|
479
|
+
{
|
|
480
|
+
label: 'Mike Johnson',
|
|
481
|
+
id: '3',
|
|
482
|
+
role: 'Product Manager',
|
|
483
|
+
avatar: alexJohnson,
|
|
484
|
+
status: 'offline',
|
|
485
|
+
statusColor: 'grayscale',
|
|
486
|
+
},
|
|
487
|
+
{
|
|
488
|
+
label: 'Sarah Wilson',
|
|
489
|
+
id: '4',
|
|
490
|
+
role: 'QA Engineer',
|
|
491
|
+
avatar: patMorgan,
|
|
492
|
+
status: 'online',
|
|
493
|
+
statusColor: 'success',
|
|
494
|
+
},
|
|
495
|
+
]"
|
|
496
|
+
>
|
|
497
|
+
<template #after-option="{ option }">
|
|
498
|
+
<UBadge
|
|
499
|
+
:label="option.status"
|
|
500
|
+
:color="option.statusColor"
|
|
501
|
+
size="sm"
|
|
502
|
+
variant="subtle"
|
|
503
|
+
/>
|
|
504
|
+
</template>
|
|
505
|
+
</UDropdownButton>
|
|
506
|
+
</URow>
|
|
507
|
+
`,
|
|
508
|
+
});
|
|
509
|
+
OptionSlots.parameters = {
|
|
510
|
+
docs: {
|
|
511
|
+
story: {
|
|
512
|
+
height: "300px",
|
|
513
|
+
},
|
|
514
|
+
},
|
|
515
|
+
};
|