vueless 0.0.808 → 0.0.810
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/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.data-table/UTable.vue +17 -23
- package/ui.data-table/config.ts +2 -0
- package/ui.data-table/storybook/stories.ts +275 -228
- 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/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
|
*/
|
package/ui.data-table/UTable.vue
CHANGED
|
@@ -475,6 +475,7 @@ const {
|
|
|
475
475
|
headerCheckboxAttrs,
|
|
476
476
|
headerCounterAttrs,
|
|
477
477
|
bodyEmptyStateAttrs,
|
|
478
|
+
bodyEmptyStateCellAttrs,
|
|
478
479
|
bodyDateDividerAttrs,
|
|
479
480
|
bodySelectedDateDividerAttrs,
|
|
480
481
|
bodyCellDateDividerAttrs,
|
|
@@ -544,13 +545,6 @@ const {
|
|
|
544
545
|
<template v-else>
|
|
545
546
|
{{ column.label }}
|
|
546
547
|
</template>
|
|
547
|
-
|
|
548
|
-
<!--
|
|
549
|
-
@slot Use it to add something after the needed header cell.
|
|
550
|
-
@binding {object} column
|
|
551
|
-
@binding {number} index
|
|
552
|
-
-->
|
|
553
|
-
<slot :name="`header-${column.key}-after`" :column="column" :index="index" />
|
|
554
548
|
</div>
|
|
555
549
|
|
|
556
550
|
<ULoaderProgress :loading="loading" v-bind="stickyHeaderLoaderAttrs" />
|
|
@@ -626,14 +620,13 @@ const {
|
|
|
626
620
|
<thead v-bind="headerAttrs" :style="tableRowWidthStyle">
|
|
627
621
|
<tr v-if="hasSlotContent($slots['before-header'])" v-bind="headerRowAttrs">
|
|
628
622
|
<!--
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
623
|
+
@slot Use it to add something before header row.
|
|
624
|
+
@binding {number} cols-count
|
|
625
|
+
@binding {string} classes
|
|
626
|
+
-->
|
|
627
|
+
<slot name="before-header" :cols-count="colsCount" :classes="headerRowAttrs.class" />
|
|
633
628
|
</tr>
|
|
634
629
|
|
|
635
|
-
<tr v-if="hasSlotContent($slots['before-header'])" v-bind="headerRowAttrs"></tr>
|
|
636
|
-
|
|
637
630
|
<tr ref="header-row" v-bind="headerRowAttrs">
|
|
638
631
|
<th v-if="selectable" v-bind="headerCellCheckboxAttrs">
|
|
639
632
|
<UCheckbox
|
|
@@ -672,13 +665,6 @@ const {
|
|
|
672
665
|
<template v-else>
|
|
673
666
|
{{ column.label }}
|
|
674
667
|
</template>
|
|
675
|
-
|
|
676
|
-
<!--
|
|
677
|
-
@slot Use it to add something after the needed header cell.
|
|
678
|
-
@binding {object} column
|
|
679
|
-
@binding {number} index
|
|
680
|
-
-->
|
|
681
|
-
<slot :name="`header-${column.key}-after`" :column="column" :index="index" />
|
|
682
668
|
</th>
|
|
683
669
|
</tr>
|
|
684
670
|
|
|
@@ -792,15 +778,23 @@ const {
|
|
|
792
778
|
v-if="rowIndex === lastRow && hasSlotContent($slots['after-last-row'])"
|
|
793
779
|
v-bind="bodyRowAfterAttrs"
|
|
794
780
|
>
|
|
795
|
-
<!--
|
|
796
|
-
|
|
781
|
+
<!--
|
|
782
|
+
@slot Use it to add something after last row.
|
|
783
|
+
@binding {number} cols-count
|
|
784
|
+
@classes {string} classes
|
|
785
|
+
-->
|
|
786
|
+
<slot
|
|
787
|
+
name="after-last-row"
|
|
788
|
+
:cols-count="colsCount"
|
|
789
|
+
:classes="bodyCellBaseAttrs.class"
|
|
790
|
+
/>
|
|
797
791
|
</tr>
|
|
798
792
|
</template>
|
|
799
793
|
</tbody>
|
|
800
794
|
|
|
801
795
|
<tbody v-else>
|
|
802
796
|
<tr>
|
|
803
|
-
<td :colspan="colsCount">
|
|
797
|
+
<td :colspan="colsCount" v-bind="bodyEmptyStateCellAttrs">
|
|
804
798
|
<!-- @slot Use it to add custom empty state. -->
|
|
805
799
|
<slot name="empty-state">
|
|
806
800
|
<UEmpty
|