plain-design 1.0.0-beta.30 → 1.0.0-beta.32

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.
Files changed (61) hide show
  1. package/dist/plain-design.commonjs.min.js +3 -3
  2. package/dist/plain-design.min.css +11 -6
  3. package/dist/plain-design.min.js +3 -3
  4. package/dist/report.html +2 -2
  5. package/package.json +3 -3
  6. package/src/packages/components/$previewer/ImagePreviewerFixedContainer.tsx +107 -0
  7. package/src/packages/components/$previewer/image-previewer-fixed-container.scss +18 -0
  8. package/src/packages/components/$previewer/index.tsx +52 -0
  9. package/src/packages/components/Application/service/useApplicationService.tsx +2 -0
  10. package/src/packages/components/Carousel/carousel.scss +391 -0
  11. package/src/packages/components/Carousel/index.tsx +569 -22
  12. package/src/packages/components/CarouselItem/index.tsx +77 -0
  13. package/src/packages/components/ImagePreviewer/ImagePreviewer.tsx +572 -0
  14. package/src/packages/components/ImagePreviewer/ImagePreviewerButtonBar.tsx +140 -0
  15. package/src/packages/components/ImagePreviewer/ImagePreviewerCarouselImage.tsx +54 -0
  16. package/src/packages/components/ImagePreviewer/ImagePreviewerGallery.tsx +202 -0
  17. package/src/packages/components/ImagePreviewer/PreviewerLoading.tsx +26 -0
  18. package/src/packages/components/ImagePreviewer/image-previewer.scss +244 -0
  19. package/src/packages/components/ImagePreviewer/image-previewer.utils.tsx +135 -0
  20. package/src/packages/components/ImagePreviewer/index.tsx +5 -0
  21. package/src/packages/components/ImagePreviewer/previewer-loading.scss +52 -0
  22. package/src/packages/components/Input/useMultipleInput.tsx +2 -79
  23. package/src/packages/components/InputNumber/NumberResize.tsx +14 -1
  24. package/src/packages/components/InputNumber/input-number.utils.tsx +7 -5
  25. package/src/packages/components/InputNumber/useInputNumber.public.tsx +25 -6
  26. package/src/packages/components/Scroll/index.tsx +6 -6
  27. package/src/packages/components/SortList/index.tsx +191 -0
  28. package/src/packages/components/SortList/sort-list.scss +11 -0
  29. package/src/packages/components/StackCard/index.tsx +260 -0
  30. package/src/packages/components/StackCard/stack-card.scss +28 -0
  31. package/src/packages/components/StackCardItem/index.tsx +23 -0
  32. package/src/packages/components/Table/standard/PlcOperation/PlcOperation.tsx +1 -1
  33. package/src/packages/components/Table/standard/PlcTree/RenderPlcTreeNode.tsx +2 -1
  34. package/src/packages/components/Table/table/body/row.tsx +1 -1
  35. package/src/packages/components/Table/table/use/useTableDraggier.row.tsx +1 -1
  36. package/src/packages/components/Table/table/utils/createTableHooks.ts +1 -1
  37. package/src/packages/components/Tree/RenderTreeNode.tsx +2 -1
  38. package/src/packages/components/Tree/index.tsx +2 -1
  39. package/src/packages/components/VirtualList/index.tsx +12 -3
  40. package/src/packages/components/VirtualList/useVirtualList.tsx +129 -86
  41. package/src/packages/components/VirtualList/virtual-list.scss +31 -17
  42. package/src/packages/components/VirtualTable/index.tsx +1 -1
  43. package/src/packages/entry.tsx +5 -1
  44. package/src/packages/uses/useDragHorizontalScroll.ts +82 -0
  45. package/src/packages/utils/ComponentUtils.ts +10 -0
  46. package/src/packages/utils/buildCycleIndexList.ts +31 -0
  47. package/src/packages/utils/getDeviceInfo.ts +44 -44
  48. package/src/packages/utils/getRectAutoFormat.ts +9 -0
  49. package/src/packages/utils/notNull.ts +9 -0
  50. package/src/pages/index/app.scss +1 -1
  51. package/src/pages/index/components/normal/DemoCarousel.tsx +178 -73
  52. package/src/pages/index/components/normal/DemoKeepAlive.tsx +25 -25
  53. package/src/pages/index/components/normal/DemoNumber.tsx +4 -1
  54. package/src/pages/index/components/normal/DemoSortList.tsx +70 -0
  55. package/src/pages/index/components/normal/DemoStackCard.tsx +356 -0
  56. package/src/pages/index/components/normal/DemoVirtualList.tsx +89 -3
  57. package/src/pages/index/components/service/DemoImagePreviewer.tsx +185 -0
  58. package/src/pages/index/home/AppHome.tsx +18 -3
  59. package/src/pages/index/home/menus.tsx +3 -1
  60. package/src/packages/components/CarouselGroup/carousel.scss +0 -143
  61. package/src/packages/components/CarouselGroup/index.tsx +0 -274
