@indielayer/ui 1.8.3 → 1.9.0

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 (44) hide show
  1. package/docs/pages/component/menu/usage.vue +1 -0
  2. package/docs/pages/component/select/usage.vue +17 -5
  3. package/docs/pages/component/table/index.vue +7 -0
  4. package/docs/pages/component/table/virtual.vue +53 -0
  5. package/lib/components/menu/MenuItem.vue.d.ts +3 -3
  6. package/lib/components/menu/MenuItem.vue.js +1 -1
  7. package/lib/components/menu/MenuItem.vue2.js +16 -16
  8. package/lib/components/menu/theme/MenuItem.base.theme.js +30 -30
  9. package/lib/components/select/Select.vue.d.ts +36 -0
  10. package/lib/components/select/Select.vue.js +224 -201
  11. package/lib/components/select/theme/Select.base.theme.js +1 -1
  12. package/lib/components/table/Table.vue.d.ts +91 -4
  13. package/lib/components/table/Table.vue.js +214 -180
  14. package/lib/components/table/TableHead.vue.d.ts +10 -2
  15. package/lib/components/table/TableHead.vue.js +16 -13
  16. package/lib/components/table/TableHeader.vue.d.ts +0 -4
  17. package/lib/components/table/TableHeader.vue.js +9 -10
  18. package/lib/components/table/theme/TableHead.base.theme.js +7 -4
  19. package/lib/components/table/theme/TableHead.carbon.theme.js +7 -4
  20. package/lib/components/table/theme/TableHeader.base.theme.js +3 -3
  21. package/lib/components/table/theme/TableHeader.carbon.theme.js +1 -1
  22. package/lib/composables/index.d.ts +1 -0
  23. package/lib/composables/useVirtualList.d.ts +48 -0
  24. package/lib/composables/useVirtualList.js +123 -0
  25. package/lib/index.js +35 -33
  26. package/lib/index.umd.js +4 -4
  27. package/lib/node_modules/.pnpm/@vueuse_core@10.2.0_vue@3.3.9_typescript@5.2.2_/node_modules/@vueuse/core/index.js +254 -221
  28. package/lib/version.d.ts +1 -1
  29. package/lib/version.js +1 -1
  30. package/package.json +1 -1
  31. package/src/components/menu/MenuItem.vue +1 -1
  32. package/src/components/menu/theme/MenuItem.base.theme.ts +8 -8
  33. package/src/components/select/Select.vue +56 -26
  34. package/src/components/select/theme/Select.base.theme.ts +1 -1
  35. package/src/components/table/Table.vue +152 -113
  36. package/src/components/table/TableHead.vue +6 -2
  37. package/src/components/table/TableHeader.vue +0 -1
  38. package/src/components/table/theme/TableHead.base.theme.ts +7 -1
  39. package/src/components/table/theme/TableHead.carbon.theme.ts +7 -1
  40. package/src/components/table/theme/TableHeader.base.theme.ts +0 -2
  41. package/src/components/table/theme/TableHeader.carbon.theme.ts +0 -2
  42. package/src/composables/index.ts +1 -0
  43. package/src/composables/useVirtualList.ts +286 -0
  44. package/src/version.ts +1 -1
