@peng_kai/kit 0.1.2 → 0.1.3

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/tsconfig.json CHANGED
@@ -20,9 +20,12 @@
20
20
  /* Linting */
21
21
  "strict": true,
22
22
  "noFallthroughCasesInSwitch": true,
23
+ "noImplicitAny": false,
23
24
  "noUnusedLocals": true,
24
25
  "noUnusedParameters": true,
25
26
  "noEmit": true,
27
+ "allowSyntheticDefaultImports": true,
28
+ "esModuleInterop": true,
26
29
  "isolatedModules": true,
27
30
  "skipLibCheck": true
28
31
  },
package/uno.config.ts ADDED
@@ -0,0 +1 @@
1
+ export default {};
@@ -2,15 +2,30 @@
2
2
  import { computed, ref, unref } from 'vue';
3
3
  import type { UseInfiniteQueryReturnType } from '@tanstack/vue-query';
4
4
  import { useCreateTrigger } from './useCreateTrigger';
5
+
6
+ export type { ISlotProvide };
7
+
8
+ interface ISlotProvide {
9
+ isInitialLoading: boolean
10
+ isInitialLoadingError: boolean
11
+ isEmpty: boolean
12
+ isMoreLoading: boolean
13
+ isMoreLoadingError: boolean
14
+ isNoMore: boolean
15
+ refetch: () => void
16
+ }
5
17
  </script>
6
18
 
7
19
  <script setup lang="ts" generic="T extends UseInfiniteQueryReturnType<any, any>">
8
20
  type TPage = T extends UseInfiniteQueryReturnType<infer P, any> ? NonNullable<P> : any;
9
21
  type TRecord = TPage extends { list: Array<infer I> } ? I : any;
10
22
 
11
- const props = defineProps<{
23
+ const props = withDefaults(defineProps<{
12
24
  queryier: T
13
- }>();
25
+ distance?: string
26
+ }>(), {
27
+ distance: '50px',
28
+ });
14
29
 
15
30
  const { queryier } = props;
16
31
  const pages = computed(() => queryier.data.value?.pages);
