vueless 0.0.725 → 0.0.726
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.loader-progress/ULoaderProgress.vue +46 -63
- package/ui.loader-progress/config.ts +1 -1
- package/ui.loader-progress/constants.ts +0 -1
- package/ui.loader-progress/storybook/docs.mdx +3 -15
- package/ui.loader-progress/storybook/stories.ts +1 -1
- package/ui.loader-progress/types.ts +1 -1
- package/ui.loader-progress/useLoaderProgress.ts +19 -30
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { computed,
|
|
2
|
+
import { computed, watch, ref } from "vue";
|
|
3
3
|
|
|
4
4
|
import useUI from "../composables/useUI.ts";
|
|
5
5
|
import { getDefaults } from "../utils/ui.ts";
|
|
@@ -7,7 +7,7 @@ import { getDefaults } from "../utils/ui.ts";
|
|
|
7
7
|
import { clamp, queue, getRequestWithoutQuery } from "./utilLoaderProgress.ts";
|
|
8
8
|
import { useLoaderProgress } from "./useLoaderProgress.ts";
|
|
9
9
|
|
|
10
|
-
import { COMPONENT_NAME, MAXIMUM, SPEED
|
|
10
|
+
import { COMPONENT_NAME, MAXIMUM, SPEED } from "./constants.ts";
|
|
11
11
|
import defaultConfig from "./config.ts";
|
|
12
12
|
|
|
13
13
|
import type { Props, Config } from "./types.ts";
|
|
@@ -25,16 +25,9 @@ const progress = ref(0);
|
|
|
25
25
|
const opacity = ref(1);
|
|
26
26
|
const status = ref<number | null>(null);
|
|
27
27
|
|
|
28
|
-
const {
|
|
29
|
-
requestQueue,
|
|
30
|
-
removeRequestUrl,
|
|
31
|
-
isLoading,
|
|
32
|
-
loaderProgressOff,
|
|
33
|
-
loaderProgressOn,
|
|
34
|
-
addRequestUrl,
|
|
35
|
-
} = useLoaderProgress();
|
|
28
|
+
const { requestQueue } = useLoaderProgress();
|
|
36
29
|
|
|
37
|
-
const
|
|
30
|
+
const isLoading = computed(() => {
|
|
38
31
|
return typeof status.value === "number";
|
|
39
32
|
});
|
|
40
33
|
|
|
@@ -45,68 +38,37 @@ const barStyle = computed(() => {
|
|
|
45
38
|
};
|
|
46
39
|
});
|
|
47
40
|
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
: [getRequestWithoutQuery(props.resources)];
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
const isPropsLoading = computed(
|
|
55
|
-
() => requestQueue.value.includes(INFINITY_LOADING) && props.loading,
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
watch(() => requestQueue.value.length, onChangeRequestsQueue);
|
|
59
|
-
|
|
60
|
-
onMounted(() => {
|
|
61
|
-
window.addEventListener("loaderProgressOn", setLoaderOnHandler as EventListener);
|
|
62
|
-
window.addEventListener("loaderProgressOff", setLoaderOffHandler as EventListener);
|
|
63
|
-
|
|
64
|
-
if (props.resources) {
|
|
65
|
-
onChangeRequestsQueue();
|
|
41
|
+
const resourceSubscriptions = computed(() => {
|
|
42
|
+
if (Array.isArray(props.resources)) {
|
|
43
|
+
return props.resources.map(getRequestWithoutQuery);
|
|
66
44
|
}
|
|
67
|
-
});
|
|
68
45
|
|
|
69
|
-
|
|
70
|
-
removeRequestUrl(resourceNamesArray.value);
|
|
46
|
+
return [getRequestWithoutQuery(props.resources)];
|
|
71
47
|
});
|
|
72
48
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
49
|
+
const isActiveRequests = computed(() => {
|
|
50
|
+
const isAnyRequestActive = props.resources === "any" && requestQueue.value.length;
|
|
51
|
+
const isSubscribedRequestsActive = resourceSubscriptions.value.some((resource) =>
|
|
52
|
+
requestQueue.value.includes(resource),
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
return isAnyRequestActive || isSubscribedRequestsActive;
|
|
76
56
|
});
|
|
77
57
|
|
|
58
|
+
watch(() => requestQueue, onChangeRequestsQueue, { immediate: true, deep: true });
|
|
59
|
+
|
|
78
60
|
watch(
|
|
79
61
|
() => props.loading,
|
|
80
|
-
() =>
|
|
81
|
-
if (props.loading) {
|
|
82
|
-
addRequestUrl(INFINITY_LOADING);
|
|
83
|
-
isLoading.value = true;
|
|
84
|
-
} else {
|
|
85
|
-
removeRequestUrl(INFINITY_LOADING);
|
|
86
|
-
}
|
|
87
|
-
},
|
|
88
|
-
{ immediate: true },
|
|
62
|
+
() => (props.loading ? start() : stop()),
|
|
89
63
|
);
|
|
90
64
|
|
|
91
|
-
function setLoaderOnHandler(event: CustomEvent<{ resource: string }>) {
|
|
92
|
-
loaderProgressOn(event.detail.resource);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function setLoaderOffHandler(event: CustomEvent<{ resource: string }>) {
|
|
96
|
-
loaderProgressOff(event.detail.resource);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
65
|
function onChangeRequestsQueue() {
|
|
100
|
-
|
|
101
|
-
isPropsLoading.value ||
|
|
102
|
-
resourceNamesArray.value.some((resource: string) => {
|
|
103
|
-
return requestQueue.value.includes(resource);
|
|
104
|
-
});
|
|
66
|
+
if (props.loading !== undefined) return;
|
|
105
67
|
|
|
106
|
-
if (isActiveRequests
|
|
68
|
+
if (isActiveRequests.value && !isLoading.value) {
|
|
107
69
|
start();
|
|
108
|
-
} else if (!isActiveRequests &&
|
|
109
|
-
|
|
70
|
+
} else if (!isActiveRequests.value && isLoading.value && show.value) {
|
|
71
|
+
stop();
|
|
110
72
|
}
|
|
111
73
|
}
|
|
112
74
|
|
|
@@ -125,8 +87,9 @@ function afterEnter() {
|
|
|
125
87
|
}
|
|
126
88
|
|
|
127
89
|
function work() {
|
|
90
|
+
// TODO: Use requestAnimationFrame for animations instead of setTimeout for better performance and smoothness.
|
|
128
91
|
setTimeout(() => {
|
|
129
|
-
if (!
|
|
92
|
+
if (!isLoading.value) {
|
|
130
93
|
return;
|
|
131
94
|
}
|
|
132
95
|
|
|
@@ -152,7 +115,7 @@ function start() {
|
|
|
152
115
|
function set(amount: number) {
|
|
153
116
|
let currentProgress;
|
|
154
117
|
|
|
155
|
-
if (
|
|
118
|
+
if (isLoading.value) {
|
|
156
119
|
currentProgress = amount < progress.value ? clamp(amount, 0, 100) : clamp(amount, 0.8, 100);
|
|
157
120
|
} else {
|
|
158
121
|
currentProgress = 0;
|
|
@@ -200,10 +163,30 @@ function increase(amount?: number) {
|
|
|
200
163
|
set(clamp(currentProgress + (amount || 0), 0, MAXIMUM));
|
|
201
164
|
}
|
|
202
165
|
|
|
203
|
-
function
|
|
166
|
+
function stop() {
|
|
204
167
|
set(100);
|
|
205
168
|
}
|
|
206
169
|
|
|
170
|
+
defineExpose({
|
|
171
|
+
/**
|
|
172
|
+
* Start loading animation.
|
|
173
|
+
* @property {Function}
|
|
174
|
+
*/
|
|
175
|
+
start,
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Stop loading animation.
|
|
179
|
+
* @property {Function}
|
|
180
|
+
*/
|
|
181
|
+
stop,
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Loading state.
|
|
185
|
+
* @property {Boolean}
|
|
186
|
+
*/
|
|
187
|
+
isLoading,
|
|
188
|
+
});
|
|
189
|
+
|
|
207
190
|
/**
|
|
208
191
|
* Get element / nested component attributes for each config token ✨
|
|
209
192
|
* Applies: `class`, `config`, redefined default `props` and dev `vl-...` attributes.
|
|
@@ -21,33 +21,21 @@ The loader uses queue of resources and will be shown until at least one item is
|
|
|
21
21
|
import { useLoaderProgress } from "vueless";
|
|
22
22
|
|
|
23
23
|
const {
|
|
24
|
-
isLoading,
|
|
25
24
|
loaderProgressOn,
|
|
26
25
|
loaderProgressOff,
|
|
27
26
|
requestQueue,
|
|
28
|
-
addRequestUrl
|
|
29
|
-
removeRequestUrl
|
|
30
27
|
} = useLoaderProgress();
|
|
31
28
|
|
|
32
|
-
// get loader state
|
|
33
|
-
console.log(isLoading.value);
|
|
34
|
-
|
|
35
29
|
// show loader (add resource into queue)
|
|
36
30
|
loaderProgressOn("/transactions");
|
|
31
|
+
loaderProgressOff(["/transactions", "/products"]);
|
|
37
32
|
|
|
38
33
|
// hide loader (remove resource from queue)
|
|
39
34
|
loaderProgressOff("/transactions");
|
|
35
|
+
loaderProgressOff(["/transactions", "/products"]);
|
|
40
36
|
|
|
41
|
-
// get current resource
|
|
37
|
+
// get current global resource queue
|
|
42
38
|
console.log(requestQueue.value);
|
|
43
|
-
|
|
44
|
-
// add resource into loader queue
|
|
45
|
-
addRequestUrl("/transactions");
|
|
46
|
-
addRequestUrl(["/transactions", "/products"]);
|
|
47
|
-
|
|
48
|
-
// remove resource from loader queue
|
|
49
|
-
removeRequestUrl("/transactions");
|
|
50
|
-
removeRequestUrl(["/transactions", "/products"]);
|
|
51
39
|
`} language="jsx" dark />
|
|
52
40
|
|
|
53
41
|
## Using loader outside Vue components
|
|
@@ -97,7 +97,7 @@ const EnumVariantTemplate: StoryFn<ULoaderProgressArgs> = (
|
|
|
97
97
|
});
|
|
98
98
|
|
|
99
99
|
export const Default = DefaultTemplate.bind({});
|
|
100
|
-
Default.args = {
|
|
100
|
+
Default.args = {};
|
|
101
101
|
|
|
102
102
|
export const Color = EnumVariantTemplate.bind({});
|
|
103
103
|
Color.args = { enum: "color" };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { inject, readonly, ref } from "vue";
|
|
1
|
+
import { inject, onBeforeUnmount, readonly, ref } from "vue";
|
|
2
2
|
|
|
3
3
|
import type { Ref } from "vue";
|
|
4
4
|
|
|
@@ -7,38 +7,14 @@ import { getRequestWithoutQuery } from "./utilLoaderProgress.ts";
|
|
|
7
7
|
export const LoaderProgressSymbol = Symbol.for("vueless:loader-progress");
|
|
8
8
|
|
|
9
9
|
type LoaderProgress = {
|
|
10
|
-
isLoading: Ref<boolean>;
|
|
11
10
|
requestQueue: Readonly<Ref<readonly string[]>>;
|
|
12
11
|
loaderProgressOn: (url: string | string[]) => void;
|
|
13
12
|
loaderProgressOff: (url: string | string[]) => void;
|
|
14
|
-
addRequestUrl: (url: string | string[]) => void;
|
|
15
|
-
removeRequestUrl: (url: string | string[]) => void;
|
|
16
13
|
};
|
|
17
14
|
|
|
18
|
-
const isLoading = ref(false);
|
|
19
15
|
const requestQueue = ref<string[]>([]);
|
|
20
|
-
const requestTimeout = ref<number | undefined>(undefined);
|
|
21
16
|
|
|
22
17
|
function loaderProgressOn(url: string | string[]): void {
|
|
23
|
-
addRequestUrl(url);
|
|
24
|
-
isLoading.value = true;
|
|
25
|
-
|
|
26
|
-
if (requestTimeout.value !== undefined) {
|
|
27
|
-
clearTimeout(requestTimeout.value);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function loaderProgressOff(url: string | string[]): void {
|
|
32
|
-
removeRequestUrl(url);
|
|
33
|
-
|
|
34
|
-
requestTimeout.value = window.setTimeout(() => {
|
|
35
|
-
if (!requestQueue.value.length) {
|
|
36
|
-
isLoading.value = false;
|
|
37
|
-
}
|
|
38
|
-
}, 50);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function addRequestUrl(url: string | string[]): void {
|
|
42
18
|
if (Array.isArray(url)) {
|
|
43
19
|
requestQueue.value.push(...url.map(getRequestWithoutQuery));
|
|
44
20
|
} else {
|
|
@@ -46,28 +22,41 @@ function addRequestUrl(url: string | string[]): void {
|
|
|
46
22
|
}
|
|
47
23
|
}
|
|
48
24
|
|
|
49
|
-
function
|
|
25
|
+
function loaderProgressOff(url: string | string[]): void {
|
|
50
26
|
if (Array.isArray(url)) {
|
|
51
|
-
url.map(getRequestWithoutQuery).forEach(
|
|
27
|
+
url.map(getRequestWithoutQuery).forEach(loaderProgressOff);
|
|
52
28
|
} else {
|
|
53
29
|
requestQueue.value = requestQueue.value.filter((item) => item !== getRequestWithoutQuery(url));
|
|
54
30
|
}
|
|
55
31
|
}
|
|
56
32
|
|
|
33
|
+
function setLoaderOnHandler(event: CustomEvent<{ resource: string }>) {
|
|
34
|
+
loaderProgressOn(event.detail.resource);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function setLoaderOffHandler(event: CustomEvent<{ resource: string }>) {
|
|
38
|
+
loaderProgressOff(event.detail.resource);
|
|
39
|
+
}
|
|
40
|
+
|
|
57
41
|
export function createLoaderProgress(): LoaderProgress {
|
|
58
42
|
return {
|
|
59
|
-
isLoading,
|
|
60
43
|
requestQueue: readonly(requestQueue),
|
|
61
44
|
loaderProgressOn,
|
|
62
45
|
loaderProgressOff,
|
|
63
|
-
addRequestUrl,
|
|
64
|
-
removeRequestUrl,
|
|
65
46
|
};
|
|
66
47
|
}
|
|
67
48
|
|
|
68
49
|
export function useLoaderProgress(): LoaderProgress {
|
|
69
50
|
const loaderProgress = inject<LoaderProgress>(LoaderProgressSymbol);
|
|
70
51
|
|
|
52
|
+
window.addEventListener("loaderProgressOn", setLoaderOnHandler as EventListener);
|
|
53
|
+
window.addEventListener("loaderProgressOff", setLoaderOffHandler as EventListener);
|
|
54
|
+
|
|
55
|
+
onBeforeUnmount(() => {
|
|
56
|
+
window.removeEventListener("loaderProgressOn", setLoaderOnHandler as EventListener);
|
|
57
|
+
window.removeEventListener("loaderProgressOff", setLoaderOffHandler as EventListener);
|
|
58
|
+
});
|
|
59
|
+
|
|
71
60
|
if (!loaderProgress) {
|
|
72
61
|
throw new Error(
|
|
73
62
|
"LoaderProgress not provided. Ensure you are using `provide` with `LoaderProgressSymbol`.",
|