vueless 0.0.807 → 0.0.809
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/README.md +5 -7
- package/package.json +1 -1
- package/ui.data-list/UDataList.vue +36 -100
- package/ui.data-list/config.ts +2 -10
- package/ui.data-list/storybook/docs.mdx +14 -22
- package/ui.data-list/storybook/stories.ts +123 -40
- package/ui.data-list/types.ts +3 -16
- package/ui.form-input-rating/storybook/stories.ts +0 -1
- package/ui.image-avatar/storybook/stories.ts +55 -41
- package/ui.image-icon/storybook/stories.ts +19 -1
package/README.md
CHANGED
|
@@ -56,13 +56,11 @@ That's it! You can use components in your app now ✨
|
|
|
56
56
|
|
|
57
57
|
## Contributing
|
|
58
58
|
|
|
59
|
-
We encourage you to contribute to Vueless! Please check out the
|
|
60
|
-
[
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
Everyone interacting in Vueless and its sub-projects' codebases, issue trackers, chat rooms, and mailing lists is expected to follow the Vueless [code of conduct](CODE_OF_CONDUCT.md).
|
|
59
|
+
* We encourage you to contribute to Vueless! Please check out the
|
|
60
|
+
[contributing to Vueless](CONTRIBUTING.md) for guidelines.
|
|
61
|
+
* Trying to report a possible security vulnerability in Vueless? Please
|
|
62
|
+
check out our [security policy](SECURITY.md) for guidelines.
|
|
63
|
+
* Everyone interacting in Vueless and its sub-projects' codebases, issue trackers, chats, and mailing lists is expected to follow our [code of conduct](CODE_OF_CONDUCT.md) rules.
|
|
66
64
|
|
|
67
65
|
## License
|
|
68
66
|
|
package/package.json
CHANGED
|
@@ -29,20 +29,6 @@ const emit = defineEmits([
|
|
|
29
29
|
* @property {array} sortData
|
|
30
30
|
*/
|
|
31
31
|
"dragSort",
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Triggers when edit button is clicked.
|
|
35
|
-
* @property {number} value
|
|
36
|
-
* @property {string} label
|
|
37
|
-
*/
|
|
38
|
-
"clickEdit",
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Triggers when delete button is clicked.
|
|
42
|
-
* @property {number} value
|
|
43
|
-
* @property {string} label
|
|
44
|
-
*/
|
|
45
|
-
"clickDelete",
|
|
46
32
|
]);
|
|
47
33
|
|
|
48
34
|
const { tm } = useLocale();
|
|
@@ -50,13 +36,13 @@ const { tm } = useLocale();
|
|
|
50
36
|
const i18nGlobal = tm(COMPONENT_NAME);
|
|
51
37
|
const currentLocale = computed(() => merge({}, defaultConfig.i18n, i18nGlobal, props.config.i18n));
|
|
52
38
|
|
|
53
|
-
function
|
|
54
|
-
return element.
|
|
39
|
+
function isCrossed(element: DataListItem) {
|
|
40
|
+
return Boolean(element.crossed);
|
|
55
41
|
}
|
|
56
42
|
|
|
57
43
|
function onDragMove(event: DragMoveEvent): boolean | void {
|
|
58
|
-
const isDisabledNestingItem = event.draggedContext.element.
|
|
59
|
-
const isNestingAction =
|
|
44
|
+
const isDisabledNestingItem = !Boolean(event.draggedContext.element.nesting);
|
|
45
|
+
const isNestingAction = Boolean(event.relatedContext?.element?.nesting);
|
|
60
46
|
|
|
61
47
|
if (isDisabledNestingItem && isNestingAction) {
|
|
62
48
|
return false;
|
|
@@ -69,14 +55,6 @@ function onDragEnd() {
|
|
|
69
55
|
emit("dragSort", sortData);
|
|
70
56
|
}
|
|
71
57
|
|
|
72
|
-
function onClickEdit(value: number, label: string) {
|
|
73
|
-
emit("clickEdit", value, label);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function onClickDelete(value: number, label: string) {
|
|
77
|
-
emit("clickDelete", value, label);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
58
|
function prepareSortData(list: DataListItem[] = [], parentValue: string | number | null = null) {
|
|
81
59
|
const sortData: DataListItem[] = [];
|
|
82
60
|
|
|
@@ -116,28 +94,27 @@ const {
|
|
|
116
94
|
labelAttrs,
|
|
117
95
|
labelCrossedAttrs,
|
|
118
96
|
customActionsAttrs,
|
|
119
|
-
deleteIconAttrs,
|
|
120
|
-
editIconAttrs,
|
|
121
97
|
dragIconAttrs,
|
|
98
|
+
dragAttrs,
|
|
122
99
|
} = useUI<Config>(defaultConfig);
|
|
123
100
|
</script>
|
|
124
101
|
|
|
125
102
|
<template>
|
|
126
103
|
<div v-bind="wrapperAttrs">
|
|
127
104
|
<!--
|
|
128
|
-
@slot Use it to add
|
|
105
|
+
@slot Use it to add custom empty state.
|
|
129
106
|
@binding {string} empty-title
|
|
130
107
|
@binding {string} empty-description
|
|
131
108
|
-->
|
|
132
109
|
<slot
|
|
133
110
|
v-if="!hideEmptyStateForNesting && !list?.length"
|
|
134
111
|
name="empty"
|
|
135
|
-
:empty-title="emptyTitle"
|
|
136
|
-
:empty-description="emptyDescription"
|
|
112
|
+
:empty-title="currentLocale.emptyTitle"
|
|
113
|
+
:empty-description="currentLocale.emptyDescription"
|
|
137
114
|
>
|
|
138
115
|
<UEmpty
|
|
139
|
-
:title="
|
|
140
|
-
:description="
|
|
116
|
+
:title="currentLocale.emptyTitle"
|
|
117
|
+
:description="currentLocale.emptyDescription"
|
|
141
118
|
v-bind="emptyAttrs"
|
|
142
119
|
/>
|
|
143
120
|
</slot>
|
|
@@ -159,105 +136,64 @@ const {
|
|
|
159
136
|
<template #item="{ element }">
|
|
160
137
|
<div :id="element[valueKey]" v-bind="itemWrapperAttrs" :data-test="getDataTest('item')">
|
|
161
138
|
<div v-bind="itemAttrs" :data-test="getDataTest(`item-${element[valueKey]}`)">
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
<
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
139
|
+
<div v-bind="dragAttrs">
|
|
140
|
+
<!--
|
|
141
|
+
@slot Use it to add something instead of the drag icon.
|
|
142
|
+
@binding {object} item
|
|
143
|
+
@binding {string} icon-name
|
|
144
|
+
-->
|
|
145
|
+
<slot name="drag" :item="element" :icon-name="config.defaults.dragIcon">
|
|
146
|
+
<UIcon
|
|
147
|
+
internal
|
|
148
|
+
color="gray"
|
|
149
|
+
variant="light"
|
|
150
|
+
:name="config.defaults.dragIcon"
|
|
151
|
+
v-bind="dragIconAttrs"
|
|
152
|
+
/>
|
|
153
|
+
</slot>
|
|
154
|
+
</div>
|
|
176
155
|
|
|
177
|
-
<div v-bind="
|
|
156
|
+
<div v-bind="isCrossed(element) ? labelCrossedAttrs : labelAttrs">
|
|
178
157
|
<!--
|
|
179
158
|
@slot Use it to modify label.
|
|
180
159
|
@binding {object} item
|
|
181
|
-
@binding {boolean}
|
|
160
|
+
@binding {boolean} crossed
|
|
182
161
|
-->
|
|
183
|
-
<slot name="label" :item="element" :
|
|
162
|
+
<slot name="label" :item="element" :crossed="isCrossed(element)">
|
|
184
163
|
{{ element[labelKey] }}
|
|
185
164
|
</slot>
|
|
186
165
|
</div>
|
|
187
166
|
|
|
188
|
-
<template v-if="
|
|
189
|
-
<div
|
|
190
|
-
v-if="hasSlotContent($slots['actions']) && !element.isHiddenCustomActions"
|
|
191
|
-
v-bind="customActionsAttrs"
|
|
192
|
-
>
|
|
167
|
+
<template v-if="element.actions !== false">
|
|
168
|
+
<div v-if="hasSlotContent($slots['actions'])" v-bind="customActionsAttrs">
|
|
193
169
|
<!--
|
|
194
170
|
@slot Use it to add custom actions.
|
|
195
171
|
@binding {object} item
|
|
196
172
|
-->
|
|
197
173
|
<slot name="actions" :item="element" />
|
|
198
174
|
</div>
|
|
199
|
-
|
|
200
|
-
<!--
|
|
201
|
-
@slot Use it to add something instead of the delete icon.
|
|
202
|
-
@binding {object} item
|
|
203
|
-
@binding {string} icon-name
|
|
204
|
-
-->
|
|
205
|
-
<slot name="delete" :item="element" :icon-name="config.defaults.deleteIcon">
|
|
206
|
-
<UIcon
|
|
207
|
-
v-if="!element.isHiddenDelete"
|
|
208
|
-
internal
|
|
209
|
-
interactive
|
|
210
|
-
color="red"
|
|
211
|
-
:name="config.defaults.deleteIcon"
|
|
212
|
-
:tooltip="currentLocale.delete"
|
|
213
|
-
v-bind="deleteIconAttrs"
|
|
214
|
-
:data-test="getDataTest('delete')"
|
|
215
|
-
@click="onClickDelete(element[valueKey], element[labelKey])"
|
|
216
|
-
/>
|
|
217
|
-
</slot>
|
|
218
|
-
|
|
219
|
-
<!--
|
|
220
|
-
@slot Use it to add something instead of the edit icon.
|
|
221
|
-
@binding {object} item
|
|
222
|
-
@binding {string} icon-name
|
|
223
|
-
-->
|
|
224
|
-
<slot name="edit" :item="element" :icon-name="config.defaults.editIcon">
|
|
225
|
-
<UIcon
|
|
226
|
-
v-if="!element.isHiddenEdit"
|
|
227
|
-
internal
|
|
228
|
-
interactive
|
|
229
|
-
color="gray"
|
|
230
|
-
:name="config.defaults.editIcon"
|
|
231
|
-
:tooltip="currentLocale.edit"
|
|
232
|
-
v-bind="editIconAttrs"
|
|
233
|
-
:data-test="getDataTest('edit')"
|
|
234
|
-
@click="onClickEdit(element[valueKey], element[labelKey])"
|
|
235
|
-
/>
|
|
236
|
-
</slot>
|
|
237
175
|
</template>
|
|
238
176
|
</div>
|
|
239
177
|
|
|
240
178
|
<UDataList
|
|
241
|
-
v-if="nesting &&
|
|
179
|
+
v-if="nesting && element.nesting"
|
|
242
180
|
:nesting="nesting"
|
|
243
181
|
hide-empty-state-for-nesting
|
|
244
182
|
:list="element.children"
|
|
245
183
|
:group="group"
|
|
246
184
|
v-bind="nestedAttrs"
|
|
247
185
|
:data-test="getDataTest('table')"
|
|
248
|
-
@click-delete="onClickDelete"
|
|
249
|
-
@click-edit="onClickEdit"
|
|
250
186
|
@drag-sort="onDragEnd"
|
|
251
187
|
>
|
|
252
|
-
<template #label="slotProps: { item: DataListItem;
|
|
188
|
+
<template #label="slotProps: { item: DataListItem; crossed: boolean }">
|
|
253
189
|
<!--
|
|
254
190
|
@slot Use it to modify label.
|
|
255
191
|
@binding {object} item
|
|
256
|
-
@binding {boolean}
|
|
192
|
+
@binding {boolean} crossed
|
|
257
193
|
-->
|
|
258
|
-
<slot name="label" :item="slotProps.item" :
|
|
194
|
+
<slot name="label" :item="slotProps.item" :crossed="slotProps.crossed">
|
|
259
195
|
<div
|
|
260
|
-
v-bind="slotProps.
|
|
196
|
+
v-bind="slotProps.crossed ? labelCrossedAttrs : labelAttrs"
|
|
261
197
|
v-text="slotProps.item[labelKey]"
|
|
262
198
|
/>
|
|
263
199
|
</slot>
|
package/ui.data-list/config.ts
CHANGED
|
@@ -29,6 +29,7 @@ export default /*tw*/ {
|
|
|
29
29
|
},
|
|
30
30
|
},
|
|
31
31
|
},
|
|
32
|
+
drag: "icon-drag cursor-move",
|
|
32
33
|
dragIcon: "{UIcon} {>dataListIcon} icon-drag cursor-move opacity-100",
|
|
33
34
|
label: {
|
|
34
35
|
base: "font-normal flex-auto pt-px",
|
|
@@ -41,18 +42,11 @@ export default /*tw*/ {
|
|
|
41
42
|
},
|
|
42
43
|
},
|
|
43
44
|
labelCrossed: "{>label} line-through",
|
|
44
|
-
customActions:
|
|
45
|
-
space-x-5 opacity-50 md:flex md:items-center md:opacity-0
|
|
46
|
-
group-hover/item:md:block group-hover/item:opacity-100
|
|
47
|
-
`,
|
|
48
|
-
deleteIcon: "{UIcon} {>dataListIcon} hidden md:block md:opacity-0 group-hover/item:md:opacity-100",
|
|
49
|
-
editIcon: "{UIcon} {>dataListIcon} fill-gray-500 opacity-50",
|
|
45
|
+
customActions: "space-x-5 opacity-50 flex items-center md:opacity-0 group-hover/item:opacity-100",
|
|
50
46
|
divider: "{UDivider}",
|
|
51
47
|
empty: "{UEmpty}",
|
|
52
48
|
nested: "{UDataList} group/nested ml-6",
|
|
53
49
|
i18n: {
|
|
54
|
-
edit: "Edit",
|
|
55
|
-
delete: "Delete",
|
|
56
50
|
emptyTitle: "",
|
|
57
51
|
emptyDescription: "There is no data in the list.",
|
|
58
52
|
},
|
|
@@ -64,7 +58,5 @@ export default /*tw*/ {
|
|
|
64
58
|
nesting: false,
|
|
65
59
|
/* icons */
|
|
66
60
|
dragIcon: "drag_indicator",
|
|
67
|
-
deleteIcon: "delete",
|
|
68
|
-
editIcon: "edit_note",
|
|
69
61
|
},
|
|
70
62
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Meta, Title, Subtitle, Description, Primary, Controls, Stories, Source } from "@storybook/blocks";
|
|
1
|
+
import { Markdown, Meta, Title, Subtitle, Description, Primary, Controls, Stories, Source } from "@storybook/blocks";
|
|
2
2
|
import { getSource } from "../../utils/storybook.ts";
|
|
3
3
|
|
|
4
4
|
import * as stories from "./stories.ts";
|
|
@@ -13,28 +13,20 @@ import defaultConfig from "../config.ts?raw"
|
|
|
13
13
|
<Stories of={stories} />
|
|
14
14
|
|
|
15
15
|
## Configuring items in a list
|
|
16
|
-
You can configure any item in a list by passing the following params
|
|
16
|
+
You can configure any item in a `list` array by passing the following params:
|
|
17
17
|
|
|
18
|
-
<
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
isHiddenDelete: true, // hide delete button
|
|
31
|
-
isHiddenActions: true, // hide default and custom action buttons
|
|
32
|
-
isHiddenCustomActions: true, // hide only custom action buttons
|
|
33
|
-
isDisabledNesting: true, // disable nesting for the item
|
|
34
|
-
}
|
|
35
|
-
{...}
|
|
36
|
-
];
|
|
37
|
-
`} language="jsx" dark />
|
|
18
|
+
<Markdown>
|
|
19
|
+
{`
|
|
20
|
+
| Key name | Description | Type | Default |
|
|
21
|
+
| ----------------------| ------------------------------------------------------ | ---------------| --------|
|
|
22
|
+
| id | Unique item identifier | String, Number | |
|
|
23
|
+
| label | Item label | String | |
|
|
24
|
+
| children | Nested items | Array | |
|
|
25
|
+
| crossed | Controls item style (line-through decoration) | Boolean | false |
|
|
26
|
+
| actions | Show custom actions buttons | Boolean | true |
|
|
27
|
+
| nesting | Enable nesting for the item | Boolean | false |
|
|
28
|
+
`}
|
|
29
|
+
</Markdown>
|
|
38
30
|
|
|
39
31
|
## Default config
|
|
40
32
|
<Source code={getSource(defaultConfig)} language="jsx" dark />
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ref } from "vue";
|
|
1
2
|
import {
|
|
2
3
|
getArgTypes,
|
|
3
4
|
getSlotNames,
|
|
@@ -9,12 +10,18 @@ import UDataList from "../../ui.data-list/UDataList.vue";
|
|
|
9
10
|
import UIcon from "../../ui.image-icon/UIcon.vue";
|
|
10
11
|
import UButton from "../../ui.button/UButton.vue";
|
|
11
12
|
import URow from "../../ui.container-row/URow.vue";
|
|
13
|
+
import UBadge from "../../ui.text-badge/UBadge.vue";
|
|
14
|
+
import UAvatar from "../../ui.image-avatar/UAvatar.vue";
|
|
15
|
+
import UHeader from "../../ui.text-header/UHeader.vue";
|
|
16
|
+
import ULoader from "../../ui.loader/ULoader.vue";
|
|
17
|
+
import tooltip from "../../directives/tooltip/vTooltip.ts";
|
|
12
18
|
|
|
13
19
|
import type { Meta, StoryFn } from "@storybook/vue3";
|
|
14
|
-
import type { Props } from "../types.ts";
|
|
20
|
+
import type { Props, DataListItem } from "../types.ts";
|
|
15
21
|
|
|
16
22
|
interface UDataListArgs extends Props {
|
|
17
23
|
slotTemplate?: string;
|
|
24
|
+
enum: "size";
|
|
18
25
|
}
|
|
19
26
|
|
|
20
27
|
export default {
|
|
@@ -24,25 +31,34 @@ export default {
|
|
|
24
31
|
args: {
|
|
25
32
|
list: [
|
|
26
33
|
{
|
|
27
|
-
label: "
|
|
34
|
+
label: "Expenses",
|
|
28
35
|
id: 1,
|
|
36
|
+
nesting: true,
|
|
29
37
|
children: [
|
|
30
|
-
{ label: "
|
|
31
|
-
{ label: "
|
|
32
|
-
{ label: "
|
|
38
|
+
{ label: "Office Supplies", id: 1.1 },
|
|
39
|
+
{ label: "Travel & Lodging", id: 1.2 },
|
|
40
|
+
{ label: "Utilities", id: 1.3 },
|
|
33
41
|
],
|
|
34
42
|
},
|
|
35
43
|
{
|
|
36
|
-
label: "
|
|
44
|
+
label: "Revenue Streams",
|
|
37
45
|
id: 2,
|
|
46
|
+
nesting: true,
|
|
38
47
|
children: [
|
|
39
|
-
{ label: "
|
|
40
|
-
{ label: "
|
|
48
|
+
{ label: "Product Sales", id: 2.1 },
|
|
49
|
+
{ label: "Subscription Services", id: 2.2 },
|
|
50
|
+
{ label: "Consulting", id: 2.3 },
|
|
41
51
|
],
|
|
42
52
|
},
|
|
43
53
|
{
|
|
44
|
-
label: "
|
|
54
|
+
label: "Departments",
|
|
45
55
|
id: 3,
|
|
56
|
+
nesting: true,
|
|
57
|
+
children: [
|
|
58
|
+
{ label: "Engineering", id: 3.1 },
|
|
59
|
+
{ label: "Marketing", id: 3.2 },
|
|
60
|
+
{ label: "Finance", id: 3.3 },
|
|
61
|
+
],
|
|
46
62
|
},
|
|
47
63
|
],
|
|
48
64
|
},
|
|
@@ -57,76 +73,143 @@ export default {
|
|
|
57
73
|
} as Meta;
|
|
58
74
|
|
|
59
75
|
const DefaultTemplate: StoryFn<UDataListArgs> = (args: UDataListArgs) => ({
|
|
60
|
-
components: { UDataList, UIcon, URow, UButton },
|
|
76
|
+
components: { UDataList, UIcon, URow, UButton, UBadge, UAvatar, ULoader, UHeader },
|
|
77
|
+
directives: { tooltip },
|
|
61
78
|
setup() {
|
|
62
79
|
const slots = getSlotNames(UDataList.__name);
|
|
63
80
|
|
|
64
|
-
|
|
81
|
+
const avatars = [
|
|
82
|
+
"https://cdn-icons-png.flaticon.com/128/1999/1999625.png",
|
|
83
|
+
"https://cdn-icons-png.flaticon.com/128/4140/4140057.png",
|
|
84
|
+
"https://cdn-icons-png.flaticon.com/128/4140/4140047.png",
|
|
85
|
+
];
|
|
86
|
+
|
|
87
|
+
const list = ref(
|
|
88
|
+
args.list?.map((item, index) => ({
|
|
89
|
+
...item,
|
|
90
|
+
id: item.id,
|
|
91
|
+
avatar: avatars[index % avatars.length],
|
|
92
|
+
})),
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
function removeItem(targetItem: DataListItem) {
|
|
96
|
+
list.value = list.value?.filter((listItem) => listItem.id !== targetItem.id);
|
|
97
|
+
|
|
98
|
+
return alert(`Removed item: ${JSON.stringify(targetItem, null, 2)}`);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function editItem(targetItem: DataListItem) {
|
|
102
|
+
alert(`Edit item: ${JSON.stringify(targetItem, null, 2)}`);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return { args, slots, removeItem, editItem, list };
|
|
65
106
|
},
|
|
66
107
|
template: `
|
|
67
|
-
<UDataList v-bind="args">
|
|
108
|
+
<UDataList v-bind="args" :list="args.slotTemplate ? list : args.list">
|
|
68
109
|
${args.slotTemplate || getSlotsFragment("")}
|
|
69
110
|
</UDataList>
|
|
70
111
|
`,
|
|
71
112
|
});
|
|
72
113
|
|
|
114
|
+
const EnumVariantTemplate: StoryFn<UDataListArgs> = (args: UDataListArgs, { argTypes }) => ({
|
|
115
|
+
components: { URow, UDataList, UHeader },
|
|
116
|
+
setup() {
|
|
117
|
+
return {
|
|
118
|
+
args,
|
|
119
|
+
options: argTypes?.[args.enum]?.options,
|
|
120
|
+
};
|
|
121
|
+
},
|
|
122
|
+
template: `
|
|
123
|
+
<div v-for="(option, index) in options" :key="index">
|
|
124
|
+
<UHeader :label="option" size="xs" />
|
|
125
|
+
<UDataList v-bind="args" :[args.enum]="option" class="mb-4" />
|
|
126
|
+
</div>
|
|
127
|
+
`,
|
|
128
|
+
});
|
|
129
|
+
|
|
73
130
|
export const Default = DefaultTemplate.bind({});
|
|
74
131
|
Default.args = {};
|
|
75
132
|
|
|
76
133
|
export const EmptyState = DefaultTemplate.bind({});
|
|
77
|
-
EmptyState.args = {
|
|
78
|
-
list: [],
|
|
79
|
-
emptyTitle: "The list is empty.",
|
|
80
|
-
emptyDescription: "There is no data in the list.",
|
|
81
|
-
};
|
|
134
|
+
EmptyState.args = { list: [] };
|
|
82
135
|
|
|
83
136
|
export const Nesting = DefaultTemplate.bind({});
|
|
84
137
|
Nesting.args = { nesting: true };
|
|
85
138
|
|
|
139
|
+
export const Size = EnumVariantTemplate.bind({});
|
|
140
|
+
Size.args = { enum: "size" };
|
|
141
|
+
|
|
86
142
|
export const SlotLabel = DefaultTemplate.bind({});
|
|
87
143
|
SlotLabel.args = {
|
|
88
144
|
slotTemplate: `
|
|
89
145
|
<template #label="{ item }">
|
|
90
|
-
<
|
|
91
|
-
{{ item.label }}
|
|
92
|
-
<UIcon name="check" color="green" size="sm" />
|
|
93
|
-
</URow>
|
|
146
|
+
<UBadge :label="item.label" />
|
|
94
147
|
</template>
|
|
95
148
|
`,
|
|
96
149
|
};
|
|
97
150
|
|
|
98
|
-
export const
|
|
99
|
-
|
|
151
|
+
export const SlotEmpty = DefaultTemplate.bind({});
|
|
152
|
+
SlotEmpty.args = {
|
|
153
|
+
list: [],
|
|
154
|
+
config: {
|
|
155
|
+
wrapper: "flex flex-col items-center justify-center py-10 gap-4",
|
|
156
|
+
i18n: {
|
|
157
|
+
emptyTitle: "Fetching data...",
|
|
158
|
+
emptyDescription: "Please wait until data is received.",
|
|
159
|
+
},
|
|
160
|
+
},
|
|
100
161
|
slotTemplate: `
|
|
101
|
-
<template #
|
|
102
|
-
<
|
|
162
|
+
<template #empty="{ emptyTitle, emptyDescription }">
|
|
163
|
+
<ULoader loading size="lg" />
|
|
164
|
+
<UHeader :label="emptyTitle" size="xs" />
|
|
165
|
+
<p>{{ emptyDescription }}</p>
|
|
103
166
|
</template>
|
|
104
167
|
`,
|
|
105
168
|
};
|
|
169
|
+
SlotEmpty.parameters = {
|
|
170
|
+
docs: {
|
|
171
|
+
description: {
|
|
172
|
+
story:
|
|
173
|
+
"You can customize the `empty` slot's props (`emptyTitle` and `emptyDescription`) using the `i18n` config key.",
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
};
|
|
106
177
|
|
|
107
178
|
export const SlotDrag = DefaultTemplate.bind({});
|
|
108
179
|
SlotDrag.args = {
|
|
180
|
+
list: [
|
|
181
|
+
{ label: "John Doe (Engineering)", id: 1 },
|
|
182
|
+
{ label: "Michael Johnson (Finance)", id: 2 },
|
|
183
|
+
{ label: "Emma Smith (Marketing)", id: 3 },
|
|
184
|
+
],
|
|
109
185
|
slotTemplate: `
|
|
110
|
-
<template #drag>
|
|
111
|
-
<
|
|
186
|
+
<template #drag="{ item }">
|
|
187
|
+
<UAvatar :src="item.avatar" rounded="full" />
|
|
112
188
|
</template>
|
|
113
189
|
`,
|
|
114
190
|
};
|
|
115
191
|
|
|
116
|
-
export const
|
|
117
|
-
|
|
118
|
-
slotTemplate: `
|
|
119
|
-
<template #delete>
|
|
120
|
-
<UButton label="Delete" size="xs" variant="secondary" color="red" />
|
|
121
|
-
</template>
|
|
122
|
-
`,
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
export const SlotEdit = DefaultTemplate.bind({});
|
|
126
|
-
SlotEdit.args = {
|
|
192
|
+
export const SlotActions = DefaultTemplate.bind({});
|
|
193
|
+
SlotActions.args = {
|
|
127
194
|
slotTemplate: `
|
|
128
|
-
<template #
|
|
129
|
-
<UButton label="
|
|
195
|
+
<template #actions="{ item }">
|
|
196
|
+
<UButton label="Export" size="xs" />
|
|
197
|
+
<UIcon
|
|
198
|
+
name="delete"
|
|
199
|
+
size="sm"
|
|
200
|
+
color="red"
|
|
201
|
+
interactive
|
|
202
|
+
v-tooltip="'Delete'"
|
|
203
|
+
@click="removeItem(item)"
|
|
204
|
+
/>
|
|
205
|
+
<UIcon
|
|
206
|
+
name="edit_note"
|
|
207
|
+
size="sm"
|
|
208
|
+
color="grayscale"
|
|
209
|
+
interactive
|
|
210
|
+
v-tooltip="'Edit'"
|
|
211
|
+
@click="editItem(item)"
|
|
212
|
+
/>
|
|
130
213
|
</template>
|
|
131
214
|
`,
|
|
132
215
|
};
|
package/ui.data-list/types.ts
CHANGED
|
@@ -12,12 +12,9 @@ export interface DragMoveEvent extends DragEvent {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export interface DataListItem {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
isHiddenDelete?: boolean;
|
|
19
|
-
isHiddenEdit?: boolean;
|
|
20
|
-
isDisabledNesting?: boolean;
|
|
15
|
+
crossed?: boolean;
|
|
16
|
+
actions?: boolean;
|
|
17
|
+
nesting?: boolean;
|
|
21
18
|
children?: DataListItem[];
|
|
22
19
|
[key: string]: UnknownType | DataListItem[];
|
|
23
20
|
}
|
|
@@ -48,16 +45,6 @@ export interface Props {
|
|
|
48
45
|
*/
|
|
49
46
|
valueKey?: string;
|
|
50
47
|
|
|
51
|
-
/**
|
|
52
|
-
* Empty state title.
|
|
53
|
-
*/
|
|
54
|
-
emptyTitle?: string;
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Empty state description.
|
|
58
|
-
*/
|
|
59
|
-
emptyDescription?: string;
|
|
60
|
-
|
|
61
48
|
/**
|
|
62
49
|
* Drag animation duration.
|
|
63
50
|
*/
|
|
@@ -7,8 +7,8 @@ import {
|
|
|
7
7
|
|
|
8
8
|
import UAvatar from "../../ui.image-avatar/UAvatar.vue";
|
|
9
9
|
import URow from "../../ui.container-row/URow.vue";
|
|
10
|
-
import UCol from "../../ui.container-col/UCol.vue";
|
|
11
10
|
import ULoader from "../../ui.loader/ULoader.vue";
|
|
11
|
+
import tooltip from "../../directives/tooltip/vTooltip.ts";
|
|
12
12
|
|
|
13
13
|
import type { Meta, StoryFn } from "@storybook/vue3";
|
|
14
14
|
import type { UAvatarProps } from "../types.ts";
|
|
@@ -47,7 +47,8 @@ const DefaultTemplate: StoryFn<UAvatarArgs> = (args: UAvatarArgs) => ({
|
|
|
47
47
|
});
|
|
48
48
|
|
|
49
49
|
const EnumVariantTemplate: StoryFn<UAvatarArgs> = (args: UAvatarArgs, { argTypes }) => ({
|
|
50
|
-
components: {
|
|
50
|
+
components: { URow, UAvatar },
|
|
51
|
+
directives: { tooltip },
|
|
51
52
|
setup() {
|
|
52
53
|
return {
|
|
53
54
|
args,
|
|
@@ -55,26 +56,16 @@ const EnumVariantTemplate: StoryFn<UAvatarArgs> = (args: UAvatarArgs, { argTypes
|
|
|
55
56
|
};
|
|
56
57
|
},
|
|
57
58
|
template: `
|
|
58
|
-
<
|
|
59
|
-
<
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
<URow>
|
|
69
|
-
<UAvatar
|
|
70
|
-
v-for="(option, index) in options"
|
|
71
|
-
:key="index"
|
|
72
|
-
v-bind="args"
|
|
73
|
-
:[args.enum]="option"
|
|
74
|
-
:label="''"
|
|
75
|
-
/>
|
|
76
|
-
</URow>
|
|
77
|
-
</UCol>
|
|
59
|
+
<URow>
|
|
60
|
+
<UAvatar
|
|
61
|
+
v-for="(option, index) in options"
|
|
62
|
+
:key="index"
|
|
63
|
+
v-bind="args"
|
|
64
|
+
:[args.enum]="option"
|
|
65
|
+
:label="option"
|
|
66
|
+
v-tooltip="option"
|
|
67
|
+
/>
|
|
68
|
+
</URow>
|
|
78
69
|
`,
|
|
79
70
|
});
|
|
80
71
|
|
|
@@ -83,43 +74,66 @@ Default.args = { size: "3xl" };
|
|
|
83
74
|
|
|
84
75
|
export const Src = DefaultTemplate.bind({});
|
|
85
76
|
Src.args = {
|
|
86
|
-
src: "https://
|
|
77
|
+
src: "https://i.pravatar.cc/300?img=67",
|
|
78
|
+
size: "3xl",
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export const PlaceholderIcon = DefaultTemplate.bind({});
|
|
82
|
+
PlaceholderIcon.args = {
|
|
83
|
+
placeholderIcon: "account_circle",
|
|
87
84
|
size: "3xl",
|
|
88
85
|
};
|
|
89
86
|
|
|
90
87
|
export const Label = DefaultTemplate.bind({});
|
|
91
88
|
Label.args = { label: "Name Surname", size: "3xl" };
|
|
92
89
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
90
|
+
export const Size = EnumVariantTemplate.bind({});
|
|
91
|
+
Size.args = { enum: "size" };
|
|
92
|
+
Size.parameters = {
|
|
93
|
+
docs: {
|
|
94
|
+
description: {
|
|
95
|
+
story: "Hold cursor above an avatar to see the value.",
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
};
|
|
98
99
|
|
|
99
|
-
/**
|
|
100
|
-
* Hold cursor above an avatar to see value.
|
|
101
|
-
*/
|
|
102
100
|
export const Rounded = EnumVariantTemplate.bind({});
|
|
103
101
|
Rounded.args = { enum: "rounded", label: "John Doe", color: "orange" };
|
|
102
|
+
Rounded.parameters = {
|
|
103
|
+
docs: {
|
|
104
|
+
description: {
|
|
105
|
+
story: "Hold cursor above an avatar to see the value.",
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
};
|
|
104
109
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
+
export const Color = EnumVariantTemplate.bind({});
|
|
111
|
+
Color.args = { enum: "color" };
|
|
112
|
+
Color.parameters = {
|
|
113
|
+
docs: {
|
|
114
|
+
description: {
|
|
115
|
+
story: "Hold cursor above an avatar to see the value.",
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
};
|
|
110
119
|
|
|
111
|
-
/**
|
|
112
|
-
* Hold cursor above an avatar to see value.
|
|
113
|
-
*/
|
|
114
120
|
export const Bordered = EnumVariantTemplate.bind({});
|
|
115
121
|
Bordered.args = { enum: "color", bordered: true };
|
|
122
|
+
Bordered.parameters = {
|
|
123
|
+
docs: {
|
|
124
|
+
description: {
|
|
125
|
+
story: "Hold cursor above an avatar to see the value.",
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
};
|
|
116
129
|
|
|
117
130
|
export const SlotPlaceholder = DefaultTemplate.bind({});
|
|
118
131
|
SlotPlaceholder.args = {
|
|
132
|
+
color: "green",
|
|
119
133
|
size: "3xl",
|
|
120
134
|
slotTemplate: `
|
|
121
|
-
<template #placeholder>
|
|
122
|
-
<ULoader loading />
|
|
135
|
+
<template #placeholder="{ iconColor }">
|
|
136
|
+
<ULoader loading :color="iconColor" />
|
|
123
137
|
</template>
|
|
124
138
|
`,
|
|
125
139
|
};
|
|
@@ -7,6 +7,9 @@ import {
|
|
|
7
7
|
|
|
8
8
|
import UIcon from "../../ui.image-icon/UIcon.vue";
|
|
9
9
|
import URow from "../../ui.container-row/URow.vue";
|
|
10
|
+
import tooltip from "../../directives/tooltip/vTooltip.ts";
|
|
11
|
+
|
|
12
|
+
import Beverage from "../../assets/icons/vueless/emoji_food_beverage.svg?component";
|
|
10
13
|
|
|
11
14
|
import type { Meta, StoryFn } from "@storybook/vue3";
|
|
12
15
|
import type { Props } from "../types.ts";
|
|
@@ -35,6 +38,7 @@ export default {
|
|
|
35
38
|
|
|
36
39
|
const DefaultTemplate: StoryFn<UIconArgs> = (args: UIconArgs) => ({
|
|
37
40
|
components: { UIcon },
|
|
41
|
+
directives: { tooltip },
|
|
38
42
|
setup() {
|
|
39
43
|
const slots = getSlotNames(UIcon.__name);
|
|
40
44
|
|
|
@@ -49,6 +53,7 @@ const DefaultTemplate: StoryFn<UIconArgs> = (args: UIconArgs) => ({
|
|
|
49
53
|
|
|
50
54
|
const EnumVariantTemplate: StoryFn<UIconArgs> = (args: UIconArgs, { argTypes }) => ({
|
|
51
55
|
components: { UIcon, URow },
|
|
56
|
+
directives: { tooltip },
|
|
52
57
|
setup() {
|
|
53
58
|
return {
|
|
54
59
|
args,
|
|
@@ -62,6 +67,7 @@ const EnumVariantTemplate: StoryFn<UIconArgs> = (args: UIconArgs, { argTypes })
|
|
|
62
67
|
:key="index"
|
|
63
68
|
v-bind="args"
|
|
64
69
|
:[args.enum]="option"
|
|
70
|
+
v-tooltip="option"
|
|
65
71
|
/>
|
|
66
72
|
</URow>
|
|
67
73
|
`,
|
|
@@ -70,6 +76,18 @@ const EnumVariantTemplate: StoryFn<UIconArgs> = (args: UIconArgs, { argTypes })
|
|
|
70
76
|
export const Default = DefaultTemplate.bind({});
|
|
71
77
|
Default.args = {};
|
|
72
78
|
|
|
79
|
+
export const Src = DefaultTemplate.bind({});
|
|
80
|
+
Src.args = { src: Beverage };
|
|
81
|
+
Src.parameters = {
|
|
82
|
+
docs: {
|
|
83
|
+
description: {
|
|
84
|
+
story:
|
|
85
|
+
// eslint-disable-next-line vue/max-len
|
|
86
|
+
"To use a custom icon, import it with the suffix `?component` and pass the imported component in the `src` prop, like this: <br/> `import Beverage from '../../assets/icons/vueless/emoji_food_beverage.svg?component'`",
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
|
|
73
91
|
export const Colors = EnumVariantTemplate.bind({});
|
|
74
92
|
Colors.args = { enum: "color" };
|
|
75
93
|
|
|
@@ -77,7 +95,7 @@ export const Sizes = EnumVariantTemplate.bind({});
|
|
|
77
95
|
Sizes.args = { enum: "size" };
|
|
78
96
|
|
|
79
97
|
export const Variants = EnumVariantTemplate.bind({});
|
|
80
|
-
Variants.args = { enum: "variant", color: "
|
|
98
|
+
Variants.args = { enum: "variant", color: "green" };
|
|
81
99
|
|
|
82
100
|
export const Interactive = DefaultTemplate.bind({});
|
|
83
101
|
Interactive.args = { interactive: true };
|