edvoyui-component-library-test-flight 0.0.229 → 0.0.230
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/dist/components/timeLine/EUITimeLine.d.ts +29 -2
- package/dist/components/timeLine/EUITimeLine.vue +207 -102
- package/dist/edvoy-ui.cjs.js +13 -13
- package/dist/edvoy-ui.css +1 -1
- package/dist/edvoy-ui.es.js +4381 -4300
- package/dist/edvoy-ui.umd.js +13 -13
- package/package.json +1 -1
|
@@ -6,10 +6,19 @@ interface ITimeLine {
|
|
|
6
6
|
date?: string;
|
|
7
7
|
dateTime?: string;
|
|
8
8
|
showmore?: any;
|
|
9
|
+
[key: string]: any;
|
|
9
10
|
}
|
|
10
11
|
declare function __VLS_template(): {
|
|
11
12
|
attrs: Partial<{}>;
|
|
12
13
|
slots: {
|
|
14
|
+
dateIcon?(_: {
|
|
15
|
+
date: Date | null;
|
|
16
|
+
label: string;
|
|
17
|
+
}): any;
|
|
18
|
+
dateHeader?(_: {
|
|
19
|
+
date: Date | null;
|
|
20
|
+
label: string;
|
|
21
|
+
}): any;
|
|
13
22
|
line?(_: {
|
|
14
23
|
type: "icon" | "image" | "view";
|
|
15
24
|
}): any;
|
|
@@ -49,7 +58,7 @@ declare const __VLS_component: import('../../../node_modules/vue').DefineCompone
|
|
|
49
58
|
of<T>(...items: T[]): T[];
|
|
50
59
|
readonly [Symbol.species]: ArrayConstructor;
|
|
51
60
|
};
|
|
52
|
-
default: never[];
|
|
61
|
+
default: () => never[];
|
|
53
62
|
};
|
|
54
63
|
type: {
|
|
55
64
|
type: PropType<"view" | "icon" | "image">;
|
|
@@ -63,6 +72,14 @@ declare const __VLS_component: import('../../../node_modules/vue').DefineCompone
|
|
|
63
72
|
type: BooleanConstructor;
|
|
64
73
|
default: boolean;
|
|
65
74
|
};
|
|
75
|
+
groupByDate: {
|
|
76
|
+
type: BooleanConstructor;
|
|
77
|
+
default: boolean;
|
|
78
|
+
};
|
|
79
|
+
dateKey: {
|
|
80
|
+
type: StringConstructor;
|
|
81
|
+
default: string;
|
|
82
|
+
};
|
|
66
83
|
}>, {}, {}, {}, {}, import('../../../node_modules/vue').ComponentOptionsMixin, import('../../../node_modules/vue').ComponentOptionsMixin, {}, string, import('../../../node_modules/vue').PublicProps, Readonly<import('../../../node_modules/vue').ExtractPropTypes<{
|
|
67
84
|
items: {
|
|
68
85
|
type: {
|
|
@@ -79,7 +96,7 @@ declare const __VLS_component: import('../../../node_modules/vue').DefineCompone
|
|
|
79
96
|
of<T>(...items: T[]): T[];
|
|
80
97
|
readonly [Symbol.species]: ArrayConstructor;
|
|
81
98
|
};
|
|
82
|
-
default: never[];
|
|
99
|
+
default: () => never[];
|
|
83
100
|
};
|
|
84
101
|
type: {
|
|
85
102
|
type: PropType<"view" | "icon" | "image">;
|
|
@@ -93,11 +110,21 @@ declare const __VLS_component: import('../../../node_modules/vue').DefineCompone
|
|
|
93
110
|
type: BooleanConstructor;
|
|
94
111
|
default: boolean;
|
|
95
112
|
};
|
|
113
|
+
groupByDate: {
|
|
114
|
+
type: BooleanConstructor;
|
|
115
|
+
default: boolean;
|
|
116
|
+
};
|
|
117
|
+
dateKey: {
|
|
118
|
+
type: StringConstructor;
|
|
119
|
+
default: string;
|
|
120
|
+
};
|
|
96
121
|
}>> & Readonly<{}>, {
|
|
97
122
|
type: "icon" | "image" | "view";
|
|
98
123
|
icon: string | Record<string, any>;
|
|
99
124
|
items: ITimeLine[];
|
|
100
125
|
showMore: boolean;
|
|
126
|
+
groupByDate: boolean;
|
|
127
|
+
dateKey: string;
|
|
101
128
|
}, {}, {}, {}, string, import('../../../node_modules/vue').ComponentProvideOptions, true, {}, HTMLDivElement>;
|
|
102
129
|
declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
|
|
103
130
|
export default _default;
|
|
@@ -1,119 +1,149 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div>
|
|
3
3
|
<ul role="list" class="p-4 space-y-6">
|
|
4
|
-
<
|
|
5
|
-
v-
|
|
6
|
-
:data="item"
|
|
7
|
-
:key="`timeline_${itemIdx}`"
|
|
8
|
-
class="relative flex gap-x-4 group"
|
|
9
|
-
:type="type"
|
|
10
|
-
:timeline-icon="icon"
|
|
11
|
-
:show-more="showMore"
|
|
12
|
-
>
|
|
13
|
-
<div
|
|
14
|
-
:class="[
|
|
15
|
-
itemIdx === items.length - 1 ? 'h-6' : '-bottom-6',
|
|
16
|
-
'absolute left-0 top-0 flex w-6 justify-center',
|
|
17
|
-
]"
|
|
18
|
-
>
|
|
19
|
-
<slot name="line" :type="type">
|
|
4
|
+
<template v-for="group in timelineGroups" :key="group.key">
|
|
5
|
+
<li v-if="groupByDate" class="relative flex items-center gap-x-4">
|
|
20
6
|
<div
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
</div>
|
|
28
|
-
<template v-if="type === 'image'">
|
|
29
|
-
<slot name="image" :data="item" :dataIndex="itemIdx">
|
|
30
|
-
<img
|
|
31
|
-
:src="item.person?.imageUrl"
|
|
32
|
-
alt=""
|
|
33
|
-
class="relative flex-initial flex-shrink-0 rounded-full size-6 bg-gray-50"
|
|
34
|
-
/>
|
|
35
|
-
</slot>
|
|
36
|
-
<slot name="details" :data="item" :dataIndex="itemIdx">
|
|
7
|
+
class="absolute top-0 left-0 flex justify-center w-6 -bottom-6"
|
|
8
|
+
aria-hidden="true"
|
|
9
|
+
>
|
|
10
|
+
<div class="w-px bg-gray-200" />
|
|
11
|
+
</div>
|
|
12
|
+
<slot name="dateIcon" :date="group.date" :label="group.label">
|
|
37
13
|
<div
|
|
38
|
-
class="flex-
|
|
14
|
+
class="relative flex items-center justify-center flex-none -m-1 rounded-full bg-purple-100 size-8"
|
|
39
15
|
>
|
|
40
|
-
<
|
|
41
|
-
<div class="text-xs leading-5 text-gray-500">
|
|
42
|
-
<span class="font-medium text-gray-900">{{
|
|
43
|
-
item.person?.name
|
|
44
|
-
}}</span>
|
|
45
|
-
</div>
|
|
46
|
-
<time
|
|
47
|
-
:datetime="item.dateTime"
|
|
48
|
-
class="flex-none text-xs leading-5 text-gray-500"
|
|
49
|
-
>
|
|
50
|
-
{{ item.date + " " + item.dateTime }}
|
|
51
|
-
</time>
|
|
52
|
-
</div>
|
|
53
|
-
<p class="text-sm leading-6 text-gray-500">
|
|
54
|
-
{{ item.comment }}
|
|
55
|
-
</p>
|
|
56
|
-
|
|
57
|
-
<details
|
|
58
|
-
v-if="showMore"
|
|
59
|
-
:open="itemIdx === 0"
|
|
60
|
-
class="h-6 p-2 mt-2 text-xs text-gray-500 transition-colors duration-100 ease-in-out select-none open:border open:border-gray-100 open:bg-gray-50 open:rounded-md group open:h-auto"
|
|
61
|
-
>
|
|
62
|
-
<summary
|
|
63
|
-
class="flex flex-row items-center justify-start text-sm leading-5 text-gray-900 list-none cursor-pointer"
|
|
64
|
-
>
|
|
65
|
-
<slot name="showMoreTitle" :data="item" :open="itemIdx === 0">
|
|
66
|
-
{{ item.showmore?.title || "More Details" }}
|
|
67
|
-
<PlusIcon
|
|
68
|
-
class="ml-auto -mr-1 transition-all duration-300 opacity-75 fill-current size-4 group-open:hidden"
|
|
69
|
-
/>
|
|
70
|
-
<MinusIcon
|
|
71
|
-
class="hidden ml-auto -mr-1 transition-all duration-300 opacity-75 fill-current size-4 group-open:inline-block"
|
|
72
|
-
/>
|
|
73
|
-
</slot>
|
|
74
|
-
</summary>
|
|
75
|
-
<slot name="showMoreContent" :data="item">
|
|
76
|
-
<div>{{ item.showmore?.content }}</div>
|
|
77
|
-
</slot>
|
|
78
|
-
</details>
|
|
16
|
+
<CalendarDaysIcon class="text-purple-500 size-4" />
|
|
79
17
|
</div>
|
|
80
18
|
</slot>
|
|
81
|
-
|
|
82
|
-
|
|
19
|
+
<slot name="dateHeader" :date="group.date" :label="group.label">
|
|
20
|
+
<h3 class="text-sm font-semibold text-gray-900">
|
|
21
|
+
{{ group.label }}
|
|
22
|
+
</h3>
|
|
23
|
+
</slot>
|
|
24
|
+
</li>
|
|
25
|
+
|
|
26
|
+
<li
|
|
27
|
+
v-for="(item, itemIdx) in group.items"
|
|
28
|
+
:key="getItemKey(group.key, item, itemIdx)"
|
|
29
|
+
:data="item"
|
|
30
|
+
class="relative flex gap-x-4 group"
|
|
31
|
+
:type="type"
|
|
32
|
+
:timeline-icon="icon"
|
|
33
|
+
:show-more="showMore"
|
|
34
|
+
>
|
|
83
35
|
<div
|
|
84
|
-
class="
|
|
36
|
+
:class="[
|
|
37
|
+
itemIdx === group.items.length - 1 ? 'h-6' : '-bottom-6',
|
|
38
|
+
'absolute left-0 top-0 flex w-6 justify-center',
|
|
39
|
+
]"
|
|
85
40
|
>
|
|
86
|
-
<
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
v-else
|
|
94
|
-
class="size-1.5 rounded-full bg-gray-100 ring-1 ring-gray-300 group-hover:bg-purple-200 group-hover:ring-purple-500"
|
|
95
|
-
/>
|
|
41
|
+
<slot name="line" :type="type">
|
|
42
|
+
<div
|
|
43
|
+
:class="[
|
|
44
|
+
type === 'icon' ? 'w-0.5 bg-green-500' : 'w-px bg-gray-200',
|
|
45
|
+
]"
|
|
46
|
+
/>
|
|
47
|
+
</slot>
|
|
96
48
|
</div>
|
|
97
|
-
<
|
|
98
|
-
<
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
49
|
+
<template v-if="type === 'image'">
|
|
50
|
+
<slot name="image" :data="item" :dataIndex="itemIdx">
|
|
51
|
+
<img
|
|
52
|
+
:src="item.person?.imageUrl"
|
|
53
|
+
alt=""
|
|
54
|
+
class="relative flex-initial flex-shrink-0 rounded-full size-6 bg-gray-50"
|
|
55
|
+
/>
|
|
56
|
+
</slot>
|
|
57
|
+
<slot name="details" :data="item" :dataIndex="itemIdx">
|
|
58
|
+
<div
|
|
59
|
+
class="flex-1 min-w-0 p-3 rounded-md ring-1 ring-inset ring-gray-200"
|
|
60
|
+
>
|
|
61
|
+
<div class="flex justify-between gap-x-4 mb-0.5">
|
|
62
|
+
<div class="text-xs leading-5 text-gray-500">
|
|
63
|
+
<span class="font-medium text-gray-900">{{
|
|
64
|
+
item.person?.name
|
|
65
|
+
}}</span>
|
|
66
|
+
</div>
|
|
67
|
+
<time
|
|
68
|
+
:datetime="item.dateTime"
|
|
69
|
+
class="flex-none text-xs leading-5 text-gray-500"
|
|
70
|
+
>
|
|
71
|
+
{{ item.date + " " + item.dateTime }}
|
|
72
|
+
</time>
|
|
73
|
+
</div>
|
|
74
|
+
<p class="text-sm leading-6 text-gray-500">
|
|
75
|
+
{{ item.comment }}
|
|
76
|
+
</p>
|
|
77
|
+
|
|
78
|
+
<details
|
|
79
|
+
v-if="showMore"
|
|
80
|
+
:open="itemIdx === 0"
|
|
81
|
+
class="h-6 p-2 mt-2 text-xs text-gray-500 transition-colors duration-100 ease-in-out select-none open:border open:border-gray-100 open:bg-gray-50 open:rounded-md group open:h-auto"
|
|
82
|
+
>
|
|
83
|
+
<summary
|
|
84
|
+
class="flex flex-row items-center justify-start text-sm leading-5 text-gray-900 list-none cursor-pointer"
|
|
85
|
+
>
|
|
86
|
+
<slot
|
|
87
|
+
name="showMoreTitle"
|
|
88
|
+
:data="item"
|
|
89
|
+
:open="itemIdx === 0"
|
|
90
|
+
>
|
|
91
|
+
{{ item.showmore?.title || "More Details" }}
|
|
92
|
+
<PlusIcon
|
|
93
|
+
class="ml-auto -mr-1 transition-all duration-300 opacity-75 fill-current size-4 group-open:hidden"
|
|
94
|
+
/>
|
|
95
|
+
<MinusIcon
|
|
96
|
+
class="hidden ml-auto -mr-1 transition-all duration-300 opacity-75 fill-current size-4 group-open:inline-block"
|
|
97
|
+
/>
|
|
98
|
+
</slot>
|
|
99
|
+
</summary>
|
|
100
|
+
<slot name="showMoreContent" :data="item">
|
|
101
|
+
<div>{{ item.showmore?.content }}</div>
|
|
102
|
+
</slot>
|
|
103
|
+
</details>
|
|
104
|
+
</div>
|
|
105
|
+
</slot>
|
|
106
|
+
</template>
|
|
107
|
+
<template v-else>
|
|
108
|
+
<div
|
|
109
|
+
class="relative flex items-center justify-center flex-none bg-white size-6"
|
|
110
|
+
>
|
|
111
|
+
<component
|
|
112
|
+
v-if="type === 'icon'"
|
|
113
|
+
:is="icon || CheckCircleIcon"
|
|
114
|
+
class="text-green-500 size-6"
|
|
115
|
+
aria-hidden="true"
|
|
116
|
+
/>
|
|
117
|
+
<div
|
|
118
|
+
v-else
|
|
119
|
+
class="size-1.5 rounded-full bg-gray-100 ring-1 ring-gray-300 group-hover:bg-purple-200 group-hover:ring-purple-500"
|
|
120
|
+
/>
|
|
121
|
+
</div>
|
|
122
|
+
<p class="flex-auto py-0.5 text-xs leading-5 text-gray-500">
|
|
123
|
+
<span class="font-medium text-gray-900">{{
|
|
124
|
+
item.person?.name
|
|
125
|
+
}}</span>
|
|
126
|
+
{{ item?.comment }}
|
|
127
|
+
</p>
|
|
128
|
+
<time
|
|
129
|
+
:datetime="item.dateTime"
|
|
130
|
+
class="flex-none py-0.5 text-xs leading-5 text-gray-500"
|
|
131
|
+
>{{ item.date + " " + item.dateTime }}</time
|
|
132
|
+
>
|
|
133
|
+
</template>
|
|
134
|
+
</li>
|
|
135
|
+
</template>
|
|
110
136
|
</ul>
|
|
111
137
|
</div>
|
|
112
138
|
</template>
|
|
113
139
|
|
|
114
140
|
<script setup lang="ts">
|
|
115
|
-
import { PropType, toRefs } from "vue";
|
|
116
|
-
import {
|
|
141
|
+
import { computed, PropType, toRefs } from "vue";
|
|
142
|
+
import {
|
|
143
|
+
CalendarDaysIcon,
|
|
144
|
+
MinusIcon,
|
|
145
|
+
PlusIcon,
|
|
146
|
+
} from "@heroicons/vue/24/outline";
|
|
117
147
|
import { CheckCircleIcon } from "@heroicons/vue/24/solid";
|
|
118
148
|
|
|
119
149
|
interface ITimeLine {
|
|
@@ -123,12 +153,20 @@ interface ITimeLine {
|
|
|
123
153
|
date?: string;
|
|
124
154
|
dateTime?: string;
|
|
125
155
|
showmore?: any;
|
|
156
|
+
[key: string]: any;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
interface ITimeLineGroup {
|
|
160
|
+
key: string;
|
|
161
|
+
label: string;
|
|
162
|
+
date: Date | null;
|
|
163
|
+
items: ITimeLine[];
|
|
126
164
|
}
|
|
127
165
|
|
|
128
166
|
const props = defineProps({
|
|
129
167
|
items: {
|
|
130
168
|
type: Array<ITimeLine>,
|
|
131
|
-
default: [],
|
|
169
|
+
default: () => [],
|
|
132
170
|
},
|
|
133
171
|
type: {
|
|
134
172
|
type: String as PropType<"view" | "icon" | "image">,
|
|
@@ -142,7 +180,74 @@ const props = defineProps({
|
|
|
142
180
|
type: Boolean,
|
|
143
181
|
default: false,
|
|
144
182
|
},
|
|
183
|
+
groupByDate: {
|
|
184
|
+
type: Boolean,
|
|
185
|
+
default: false,
|
|
186
|
+
},
|
|
187
|
+
dateKey: {
|
|
188
|
+
type: String,
|
|
189
|
+
default: "createdAt",
|
|
190
|
+
},
|
|
145
191
|
});
|
|
146
192
|
|
|
147
|
-
const { items, type, icon, showMore } = toRefs(props);
|
|
193
|
+
const { items, type, icon, showMore, groupByDate, dateKey } = toRefs(props);
|
|
194
|
+
|
|
195
|
+
const getItemKey = (groupKey: string, item: ITimeLine, itemIdx: number) => {
|
|
196
|
+
if (!groupByDate.value) return `timeline_${itemIdx}`;
|
|
197
|
+
return `timeline_${groupKey}_${item.id ?? itemIdx}`;
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
const getLocalDateKey = (date: Date) => {
|
|
201
|
+
const year = date.getFullYear();
|
|
202
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
203
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
204
|
+
return `${year}-${month}-${day}`;
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
const getDateLabel = (date: Date | null) => {
|
|
208
|
+
if (!date) return "Unknown date";
|
|
209
|
+
|
|
210
|
+
const today = new Date();
|
|
211
|
+
const yesterday = new Date(today);
|
|
212
|
+
yesterday.setDate(today.getDate() - 1);
|
|
213
|
+
|
|
214
|
+
const dateKeyValue = getLocalDateKey(date);
|
|
215
|
+
if (dateKeyValue === getLocalDateKey(today)) return "Today";
|
|
216
|
+
if (dateKeyValue === getLocalDateKey(yesterday)) return "Yesterday";
|
|
217
|
+
|
|
218
|
+
return new Intl.DateTimeFormat("en-GB", {
|
|
219
|
+
day: "numeric",
|
|
220
|
+
month: "short",
|
|
221
|
+
year: "numeric",
|
|
222
|
+
}).format(date);
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
const timelineGroups = computed<ITimeLineGroup[]>(() => {
|
|
226
|
+
if (!groupByDate.value) {
|
|
227
|
+
return [{ key: "all", label: "", date: null, items: items.value }];
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const groups = new Map<string, ITimeLineGroup>();
|
|
231
|
+
|
|
232
|
+
items.value.forEach((item) => {
|
|
233
|
+
const rawDate = item[dateKey.value];
|
|
234
|
+
const parsedDate = rawDate ? new Date(rawDate) : null;
|
|
235
|
+
const date =
|
|
236
|
+
parsedDate && !Number.isNaN(parsedDate.getTime()) ? parsedDate : null;
|
|
237
|
+
const key = date ? getLocalDateKey(date) : "unknown";
|
|
238
|
+
|
|
239
|
+
if (!groups.has(key)) {
|
|
240
|
+
groups.set(key, {
|
|
241
|
+
key,
|
|
242
|
+
label: getDateLabel(date),
|
|
243
|
+
date,
|
|
244
|
+
items: [],
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
groups.get(key)?.items.push(item);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
return Array.from(groups.values());
|
|
252
|
+
});
|
|
148
253
|
</script>
|