@@ -4,17 +4,25 @@ import './virtual-list.scss';
4
4
  import Scroll from "../Scroll";
5
5
  import {unit} from "plain-utils/string/unit";
6
6
  import {createEnum} from "plain-utils/utils/createEnum";
7
+ import {PlainObject} from "plain-utils/utils/event";
7
8
 
8
9
  interface DataNode {
9
- top: number;
10
- bottom: number;
11
- height: number;
10
+ start: number;
11
+ end: number;
12
+ size: number;
12
13
  item: any;
13
14
  id: string;
14
15
  index: number,
15
16
  }
16
17
 
17
- const ScrollDirection = createEnum(['up', 'down', 'none'] as const);
18
+ /**
19
+ * 滚动的方向
20
+ * 纵向:start表示往上滚动,end表示往下滚动
21
+ * 横向:start表示往左滚动,end表示往右滚动
22
+ * @author 韦胜健
23
+ * @date 2024/1/10 14:37
24
+ */
25
+ const ScrollDirection = createEnum(['start', 'end', 'none'] as const);
18
26
 
19
27
  const nextRowId = createCounter('__v__');
20
28
 
@@ -30,7 +38,12 @@ export function useVirtualList(
30
38
  size: number,
31
39
  disabled?: boolean,
32
40
  dynamicSize?: boolean,
41
+ /*纵向虚拟滚动,需要横向滚动的时候必须指定宽度*/
33
42
  width?: string | number,
43
+ /*横向虚拟滚动,需要纵向滚动的时候必须指定高度*/
44
+ height?: string | number,
45
+ /*启用横向虚拟滚动*/
46
+ horizontal?: boolean,
34
47
  },
35
48
  refs: {
36
49
  scroll?: typeof Scroll.use.class | null,
@@ -38,7 +51,7 @@ export function useVirtualList(
38
51
  },
39
52
  emit: {
40
53
  onScroll: (e: Event) => void,
41
- onPageIndexChange: (data: { pageIndex: number, start: number }) => void,
54
+ onPageIndexChange: (data: { pageIndex: number, startIndex: number, endIndex: number }) => void,
42
55
  },
43
56
  transform?: boolean,
44
57
  }