@@ -0,0 +1,286 @@
1
+ /**
2
+ * @file useVirtualList composable adapted from https://github.com/vueuse/vueuse/blob/main/packages/core/useVirtualList/index.ts
3
+ */
4
+ import { computed, ref, shallowRef, unref, watch } from 'vue'
5
+ import type { Ref, ShallowRef, StyleValue } from 'vue'
6
+ import type { MaybeRef } from '@vueuse/shared'
7
+ import { useElementSize } from '@vueuse/core'
8
+
9
+ type UseVirtualListItemSize = number | ((index: number) => number)
10
+
11
+ export type UseVirtualListOptions = {
12
+ /**
13
+ * item height, accept a pixel value or a function that returns the height
14
+ *
15
+ * @default 0
16
+ */
17
+ disabled?: boolean;
18
+ itemHeight: UseVirtualListItemSize;
19
+ topOffset: number;
20
+ bottomOffset: number;
21
+ /**
22
+ * the extra buffer items outside of the view area
23
+ *
24
+ * @default 5
25
+ */
26
+ overscan?: number;
27
+ }
28
+
29
+ export interface UseVirtualListItem<T> {
30
+ data: T;
31
+ index: number;
32
+ }
33
+
34
+ export interface UseVirtualListReturn<T> {
35
+ list: Ref<UseVirtualListItem<T>[]>;
36
+ scrollTo: (index: number) => void;
37
+ reset: () => void;
38
+
39
+ containerProps: {
40
+ ref: Ref<HTMLElement | null>;
41
+ style: StyleValue;
42
+ onScroll: () => void;
43
+ };
44
+ wrapperProps: MaybeRef<{
45
+ style?: {
46
+ width: string;
47
+ height: string;
48
+ marginTop: string;
49
+ } | {
50
+ width: string;
51
+ height: string;
52
+ marginLeft: string;
53
+ display: string;
54
+ };
55
+ }>;
56
+ }
57
+
58
+ export function useVirtualList<T = any>(list: MaybeRef<T[]>, options: UseVirtualListOptions): UseVirtualListReturn<T> {
59
+ if (options.disabled) {
60
+ return {
61
+ list: computed(() => unref(list).map((data, index) => ({ data, index }))),
62
+ scrollTo: () => {},
63
+ reset: () => {},
64
+ containerProps: {
65
+ ref: ref(null),
66
+ style: {},
67
+ onScroll: () => {},
68
+ },
69
+ wrapperProps: {},
70
+ }
71
+ }
72
+
73
+ const { containerStyle, wrapperProps, scrollTo, calculateRange, currentList, containerRef } = useVerticalVirtualList(options, list)
74
+
75
+ return {
76
+ list: currentList,
77
+ scrollTo,
78
+ reset: calculateRange,
79
+ containerProps: {
80
+ ref: containerRef,
81
+ onScroll: () => {
82
+ calculateRange()
83
+ },
84
+ style: containerStyle,
85
+ },
86
+ wrapperProps,
87
+ }
88
+ }
89
+
90
+ type UseVirtualListContainerRef = Ref<HTMLElement | null>
91
+
92
+ interface UseVirtualElementSizes {
93
+ width: Ref<number>;
94
+ height: Ref<number>;
95
+ }
96
+
97
+ type UseVirtualListArray<T> = UseVirtualListItem<T>[]
98
+ type UseVirtualListRefArray<T> = Ref<UseVirtualListArray<T>>
99
+
100
+ type UseVirtualListSource<T> = Ref<T[]> | ShallowRef<T[]>
101
+
102
+ interface UseVirtualListState { start: number; end: number; }
103
+
104
+ type RefState = Ref<UseVirtualListState>
105
+
106
+ interface UseVirtualListResources<T> {
107
+ state: RefState;
108
+ source: UseVirtualListSource<T>;
109
+ currentList: UseVirtualListRefArray<T>;
110
+ size: UseVirtualElementSizes;
111
+ containerRef: UseVirtualListContainerRef;
112
+ }
113
+
114
+ function useVirtualListResources<T>(list: MaybeRef<T[]>): UseVirtualListResources<T> {
115
+ const containerRef = ref<HTMLElement | null>(null)
116
+ const size = useElementSize(containerRef)
117
+
118
+ const currentList: Ref<UseVirtualListItem<T>[]> = ref([])
119
+ const source = shallowRef(list)
120
+
121
+ const state: Ref<{ start: number; end: number; }> = ref({ start: 0, end: 10 })
122
+
123
+ return { state, source, currentList, size, containerRef }
124
+ }
125
+
126
+ function createGetViewCapacity<T>(state: UseVirtualListResources<T>['state'], source: UseVirtualListResources<T>['source'], itemSize: UseVirtualListItemSize) {
127
+ return (containerSize: number) => {
128
+ if (typeof itemSize === 'number')
129
+ return Math.ceil(containerSize / itemSize)
130
+
131
+ const { start = 0 } = state.value
132
+ let sum = 0
133
+ let capacity = 0
134
+
135
+ for (let i = start; i < source.value.length; i++) {
136
+ const size = itemSize(i)
137
+
138
+ sum += size
139
+ capacity = i
140
+ if (sum > containerSize)
141
+ break
142
+ }
143
+
144
+ return capacity - start
145
+ }
146
+ }
147
+
148
+ function createGetOffset<T>(source: UseVirtualListResources<T>['source'], itemSize: UseVirtualListItemSize) {
149
+ return (scrollDirection: number) => {
150
+ if (typeof itemSize === 'number')
151
+ return Math.floor(scrollDirection / itemSize) + 1
152
+
153
+ let sum = 0
154
+ let offset = 0
155
+
156
+ for (let i = 0; i < source.value.length; i++) {
157
+ const size = itemSize(i)
158
+
159
+ sum += size
160
+ if (sum >= scrollDirection) {
161
+ offset = i
162
+ break
163
+ }
164
+ }
165
+
166
+ return offset + 1
167
+ }
168
+ }
169
+
170
+ function createCalculateRange<T>(type: 'horizontal' | 'vertical', overscan: number, getOffset: ReturnType<typeof createGetOffset>, getViewCapacity: ReturnType<typeof createGetViewCapacity>, { containerRef, state, currentList, source }: UseVirtualListResources<T>) {
171
+ return () => {
172
+ const element = containerRef.value
173
+
174
+ if (element) {
175
+ const offset = getOffset(type === 'vertical' ? element.scrollTop : element.scrollLeft)
176
+ const viewCapacity = getViewCapacity(type === 'vertical' ? element.clientHeight : element.clientWidth)
177
+
178
+ const from = offset - overscan
179
+ const to = offset + viewCapacity + overscan
180
+
181
+ state.value = {
182
+ start: from < 0 ? 0 : from,
183
+ end: to > source.value.length
184
+ ? source.value.length
185
+ : to,
186
+ }
187
+ currentList.value = source.value
188
+ .slice(state.value.start, state.value.end)
189
+ .map((ele, index) => ({
190
+ data: ele,
191
+ index: index + state.value.start,
192
+ }))
193
+ }
194
+ }
195
+ }
196
+
197
+ function createGetDistance<T>(itemSize: UseVirtualListItemSize, source: UseVirtualListResources<T>['source']) {
198
+ return (index: number) => {
199
+ if (typeof itemSize === 'number') {
200
+ const size = index * itemSize
201
+
202
+ return size
203
+ }
204
+
205
+ const size = source.value
206
+ .slice(0, index)
207
+ .reduce((sum, _, i) => sum + itemSize(i), 0)
208
+
209
+ return size
210
+ }
211
+ }
212
+
213
+ function useWatchForSizes<T>(size: UseVirtualElementSizes, list: MaybeRef<T[]>, containerRef: Ref<HTMLElement | null>, calculateRange: () => void, scrollTo: (index: number) => void) {
214
+ watch([size.width, size.height, list, containerRef], () => {
215
+ calculateRange()
216
+ scrollTo(0)
217
+ })
218
+ }
219
+
220
+ function createComputedTotalSize<T>(itemSize: UseVirtualListItemSize, source: UseVirtualListResources<T>['source']) {
221
+ return computed(() => {
222
+ if (typeof itemSize === 'number')
223
+ return source.value.length * itemSize
224
+
225
+ return source.value.reduce((sum, _, index) => sum + itemSize(index), 0)
226
+ })
227
+ }
228
+
229
+ const scrollToDictionaryForElementScrollKey = {
230
+ horizontal: 'scrollLeft',
231
+ vertical: 'scrollTop',
232
+ } as const
233
+
234
+ function createScrollTo<T>(type: 'horizontal' | 'vertical', calculateRange: () => void, getDistance: ReturnType<typeof createGetDistance>, containerRef: UseVirtualListResources<T>['containerRef']) {
235
+ return (index: number) => {
236
+ if (containerRef.value) {
237
+ containerRef.value[scrollToDictionaryForElementScrollKey[type]] = getDistance(index)
238
+ calculateRange()
239
+ }
240
+ }
241
+ }
242
+
243
+ function useVerticalVirtualList<T>(options: UseVirtualListOptions, list: MaybeRef<T[]>) {
244
+ const resources = useVirtualListResources(list)
245
+
246
+ const { state, source, currentList, size, containerRef } = resources
247
+
248
+ const containerStyle: StyleValue = { overflowY: 'auto' }
249
+
250
+ const { itemHeight, topOffset = 0, bottomOffset = 0, overscan = 5 } = options
251
+
252
+ const getViewCapacity = createGetViewCapacity(state, source, itemHeight)
253
+
254
+ const getOffset = createGetOffset(source, itemHeight)
255
+
256
+ const calculateRange = createCalculateRange('vertical', overscan, getOffset, getViewCapacity, resources)
257
+
258
+ const getDistanceTop = createGetDistance(itemHeight, source)
259
+
260
+ const offsetTop = computed(() => getDistanceTop(state.value.start))
261
+
262
+ const totalHeight = createComputedTotalSize(itemHeight, source)
263
+
264
+ const scrollTo = createScrollTo('vertical', calculateRange, getDistanceTop, containerRef)
265
+
266
+ useWatchForSizes(size, list, containerRef, calculateRange, scrollTo)
267
+
268
+ const wrapperProps = computed(() => {
269
+ return {
270
+ style: {
271
+ width: '100%',
272
+ height: `${totalHeight.value - offsetTop.value + topOffset + bottomOffset}px`,
273
+ marginTop: `${offsetTop.value}px`,
274
+ },
275
+ }
276
+ })
277
+
278
+ return {
279
+ calculateRange,
280
+ scrollTo,
281
+ containerStyle,
282
+ wrapperProps,
283
+ currentList,
284
+ containerRef,
285
+ }
286
+ }
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export default '1.8.3'
1
+ export default '1.9.0'