@@ -20,8 +35,9 @@ const isInitialLoadingError = computed(() => queryier.isLoadingError.value && !i
20
35
  const isMoreLoading = computed(
21
36
  () => (queryier.isFetchingNextPage.value || queryier.isFetching.value) && !isInitialLoading.value,
22
37
  );
38
+ const isEmpty = computed(() => queryier.isSuccess.value && !pages.value?.[0].list?.length);
23
39
  const isMoreLoadingError = computed(() => queryier.isRefetchError.value && !isMoreLoading.value);
24
- const noMore = computed(
40
+ const isNoMore = computed(
25
41
  () =>
26
42
  !queryier.hasNextPage?.value
27
43
  && !isInitialLoading.value
@@ -43,10 +59,6 @@ const containerCssVars = computed(() => {
43
59
  };
44
60
  });
45
61
 
46
- function refetch() {
47
- queryier.refetch();
48
- }
49
-
50
62
  function refetchLastPage() {
51
63
  queryier.refetch({
52
64
  refetchPage(lastPage: any, _index, allPages: any[]) {
@@ -65,6 +77,15 @@ function fetchNextPage() {
65
77
  queryier.fetchNextPage();
66
78
  }
67
79
 
80
+ function refetch() {
81
+ if (isNoMore.value)
82
+ refetchLastPage();
83
+ else if (isMoreLoadingError.value)
84
+ fetchNextPage();
85
+ else
86
+ queryier.refetch();
87
+ }
88
+
68
89
  function triggerFetchNextPage() {
69
90
  if (queryier.isError.value)
70
91
  return;
@@ -72,34 +93,70 @@ function triggerFetchNextPage() {
72
93
  fetchNextPage();
73
94
  }
74
95
 
75
- useCreateTrigger($container, triggerFetchNextPage);
96
+ useCreateTrigger($container, triggerFetchNextPage, props.distance);
97
+
98
+ const slotProvide = computed<ISlotProvide>(() => ({
99
+ isInitialLoading: isInitialLoading.value,
100
+ isInitialLoadingError: isInitialLoadingError.value,
101
+ isMoreLoading: isMoreLoading.value,
102
+ isMoreLoadingError: isMoreLoadingError.value,
103
+ isNoMore: isNoMore.value,
104
+ isEmpty: isEmpty.value,
105
+ refetch,
106
+ }));
76
107
  </script>
77
108
 
78
109
  <template>
79
110
  <div ref="$container" class="infinite-query-wrapper" :style="containerCssVars">
80
- <div v-if="isInitialLoading" class="initial-loading">
81
- <i class="i-svg-spinners:180-ring-with-bg loading-icon" />
82
- </div>
83
- <div v-if="isInitialLoadingError" class="initial-loading-error" @click="refetch()">
84
- <span>加载失败,点击重试</span>
85
- </div>
86
-
87
- <div v-for="(page, i) of pages" :key="i">
88
- <template v-for="record of page.list">
89
- <slot :record="record as TRecord" />
111
+ <div class="list">
112
+ <template v-for="(page) of pages">
113
+ <template v-for="record of page.list">
114
+ <!-- eslint-disable-next-line vue/no-extra-parens -->
115
+ <slot name="default" :record="(record as TRecord)" />
116
+ </template>
90
117
  </template>
91
118
  </div>
92
119
 
93
- <div v-if="isMoreLoading" class="more-loading">
94
- <i class="i-svg-spinners:180-ring-with-bg loading-icon" />
95
- <span class="ml-1 text">加载中...</span>
96
- </div>
97
- <div v-if="isMoreLoadingError" class="more-loading-error" @click="fetchNextPage()">
98
- <span class="text">加载失败,点击重试</span>
99
- </div>
100
- <div v-if="noMore" class="no-more" @click="refetchLastPage()">
101
- <span class="text">暂无更多</span>
102
- </div>
120
+ <slot
121
+ name="status" v-bind="slotProvide"
122
+ >
123
+ <slot name="initialLoading">
124
+ <div v-if="isInitialLoading" class="initial-loading">
125
+ <i class="i-svg-spinners:180-ring-with-bg loading-icon" />
126
+ </div>
127
+ </slot>
128
+
129
+ <slot name="initialLoadingError">
130
+ <div v-if="isInitialLoadingError" class="initial-loading-error" @click="refetch()">
131
+ <span>加载失败,点击重试</span>
132
+ </div>
133
+ </slot>
134
+
135
+ <slot name="empty">
136
+ <div v-if="isEmpty" class="empty">
137
+ <span>暂无数据</span>
138
+ </div>
139
+ </slot>
140
+
141
+ <slot name="oreLoading">
142
+ <div v-if="isMoreLoading" class="more-loading">
143
+ <i class="i-svg-spinners:180-ring-with-bg loading-icon" />
144
+ <span class="ml-1 text">加载中...</span>
145
+ </div>
146
+ </slot>
147
+
148
+ <slot name="moreLoadingError">
149
+ <div v-if="isMoreLoadingError" class="more-loading-error" @click="refetch()">
150
+ <span class="text">加载失败,点击重试</span>
151
+ </div>
152
+ </slot>
153
+
154
+ <slot name="noMore">
155
+ <div v-if="isNoMore" class="no-more" @click="refetch()">
156
+ <span class="text">暂无更多</span>
157
+ </div>
158
+ </slot>
159
+ </slot>
103
160
  </div>
104
161
  </template>
105
162
 
@@ -117,6 +174,7 @@ useCreateTrigger($container, triggerFetchNextPage);
117
174
 
118
175
  .initial-loading,
119
176
  .initial-loading-error,
177
+ .empty,
120
178
  .more-loading,
121
179
  .more-loading-error,
122
180
  .no-more {
@@ -1,15 +1,15 @@
1
- import { watch } from 'vue';
1
+ import { onUnmounted, watch } from 'vue';
2
2
  import type { Ref } from 'vue';
3
3
  import { useIntersectionObserver, useIntervalFn } from '@vueuse/core';
4
4
 
5
- export function useCreateTrigger(containerEle: Ref<HTMLElement | undefined>, callback: Function) {
5
+ export function useCreateTrigger(containerEle: Ref<HTMLElement | undefined>, callback: Function, distance: string) {
6
6
  const triggerEl = document.createElement('div');
7
7
 
8
8
  Object.assign(triggerEl.style, {
9
9
  position: 'relative',
10
10
  zIndex: '5',
11
- marginTop: '-150px',
12
- marginBottom: '150px',
11
+ marginTop: `-${distance}`,
12
+ marginBottom: distance,
13
13
  width: '5px',
14
14
  height: '5px',
15
15
  // background: 'red',
@@ -32,4 +32,8 @@ export function useCreateTrigger(containerEle: Ref<HTMLElement | undefined>, cal
32
32
  if (ele)
33
33
  ele.append(triggerEl);
34
34
  });
35
+
36
+ onUnmounted(() => {
37
+ triggerEl.remove();
38
+ });
35
39
  }