@@ -46,38 +59,38 @@ export function useVirtualList(
46
59
 
47
60
  /*非响应式属性*/
48
61
  const freezeState = {
49
- scrollTop: 0, // 实时的scrollTop值
50
- current: { // 当前的页面信息
62
+ scrollValue: 0, // 实时的scrollTop值
63
+ current: { // 当前的页面信息
51
64
  pageIndex: 0,
52
- start: 0,
53
- end: 0,
65
+ startIndex: 0,
66
+ endIndex: 0,
54
67
  },
55
68
  };
56
69
  /*响应式属性*/
57
70
  const state = reactive({
58
- scrollTop: 0, // 当前滚动scrollTop(非实时的)
71
+ scrollValue: 0, // 当前滚动scrollTop(非实时的)
59
72
  pageSize: 0, // 页大小
60
73
  scrollDirection: ScrollDirection.none as typeof ScrollDirection.TYPE,
61
- id2height: {} as Record<string, number | undefined>,
62
- avgHeight: props.size
74
+ id2size: {} as Record<string, number | undefined>,
75
+ avgSize: props.size
63
76
  });
64
77
 
65
- const idMap = new WeakMap<object, string>();
66
- let prevBottom = 0;
78
+ const idMap = new WeakMap<PlainObject, string>();
79
+ let prevEnd = 0;
67
80
 
68
81
  const nodes = computed(() => {
69
- prevBottom = 0;
82
+ prevEnd = 0;
70
83
  return props.data.map((item, index): DataNode => {
71
84
  let id = idMap.get(item);
72
85
  if (!id) {
73
86
  id = nextRowId();
74
87
  idMap.set(item, id);
75
88
  }
76
- const height: number = state.id2height[id] || state.avgHeight;
77
- let top = prevBottom;
78
- let bottom = top + height;
79
- prevBottom = bottom;
80
- return { id: id!, item, height, top, bottom, index };
89
+ const size: number = state.id2size[id] || state.avgSize;
90
+ let start = prevEnd;
91
+ let end = start + size;
92
+ prevEnd = end;
93
+ return { id: id!, item, size, start, end, index };
81
94
  });
82
95
  });
83
96
 
@@ -86,23 +99,23 @@ export function useVirtualList(
86
99
  * @author 韦胜健
87
100
  * @date 2020/11/15 9:28
88
101
  */
89
- const offsetData = computed((): { list: { item: any, id: string, index: number }[], startPageIndex: number, start: number } => {
90
- const { pageSize, scrollTop } = state;
102
+ const offsetData = computed((): { list: { item: any, id: string, index: number }[], startPageIndex: number, startIndex: number } => {
103
+ const { pageSize, scrollValue } = state;
91
104
  if (!pageSize) {
92
- return { list: [], startPageIndex: 0, start: 0 };
105
+ return { list: [], startPageIndex: 0, startIndex: 0 };
93
106
  }
94
107
  if (props.disabled) {
95
108
  return {
96
109
  list: nodes.value,
97
- start: 0,
110
+ startIndex: 0,
98
111
  startPageIndex: 0,
99
112
  };
100
113
  }
101
- const { start, end, pageIndex } = utils.getPageIndex(scrollTop, pageSize);
114
+ const { startIndex, endIndex, pageIndex } = utils.getPageIndex(scrollValue, pageSize);
102
115
  return {
103
- list: nodes.value.slice(start, end),
116
+ list: nodes.value.slice(startIndex, endIndex),
104
117
  startPageIndex: pageIndex,
105
- start,
118
+ startIndex,
106
119
  };
107
120
  });
108
121
 
@@ -115,7 +128,10 @@ export function useVirtualList(
115
128
  */
116
129
  const classes = useClasses(() => [
117
130
  getComponentCls('virtual-list'),
118
- { 'virtual-list-disabled': props.disabled, }
131
+ {
132
+ 'virtual-list-disabled': props.disabled,
133
+ 'virtual-list-horizontal': props.horizontal,
134
+ },
119
135
  ]);
120
136
 
121
137
  /**
@@ -130,14 +146,28 @@ export function useVirtualList(
130
146
  if (props.disabled) {
131
147
  return;
132
148
  }
133
- if (!!props.width) {
134
- style.width = unit(props.width);
135
- style.minWidth = '100%';
136
- }
137
- if (!props.dynamicSize) {
138
- style.height = `${(props.data || []).length * props.size}px`;
149
+ if (!props.horizontal) {
150
+ /*纵向*/
151
+ if (!!props.width) {
152
+ style.width = unit(props.width);
153
+ style.minWidth = '100%';
154
+ }
155
+ if (!props.dynamicSize) {
156
+ style.height = `${(props.data || []).length * props.size}px`;
157
+ } else {
158
+ style.height = `${nodes.value[nodes.value.length - 1].end}px`;
159
+ }
139
160
  } else {
140
- style.height = `${nodes.value[nodes.value.length - 1].bottom}px`;
161
+ /*横向*/
162
+ if (!!props.height) {
163
+ style.height = unit(props.height);
164
+ style.minHeight = '100%';
165
+ }
166
+ if (!props.dynamicSize) {
167
+ style.width = `${(props.data || []).length * props.size}px`;
168
+ } else {
169
+ style.width = `${nodes.value[nodes.value.length - 1].end}px`;
170
+ }
141
171
  }
142
172
  });
143
173
 
@@ -155,21 +185,33 @@ export function useVirtualList(
155
185
  return;
156
186
  }
157
187
 
158
- const { start } = offsetData.value;
188
+ const { startIndex } = offsetData.value;
159
189
 
160
- let top;
190
+ let start;
161
191
  if (!props.dynamicSize) {
162
- top = start * props.size;
192
+ start = startIndex * props.size;
163
193
  } else {
164
- top = nodes.value[start].top;
194
+ start = nodes.value[startIndex].start;
165
195
  }
166
196
 
167
- if (transform !== false) {
168
- /*transform定位*/
169
- style.transform = `translateY(${top}px)`;
197
+ if (!props.horizontal) {
198
+ /*纵向定位*/
199
+ if (transform !== false) {
200
+ /*transform定位*/
201
+ style.transform = `translateY(${start}px)`;
202
+ } else {
203
+ /*top定位*/
204
+ style.top = `${start}px`;
205
+ }
170
206
  } else {
171
- /*top定位*/
172
- style.top = `${top}px`;
207
+ /*横向定位*/
208
+ if (transform !== false) {
209
+ /*transform定位*/
210
+ style.transform = `translateX(${start}px)`;
211
+ } else {
212
+ /*top定位*/
213
+ style.left = `${start}px`;
214
+ }
173
215
  }
174
216
  });
175
217
 
@@ -181,10 +223,10 @@ export function useVirtualList(
181
223
  * @author 韦胜健
182
224
  * @date 2020/11/15 9:29
183
225
  */
184
- getIndex: (top: number) => {
226
+ getIndex: (scrollValue: number) => {
185
227
  if (!props.dynamicSize) {
186
228
  // console.log('not dynamic》》》getIndex', top / props.size)
187
- return Math.floor(top / props.size);
229
+ return Math.floor(scrollValue / props.size);
188
230
  } else {
189
231
  const _nodes = nodes.value;
190
232
  let start = 0;
@@ -192,12 +234,12 @@ export function useVirtualList(
192
234
  let temp = 0;
193
235
  while (start <= end) {
194
236
  let middle = Math.floor((start + end) / 2);
195
- let middleBottom = _nodes[middle].bottom;
196
- if (middleBottom === top) {
237
+ let middleBottom = _nodes[middle].end;
238
+ if (middleBottom === scrollValue) {
197
239
  return middle + 1;
198
- } else if (middleBottom < top) {
240
+ } else if (middleBottom < scrollValue) {
199
241
  start = middle + 1;
200
- } else if (middleBottom > top) {
242
+ } else if (middleBottom > scrollValue) {
201
243
  if (!temp || temp > middle) {
202
244
  temp = middle;
203
245
  }
@@ -213,29 +255,30 @@ export function useVirtualList(
213
255
  * @author 韦胜健
214
256
  * @date 2020/12/14 22:44
215
257
  */
216
- getPageIndex: (scrollTop: number, pageSize: number) => {
217
- if (scrollTop < 0) {
218
- scrollTop = 0;
258
+ getPageIndex: (scrollValue: number, pageSize: number) => {
259
+ if (scrollValue < 0) {
260
+ scrollValue = 0;
219
261
  }
220
262
  const data = props.data || [];
221
263
  /*当前scrollTop对应的数据中数据的索引*/
222
- let scrollIndex = utils.getIndex(scrollTop);
264
+ let scrollIndex = utils.getIndex(scrollValue);
223
265
  let pageIndex = Math.floor(scrollIndex / pageSize);
224
- let start = (() => {
266
+ let startIndex = (() => {
225
267
  if (state.scrollDirection === 'none') {
226
268
  return scrollIndex - Math.floor(pageSize * 0.5);
227
- } else if (state.scrollDirection === 'up') {
228
- return scrollIndex - pageSize;
269
+ } else if (state.scrollDirection === ScrollDirection.start) {
270
+ /*这里多减去2,避免出现空白的间隙*/
271
+ return scrollIndex - (pageSize - 2);
229
272
  } else {
230
273
  return scrollIndex;
231
274
  }
232
275
  })();
233
- let end = start + pageSize * 2;
234
- start -= 1;
235
- end += 1;
236
- if (start < 0) {
237
- end -= start;
238
- start = 0;
276
+ let endIndex = startIndex + pageSize * 2;
277
+ startIndex -= 1;
278
+ endIndex += 1;
279
+ if (startIndex < 0) {
280
+ endIndex -= startIndex;
281
+ startIndex = 0;
239
282
  }
240
283
  /*console.log({
241
284
  scrollIndex,
@@ -245,19 +288,19 @@ export function useVirtualList(
245
288
  pageSize,
246
289
  scrollDirection: state.scrollDirection
247
290
  });*/
248
- const exceed = end - data.length;
291
+ const exceed = endIndex - data.length;
249
292
  if (exceed > 0) {
250
- end = data.length;
251
- start -= exceed;
252
- if (start < 0) {
253
- start = 0;
293
+ endIndex = data.length;
294
+ startIndex -= exceed;
295
+ if (startIndex < 0) {
296
+ startIndex = 0;
254
297
  }
255
298
  }
256
- pageIndex = Math.floor(start / pageSize);
299
+ pageIndex = Math.floor(startIndex / pageSize);
257
300
  return {
258
301
  data,
259
- start,
260
- end,
302
+ startIndex,
303
+ endIndex,
261
304
  pageIndex,
262
305
  };
263
306
  },
@@ -271,11 +314,11 @@ export function useVirtualList(
271
314
  if (props.disabled) {
272
315
  return;
273
316
  }
274
- const newScrollTop = (e.target as HTMLDivElement).scrollTop;
275
- state.scrollDirection = newScrollTop > freezeState.scrollTop ? ScrollDirection.down : ScrollDirection.up;
276
- freezeState.scrollTop = newScrollTop;
317
+ const newScrollValue = (e.target as HTMLDivElement)[props.horizontal ? 'scrollLeft' : 'scrollTop'];
318
+ state.scrollDirection = newScrollValue > freezeState.scrollValue ? ScrollDirection.end : ScrollDirection.start;
319
+ freezeState.scrollValue = newScrollValue;
277
320
  const current = utils.getPageIndex((e.target as HTMLDivElement).scrollTop, state.pageSize);
278
- state.scrollTop = (e.target as HTMLDivElement).scrollTop;
321
+ state.scrollValue = (e.target as HTMLDivElement)[props.horizontal ? 'scrollLeft' : 'scrollTop'];
279
322
  freezeState.current = current;
280
323
  emit.onPageIndexChange(current);
281
324
  }
@@ -293,17 +336,17 @@ export function useVirtualList(
293
336
 
294
337
  onMounted(async () => {
295
338
  await delay(23);
296
- let hostHeight = refs.scroll!.refs.host!.offsetHeight;
339
+ let hostSize = refs.scroll!.refs.host![props.horizontal ? 'offsetWidth' : 'offsetHeight'];
297
340
  const headEl = refs.scroll!.refs.host!.querySelector('[data-virtual-head]') as undefined | HTMLDivElement;
298
341
  const footEl = refs.scroll!.refs.host!.querySelector('[data-virtual-foot]') as undefined | HTMLDivElement;
299
342
  if (!!headEl) {
300
- hostHeight -= headEl.offsetHeight;
343
+ hostSize -= headEl[props.horizontal ? 'offsetWidth' : 'offsetHeight'];
301
344
  }
302
345
  if (!!footEl) {
303
- hostHeight -= footEl.offsetHeight;
346
+ hostSize -= footEl[props.horizontal ? 'offsetWidth' : 'offsetHeight'];
304
347
  }
305
348
 
306
- state.pageSize = Math.floor(hostHeight / props.size);
349
+ state.pageSize = Math.floor(hostSize / props.size);
307
350
  });
308
351
 
309
352
  onUpdated(async () => {
@@ -316,23 +359,23 @@ export function useVirtualList(
316
359
  await delay();
317
360
  // console.log('dynamic scan height')
318
361
  const elNodes = (refs.content?.querySelectorAll('[data-vid],[vid]') || []) as HTMLElement[];
319
- let newAvgHeight = state.avgHeight;
362
+ let newAvgSize = state.avgSize;
320
363
 
321
364
  for (let i = 0; i < elNodes.length; i++) {
322
365
  const el = elNodes[i];
323
- const { offsetHeight: height } = el;
366
+ const size = el[props.horizontal ? 'offsetWidth' : 'offsetHeight'];
324
367
  let vid = el.getAttribute('vid') || el.getAttribute('data-vid') as null | number | string;
325
368
  if (vid == null) {
326
369
  throw new Error('Each item of the virtual-list must have an attribute named "vid", please set :vid="index" or :data-vid="index"');
327
370
  }
328
- if (state.id2height[vid] != height) {
329
- state.id2height[vid] = height;
330
- newAvgHeight = Number(((state.avgHeight + height) / 2).toFixed(0));
371
+ if (state.id2size[vid] != size) {
372
+ state.id2size[vid] = size;
373
+ newAvgSize = Number(((state.avgSize + size) / 2).toFixed(0));
331
374
  }
332
375
  }
333
376
 
334
- if (newAvgHeight != state.avgHeight) {
335
- state.avgHeight = newAvgHeight;
377
+ if (newAvgSize != state.avgSize) {
378
+ state.avgSize = newAvgSize;
336
379
  }
337
380
  });
338
381
 
@@ -1,23 +1,6 @@
1
- @include comp(virtual-table) {
2
- @include comp(virtual-list) {
3
- & > .scroll-wrapper {
4
- & > .scroll-content {
5
- overflow-y: unset;
6
- }
7
- }
8
- }
9
- }
10
-
11
1
  @include comp(virtual-list) {
12
2
  position: relative;
13
3
 
14
- & > .scroll-wrapper {
15
- & > .scroll-content {
16
- overflow-y: hidden;
17
- min-width: 100%;
18
- }
19
- }
20
-
21
4
  &:not(.virtual-list-disabled) {
22
5
  .virtual-list-strut {
23
6
  position: relative;
@@ -32,4 +15,35 @@
32
15
  }
33
16
  }
34
17
  }
18
+
19
+ &:not(.virtual-list-horizontal) {
20
+ & > .scroll-wrapper {
21
+ & > .scroll-content {
22
+ overflow-y: hidden;
23
+ min-width: 100%;
24
+ }
25
+ }
26
+ }
27
+
28
+ &.virtual-list-horizontal {
29
+ & > .scroll-wrapper {
30
+ & > .scroll-content {
31
+ overflow-x: hidden;
32
+ min-height: 100%;
33
+ }
34
+ }
35
+ }
36
+ }
37
+
38
+
39
+ @include comp(virtual-table) {
40
+ @include comp(virtual-list) {
41
+ &.virtual-list-horizontal, &:not(.virtual-list-horizontal) {
42
+ & > .scroll-wrapper {
43
+ & > .scroll-content {
44
+ overflow-y: unset;
45
+ }
46
+ }
47
+ }
48
+ }
35
49
  }
@@ -25,7 +25,7 @@ export const VirtualTable = designComponent({
25
25
  inheritPropsType: HTMLDivElement,
26
26
  emits: {
27
27
  onScroll: (e: Event) => true,
28
- onPageIndexChange: (data: { pageIndex: number, start: number }) => true,
28
+ onPageIndexChange: (data: { pageIndex: number, startIndex: number }) => true,
29
29
  },
30
30
  slots: ['colgroup', 'head', 'headColgroup'],
31
31
  scopeSlots: {
@@ -32,8 +32,8 @@ export {Segment} from "./components/Segment";
32
32
  export {SegmentGroup} from "./components/SegmentGroup";
33
33
  export {InputGroup} from "./components/InputGroup";
34
34
  export {Card} from "./components/Card";
35
+ export {CarouselItem} from "./components/CarouselItem";
35
36
  export {Carousel} from "./components/Carousel";
36
- export {CarouselGroup} from "./components/CarouselGroup";
37
37
  export {CollapseGroup} from "./components/CollapseGroup";
38
38
  export {Collapse} from "./components/Collapse";
39
39
  export {ProgressBar} from "./components/ProgressBar";
@@ -108,6 +108,10 @@ export {useAutoScrollUtils} from './components/useAutoScrollUtils';
108
108
  export {ClientZoom} from './components/ClientZoom';
109
109
  export {Layout} from './components/Layout';
110
110
  export {LayoutSection} from './components/LayoutSection';
111
+ export {$previewer} from './components/$previewer';
112
+ export {StackCard} from './components/StackCard';
113
+ export {StackCardItem} from './components/StackCardItem';
114
+ export {SortList} from './components/SortList';
111
115
 
112
116
  export {VirtualTable} from './components/VirtualTable';
113
117
  export {Table} from './components/Table';
@@ -0,0 +1,82 @@
1
+ import {createEffects} from "plain-utils/utils/createEffects";
2
+ import {ClientZoom} from "../utils/ClientZoom";
3
+ import {watch} from "plain-design-composition";
4
+
5
+ export function useDragHorizontalScroll(getEl: () => HTMLElement | null | undefined, config?: { onDragStart: () => void, onDragEnd: () => void }) {
6
+
7
+ const staticState = {
8
+ isDragging: false,
9
+ el: null as null | undefined | HTMLElement,
10
+ start: {
11
+ x: 0,
12
+ left: 0,
13
+ width: 0,
14
+ },
15
+ move: {
16
+ x: 0
17
+ }
18
+ };
19
+
20
+ const { effects } = createEffects();
21
+
22
+ const handler = {
23
+ mousedown: (e: MouseEvent) => {
24
+ const { clientX } = ClientZoom.getClientPosition(e);
25
+ staticState.isDragging = false;
26
+ staticState.start = {
27
+ x: clientX,
28
+ left: staticState.el!.scrollLeft,
29
+ width: staticState.el!.scrollWidth,
30
+ };
31
+ document.documentElement.addEventListener('mousemove', handler.mousemove, true);
32
+ document.documentElement.addEventListener('mouseup', handler.mouseup, true);
33
+ },
34
+ mousemove: (e: MouseEvent) => {
35
+ const { clientX } = ClientZoom.getClientPosition(e);
36
+ staticState.move.x = clientX;
37
+ const durX = staticState.move.x - staticState.start.x;
38
+ if (!staticState.isDragging) {
39
+ if (Math.abs(durX) > 5) {
40
+ staticState.isDragging = true;
41
+ config?.onDragStart();
42
+ }
43
+ }
44
+ if (!staticState.isDragging) {
45
+ return;
46
+ }
47
+ staticState.el!.scrollLeft = staticState.start.left - durX;
48
+ },
49
+ mouseup: () => {
50
+ config?.onDragEnd();
51
+ document.documentElement.removeEventListener('mousemove', handler.mousemove, true);
52
+ document.documentElement.removeEventListener('mouseup', handler.mouseup, true);
53
+ },
54
+ onWheel: (e: WheelEvent) => {
55
+ e.stopPropagation();
56
+ e.preventDefault();
57
+ const el = e.currentTarget as HTMLElement;
58
+ const delta = e.deltaX + e.deltaY;
59
+ el.scrollLeft += delta;
60
+ },
61
+ };
62
+
63
+ effects.push(watch(() => getEl(), el => {
64
+ if (!!staticState.el) {
65
+ staticState.el.removeEventListener('mousedown', handler.mousedown);
66
+ staticState.el.removeEventListener('wheel', handler.onWheel);
67
+ }
68
+ staticState.el = el;
69
+ if (!staticState.el) {return;}
70
+ staticState.el.addEventListener('mousedown', handler.mousedown);
71
+ staticState.el.addEventListener('wheel', handler.onWheel);
72
+ }));
73
+
74
+ effects.push(() => {
75
+ if (!!staticState.el) {
76
+ staticState.el.removeEventListener('mousedown', handler.mousedown);
77
+ staticState.el.removeEventListener('wheel', handler.onWheel);
78
+ }
79
+ });
80
+
81
+ return effects.clear;
82
+ }
@@ -0,0 +1,10 @@
1
+ export const ComponentUtils = {
2
+ /**
3
+ * 适配taro ui的一些写法
4
+ * @author 韦胜健
5
+ * @date 2024/1/3 16:48
6
+ */
7
+ getElInfo: async (selector: string) => {
8
+ return document.querySelector(selector)!.getBoundingClientRect();
9
+ },
10
+ };
@@ -0,0 +1,31 @@
1
+ export function buildCycleIndexList({ length, current }: { length: number, current: number }) {
2
+
3
+ const sourceList = new Array(length).fill(null).map((_, index) => index);
4
+ const cycleIndexList = (() => {
5
+
6
+ if (sourceList.length <= 2) {
7
+ return sourceList;
8
+ }
9
+
10
+ const leftList = sourceList.slice(0, current);
11
+ const rightList = sourceList.slice(current + 1);
12
+
13
+ while (Math.abs(leftList.length - rightList.length) >= 2) {
14
+ if (leftList.length > rightList.length) {
15
+ rightList.push(leftList.shift()!);
16
+ } else {
17
+ leftList.unshift(rightList.pop()!);
18
+ }
19
+ }
20
+ return [...leftList, current, ...rightList];
21
+ })();
22
+
23
+ const currentIndexInCycle = cycleIndexList.indexOf(current);
24
+
25
+ const index2distance = cycleIndexList.reduce((prev, item, cycleIndex) => {
26
+ prev[item] = cycleIndex - currentIndexInCycle;
27
+ return prev;
28
+ }, {} as Record<number, number>);
29
+
30
+ return { cycleIndexList, currentIndexInCycle, index2distance };
31
+ }