virtua 0.52.10 → 0.53.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.
- package/README.md +286 -193
- package/lib/angular/VList.d.ts +3 -1
- package/lib/angular/VMasonry.d.ts +114 -0
- package/lib/angular/Virtualizer.d.ts +3 -1
- package/lib/angular/WindowVirtualizer.d.ts +3 -1
- package/lib/angular/index.d.ts +1 -0
- package/lib/angular/index.js +733 -352
- package/lib/angular/index.js.map +1 -1
- package/lib/core/index.cjs +180 -104
- package/lib/core/index.cjs.map +1 -1
- package/lib/core/index.d.ts +1 -0
- package/lib/core/index.js +257 -181
- package/lib/core/index.js.map +1 -1
- package/lib/core/layouts/masonry.d.ts +1 -0
- package/lib/index.cjs +555 -385
- package/lib/index.cjs.map +1 -1
- package/lib/index.js +572 -404
- package/lib/index.js.map +1 -1
- package/lib/react/VMasonry.d.ts +105 -0
- package/lib/react/Virtualizer.d.ts +3 -1
- package/lib/react/WindowVirtualizer.d.ts +3 -1
- package/lib/react/index.d.ts +2 -0
- package/lib/react/types.d.ts +1 -1
- package/lib/solid/VMasonry.d.ts +107 -0
- package/lib/solid/Virtualizer.d.ts +3 -1
- package/lib/solid/WindowVirtualizer.d.ts +3 -1
- package/lib/solid/index.cjs +720 -514
- package/lib/solid/index.cjs.map +1 -1
- package/lib/solid/index.d.ts +2 -0
- package/lib/solid/index.js +691 -494
- package/lib/solid/index.js.map +1 -1
- package/lib/solid/index.jsx +329 -8
- package/lib/solid/index.jsx.map +1 -1
- package/lib/solid/types.d.ts +1 -1
- package/lib/svelte/MasonryItem.svelte +49 -0
- package/lib/svelte/VGrid.svelte +1 -1
- package/lib/svelte/VList.svelte +1 -1
- package/lib/svelte/VMasonry.svelte +182 -0
- package/lib/svelte/VMasonry.type.d.ts +104 -0
- package/lib/svelte/Virtualizer.svelte +1 -1
- package/lib/svelte/Virtualizer.type.d.ts +3 -1
- package/lib/svelte/WindowVirtualizer.svelte +1 -1
- package/lib/svelte/WindowVirtualizer.type.d.ts +3 -1
- package/lib/svelte/index.d.ts +2 -0
- package/lib/svelte/index.js +2 -1
- package/lib/svelte/types.d.ts +2 -2
- package/lib/vue/VMasonry.d.ts +110 -0
- package/lib/vue/Virtualizer.d.ts +3 -1
- package/lib/vue/WindowVirtualizer.d.ts +3 -1
- package/lib/vue/index.cjs +625 -403
- package/lib/vue/index.cjs.map +1 -1
- package/lib/vue/index.d.ts +2 -0
- package/lib/vue/index.js +672 -455
- package/lib/vue/index.js.map +1 -1
- package/package.json +6 -16
package/lib/solid/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { JSX, ParentComponent } from 'solid-js';
|
|
2
|
-
export type ViewportComponentAttributes =
|
|
2
|
+
export type ViewportComponentAttributes = Omit<JSX.HTMLAttributes<HTMLDivElement>, "ref" | "children" | "style" | "onScroll" | "onScrollEnd"> & {
|
|
3
3
|
style?: JSX.CSSProperties;
|
|
4
4
|
};
|
|
5
5
|
export interface CustomContainerComponentProps {
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<script lang="ts" generics="T">
|
|
2
|
+
import { type Snippet } from "svelte";
|
|
3
|
+
import { type Driver } from "../core/index.js";
|
|
4
|
+
import { styleToString } from "./utils.js";
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
children: Snippet<[item: T, index: number]>;
|
|
8
|
+
item: T;
|
|
9
|
+
index: number;
|
|
10
|
+
offset: number;
|
|
11
|
+
crossOffset: string;
|
|
12
|
+
crossSize: string;
|
|
13
|
+
hide: boolean;
|
|
14
|
+
resizer: Driver["$observeItem"];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let {
|
|
18
|
+
children,
|
|
19
|
+
item,
|
|
20
|
+
index,
|
|
21
|
+
offset,
|
|
22
|
+
crossOffset,
|
|
23
|
+
crossSize,
|
|
24
|
+
hide,
|
|
25
|
+
resizer,
|
|
26
|
+
}: Props = $props();
|
|
27
|
+
|
|
28
|
+
let elementRef: HTMLDivElement;
|
|
29
|
+
|
|
30
|
+
// The index may be changed if elements are inserted to or removed from the start of data
|
|
31
|
+
$effect(() => {
|
|
32
|
+
return resizer(elementRef, index);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
let style: string = $derived(
|
|
36
|
+
styleToString({
|
|
37
|
+
contain: "layout style",
|
|
38
|
+
position: "absolute",
|
|
39
|
+
top: offset + "px",
|
|
40
|
+
"inset-inline-start": crossOffset,
|
|
41
|
+
width: crossSize,
|
|
42
|
+
visibility: hide ? "hidden" : undefined,
|
|
43
|
+
}),
|
|
44
|
+
);
|
|
45
|
+
</script>
|
|
46
|
+
|
|
47
|
+
<div bind:this={elementRef} {style}>
|
|
48
|
+
{@render children(item, index)}
|
|
49
|
+
</div>
|
package/lib/svelte/VGrid.svelte
CHANGED
|
@@ -187,7 +187,7 @@
|
|
|
187
187
|
return styleToString({
|
|
188
188
|
// https://github.com/inokawa/virtua/pull/775 https://github.com/inokawa/virtua/issues/800
|
|
189
189
|
contain: "size style",
|
|
190
|
-
"overflow-anchor": "none", // opt out browser's scroll anchoring because it will conflict
|
|
190
|
+
"overflow-anchor": "none", // opt out browser's scroll anchoring because it will conflict with scroll anchoring of virtualizer
|
|
191
191
|
flex: "none", // flex style can break layout
|
|
192
192
|
display: "grid",
|
|
193
193
|
"grid-template-rows": rowTemplate,
|
package/lib/svelte/VList.svelte
CHANGED
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
)) satisfies VListHandle["scrollBy"] as VListHandle["scrollBy"];
|
|
59
59
|
|
|
60
60
|
const viewportStyle = styleToString({
|
|
61
|
-
display:
|
|
61
|
+
display: "block",
|
|
62
62
|
[horizontal ? "overflow-x" : "overflow-y"]: "auto",
|
|
63
63
|
contain: "strict",
|
|
64
64
|
width: "100%",
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
<script lang="ts" generics="T">
|
|
2
|
+
import { onMount, onDestroy } from "svelte";
|
|
3
|
+
import {
|
|
4
|
+
type ItemsRange,
|
|
5
|
+
type StateVersion,
|
|
6
|
+
UPDATE_SCROLL_END_EVENT,
|
|
7
|
+
UPDATE_SCROLL_EVENT,
|
|
8
|
+
UPDATE_VIRTUAL_STATE,
|
|
9
|
+
createContainerDriver,
|
|
10
|
+
createMasonryLayout,
|
|
11
|
+
ACTION_ITEMS_LENGTH_CHANGE,
|
|
12
|
+
ACTION_RELAYOUT,
|
|
13
|
+
createVirtualStore,
|
|
14
|
+
getScrollSize as _getScrollSize,
|
|
15
|
+
scrollTo as _scrollTo,
|
|
16
|
+
scrollBy as _scrollBy,
|
|
17
|
+
scrollToIndex as _scrollToIndex,
|
|
18
|
+
} from "../core/index.js";
|
|
19
|
+
import { defaultGetKey, isSameRange, styleToString } from "./utils.js";
|
|
20
|
+
import MasonryItem from "./MasonryItem.svelte";
|
|
21
|
+
import type { VMasonryHandle, VMasonryProps } from "./VMasonry.type.js";
|
|
22
|
+
|
|
23
|
+
const toCrossValue = (fraction: number, px: number): string =>
|
|
24
|
+
px ? `calc(${fraction * 100}% + ${px}px)` : fraction * 100 + "%";
|
|
25
|
+
|
|
26
|
+
interface Props extends VMasonryProps<T> {}
|
|
27
|
+
|
|
28
|
+
let {
|
|
29
|
+
data,
|
|
30
|
+
getKey = defaultGetKey,
|
|
31
|
+
lanes: lanesProp,
|
|
32
|
+
gap: gapProp,
|
|
33
|
+
itemSize,
|
|
34
|
+
bufferSize,
|
|
35
|
+
cache,
|
|
36
|
+
children,
|
|
37
|
+
onscroll,
|
|
38
|
+
onscrollend,
|
|
39
|
+
...rest
|
|
40
|
+
}: Props = $props();
|
|
41
|
+
|
|
42
|
+
const layout = createMasonryLayout(
|
|
43
|
+
data.length,
|
|
44
|
+
lanesProp,
|
|
45
|
+
gapProp,
|
|
46
|
+
itemSize,
|
|
47
|
+
cache,
|
|
48
|
+
);
|
|
49
|
+
const store = createVirtualStore(layout);
|
|
50
|
+
const driver = createContainerDriver(store, false);
|
|
51
|
+
store.$subscribe(UPDATE_VIRTUAL_STATE, () => {
|
|
52
|
+
stateVersion = store.$getStateVersion();
|
|
53
|
+
});
|
|
54
|
+
store.$subscribe(UPDATE_SCROLL_EVENT, () => {
|
|
55
|
+
onscroll && onscroll(store.$getScrollOffset());
|
|
56
|
+
});
|
|
57
|
+
store.$subscribe(UPDATE_SCROLL_END_EVENT, () => {
|
|
58
|
+
onscrollend && onscrollend();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
let containerRef: HTMLDivElement | undefined = $state();
|
|
62
|
+
|
|
63
|
+
let stateVersion: StateVersion = $state(store.$getStateVersion());
|
|
64
|
+
|
|
65
|
+
let prevRange: ItemsRange | undefined;
|
|
66
|
+
let range = $derived.by(() => {
|
|
67
|
+
stateVersion;
|
|
68
|
+
const next = store.$getRange(bufferSize);
|
|
69
|
+
if (prevRange && isSameRange(prevRange, next)) {
|
|
70
|
+
return prevRange;
|
|
71
|
+
}
|
|
72
|
+
return (prevRange = next);
|
|
73
|
+
});
|
|
74
|
+
let isScrolling = $derived(stateVersion && store.$isScrolling());
|
|
75
|
+
let totalSize = $derived(stateVersion && store.$getTotalSize());
|
|
76
|
+
let lanes = $derived(stateVersion && layout.$getLanes());
|
|
77
|
+
let gap = $derived(stateVersion && layout.$getGap());
|
|
78
|
+
// The lanes share the width left by the gaps between them
|
|
79
|
+
let crossSize = $derived(toCrossValue(1 / lanes, gap / lanes - gap));
|
|
80
|
+
|
|
81
|
+
let indexes = $derived.by(() => {
|
|
82
|
+
const len = data.length;
|
|
83
|
+
const [start, end] = range;
|
|
84
|
+
const arr: number[] = [];
|
|
85
|
+
for (let i = start; i <= end; i++) {
|
|
86
|
+
// Guard for experimental.async: true, which runs the each block before $effect.pre
|
|
87
|
+
// https://github.com/inokawa/virtua/pull/847
|
|
88
|
+
if (i < len) {
|
|
89
|
+
arr.push(i);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return arr;
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
onMount(() => {
|
|
96
|
+
driver.$observe(containerRef!);
|
|
97
|
+
});
|
|
98
|
+
onDestroy(() => {
|
|
99
|
+
store.$dispose();
|
|
100
|
+
driver.$dispose();
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
$effect.pre(() => {
|
|
104
|
+
if (data.length !== store.$getItemsLength()) {
|
|
105
|
+
store.$update(ACTION_ITEMS_LENGTH_CHANGE, [data.length]);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
$effect.pre(() => {
|
|
109
|
+
layout.$setOptions(lanesProp, gapProp);
|
|
110
|
+
store.$update(ACTION_RELAYOUT, undefined);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
let prevStateVersion: StateVersion | undefined;
|
|
114
|
+
$effect(() => {
|
|
115
|
+
if (prevStateVersion === stateVersion) return;
|
|
116
|
+
prevStateVersion = stateVersion;
|
|
117
|
+
driver.$effect();
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
export const getCache =
|
|
121
|
+
layout.$snapshot satisfies VMasonryHandle["getCache"] as VMasonryHandle["getCache"];
|
|
122
|
+
export const getScrollOffset =
|
|
123
|
+
store.$getScrollOffset satisfies VMasonryHandle["getScrollOffset"] as VMasonryHandle["getScrollOffset"];
|
|
124
|
+
export const getScrollSize = (() =>
|
|
125
|
+
_getScrollSize(
|
|
126
|
+
store,
|
|
127
|
+
)) satisfies VMasonryHandle["getScrollSize"] as VMasonryHandle["getScrollSize"];
|
|
128
|
+
export const getViewportSize =
|
|
129
|
+
store.$getViewportSize satisfies VMasonryHandle["getViewportSize"] as VMasonryHandle["getViewportSize"];
|
|
130
|
+
export const getItemOffset =
|
|
131
|
+
store.$getItemOffset satisfies VMasonryHandle["getItemOffset"] as VMasonryHandle["getItemOffset"];
|
|
132
|
+
export const getItemSize =
|
|
133
|
+
store.$getItemSize satisfies VMasonryHandle["getItemSize"] as VMasonryHandle["getItemSize"];
|
|
134
|
+
export const scrollToIndex: VMasonryHandle["scrollToIndex"] = (index, opts) =>
|
|
135
|
+
_scrollToIndex(driver, store, index, opts);
|
|
136
|
+
export const scrollTo: VMasonryHandle["scrollTo"] = (offset) =>
|
|
137
|
+
_scrollTo(driver, offset);
|
|
138
|
+
export const scrollBy: VMasonryHandle["scrollBy"] = (offset) =>
|
|
139
|
+
_scrollBy(driver, store, offset);
|
|
140
|
+
|
|
141
|
+
const viewportStyle = styleToString({
|
|
142
|
+
display: "block",
|
|
143
|
+
"overflow-y": "auto",
|
|
144
|
+
contain: "strict",
|
|
145
|
+
width: "100%",
|
|
146
|
+
height: "100%",
|
|
147
|
+
});
|
|
148
|
+
let containerStyle = $derived(
|
|
149
|
+
styleToString({
|
|
150
|
+
contain: "size style", // https://github.com/inokawa/virtua/pull/775 https://github.com/inokawa/virtua/issues/800
|
|
151
|
+
"overflow-anchor": "none", // opt out browser's scroll anchoring because it will conflict with scroll anchoring of virtualizer
|
|
152
|
+
flex: "none", // flex style can break layout
|
|
153
|
+
position: "relative",
|
|
154
|
+
width: "100%",
|
|
155
|
+
height: totalSize + "px",
|
|
156
|
+
"pointer-events": isScrolling ? "none" : undefined,
|
|
157
|
+
}),
|
|
158
|
+
);
|
|
159
|
+
</script>
|
|
160
|
+
|
|
161
|
+
<!--
|
|
162
|
+
@component
|
|
163
|
+
Virtualized masonry component. See {@link VMasonryProps} and {@link VMasonryHandle}.
|
|
164
|
+
-->
|
|
165
|
+
<div {...rest} style="{viewportStyle} {rest.style || ''}">
|
|
166
|
+
<div bind:this={containerRef} style={containerStyle}>
|
|
167
|
+
{#each indexes as index (getKey(data[index]!, index))}
|
|
168
|
+
{@const item = data[index]!}
|
|
169
|
+
{@const lane = stateVersion && layout.$getItemLane(index)}
|
|
170
|
+
<MasonryItem
|
|
171
|
+
{children}
|
|
172
|
+
{item}
|
|
173
|
+
{index}
|
|
174
|
+
offset={stateVersion && store.$getItemOffset(index)}
|
|
175
|
+
crossOffset={toCrossValue(lane / lanes, (lane * gap) / lanes)}
|
|
176
|
+
{crossSize}
|
|
177
|
+
hide={stateVersion && store.$isUnmeasuredItem(index)}
|
|
178
|
+
resizer={driver.$observeItem}
|
|
179
|
+
/>
|
|
180
|
+
{/each}
|
|
181
|
+
</div>
|
|
182
|
+
</div>
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { Snippet } from 'svelte';
|
|
2
|
+
import { CacheSnapshot, ScrollToIndexOpts } from '../core/index.js';
|
|
3
|
+
import { ViewportComponentAttributes } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Props of {@link VMasonry}.
|
|
6
|
+
*/
|
|
7
|
+
export interface VMasonryProps<T> extends ViewportComponentAttributes {
|
|
8
|
+
/**
|
|
9
|
+
* The data items rendered by this component.
|
|
10
|
+
*/
|
|
11
|
+
data: readonly T[];
|
|
12
|
+
/**
|
|
13
|
+
* The elements renderer snippet.
|
|
14
|
+
*/
|
|
15
|
+
children: Snippet<[item: T, index: number]>;
|
|
16
|
+
/**
|
|
17
|
+
* Function that returns the key of an item in the list. It's recommended to specify whenever possible for performance.
|
|
18
|
+
* @default defaultGetKey (returns index of item)
|
|
19
|
+
*/
|
|
20
|
+
getKey?: (data: T, index: number) => string | number;
|
|
21
|
+
/**
|
|
22
|
+
* The number of lanes (columns) which items are laid out into. Each item is placed into the shortest lane in order. It must be an integer and the minimum value is 1.
|
|
23
|
+
*/
|
|
24
|
+
lanes: number;
|
|
25
|
+
/**
|
|
26
|
+
* The gap between the items and the lanes in pixels, which is not included in the sizes.
|
|
27
|
+
* @defaultValue 0
|
|
28
|
+
*/
|
|
29
|
+
gap?: number;
|
|
30
|
+
/**
|
|
31
|
+
* Item size hint for unmeasured items in pixels. It will help to reduce scroll jump when items are measured if used properly.
|
|
32
|
+
*
|
|
33
|
+
* - If not set, initial item sizes will be automatically estimated from measured sizes. This is recommended for most cases.
|
|
34
|
+
* - If set, you can opt out estimation and use the value as initial item size.
|
|
35
|
+
*/
|
|
36
|
+
itemSize?: number;
|
|
37
|
+
/**
|
|
38
|
+
* Extra item space in pixels to render before/after the viewport. The minimum value is 0. Lower value will give better performance but you can increase to avoid showing blank items in fast scrolling.
|
|
39
|
+
* @defaultValue 200
|
|
40
|
+
*/
|
|
41
|
+
bufferSize?: number;
|
|
42
|
+
/**
|
|
43
|
+
* You can restore cache by passing a {@link CacheSnapshot} on mount. This is useful when you want to restore scroll position after navigation. The snapshot can be obtained from {@link VMasonryHandle.getCache}.
|
|
44
|
+
*
|
|
45
|
+
* **The length of items should be the same as when you take the snapshot, otherwise restoration may not work as expected.**
|
|
46
|
+
*/
|
|
47
|
+
cache?: CacheSnapshot;
|
|
48
|
+
/**
|
|
49
|
+
* Callback invoked whenever scroll offset changes.
|
|
50
|
+
* @param offset Current scrollTop.
|
|
51
|
+
*/
|
|
52
|
+
onscroll?: (offset: number) => void;
|
|
53
|
+
/**
|
|
54
|
+
* Callback invoked when scrolling stops.
|
|
55
|
+
*/
|
|
56
|
+
onscrollend?: () => void;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Methods of {@link VMasonry}.
|
|
60
|
+
*/
|
|
61
|
+
export interface VMasonryHandle {
|
|
62
|
+
/**
|
|
63
|
+
* Get current {@link CacheSnapshot}.
|
|
64
|
+
*/
|
|
65
|
+
getCache: () => CacheSnapshot;
|
|
66
|
+
/**
|
|
67
|
+
* Get current scrollTop.
|
|
68
|
+
*/
|
|
69
|
+
getScrollOffset: () => number;
|
|
70
|
+
/**
|
|
71
|
+
* Get current scrollHeight.
|
|
72
|
+
*/
|
|
73
|
+
getScrollSize: () => number;
|
|
74
|
+
/**
|
|
75
|
+
* Get current clientHeight.
|
|
76
|
+
*/
|
|
77
|
+
getViewportSize: () => number;
|
|
78
|
+
/**
|
|
79
|
+
* Get item offset from start.
|
|
80
|
+
* @param index index of item
|
|
81
|
+
*/
|
|
82
|
+
getItemOffset(index: number): number;
|
|
83
|
+
/**
|
|
84
|
+
* Get item size.
|
|
85
|
+
* @param index index of item
|
|
86
|
+
*/
|
|
87
|
+
getItemSize(index: number): number;
|
|
88
|
+
/**
|
|
89
|
+
* Scroll to the item specified by index.
|
|
90
|
+
* @param index index of item
|
|
91
|
+
* @param opts options
|
|
92
|
+
*/
|
|
93
|
+
scrollToIndex(index: number, opts?: ScrollToIndexOpts): void;
|
|
94
|
+
/**
|
|
95
|
+
* Scroll to the given offset.
|
|
96
|
+
* @param offset offset from start
|
|
97
|
+
*/
|
|
98
|
+
scrollTo(offset: number): void;
|
|
99
|
+
/**
|
|
100
|
+
* Scroll by the given offset.
|
|
101
|
+
* @param offset offset from current position
|
|
102
|
+
*/
|
|
103
|
+
scrollBy(offset: number): void;
|
|
104
|
+
}
|
|
@@ -171,7 +171,7 @@
|
|
|
171
171
|
let containerStyle = $derived(
|
|
172
172
|
styleToString({
|
|
173
173
|
contain: "size style", // https://github.com/inokawa/virtua/pull/775 https://github.com/inokawa/virtua/issues/800
|
|
174
|
-
"overflow-anchor": "none", // opt out browser's scroll anchoring because it will conflict
|
|
174
|
+
"overflow-anchor": "none", // opt out browser's scroll anchoring because it will conflict with scroll anchoring of virtualizer
|
|
175
175
|
flex: "none", // flex style can break layout
|
|
176
176
|
position: "relative",
|
|
177
177
|
width: horizontal ? totalSize + "px" : "100%",
|
|
@@ -54,7 +54,9 @@ export interface VirtualizerProps<T> {
|
|
|
54
54
|
*/
|
|
55
55
|
ssrCount?: number;
|
|
56
56
|
/**
|
|
57
|
-
*
|
|
57
|
+
* Set true only when items are added to or removed from the start of the list, such as when older items are loaded in reverse infinite scrolling. In that case, the scroll position is maintained from the end of the list instead of the start.
|
|
58
|
+
*
|
|
59
|
+
* **Do not set true in any other case, as it can cause unexpected behavior.**
|
|
58
60
|
*/
|
|
59
61
|
shift?: boolean;
|
|
60
62
|
/**
|
|
@@ -126,7 +126,7 @@
|
|
|
126
126
|
let containerStyle = $derived(
|
|
127
127
|
styleToString({
|
|
128
128
|
contain: "size style", // https://github.com/inokawa/virtua/pull/775 https://github.com/inokawa/virtua/issues/800
|
|
129
|
-
"overflow-anchor": "none", // opt out browser's scroll anchoring because it will conflict
|
|
129
|
+
"overflow-anchor": "none", // opt out browser's scroll anchoring because it will conflict with scroll anchoring of virtualizer
|
|
130
130
|
flex: "none", // flex style can break layout
|
|
131
131
|
position: "relative",
|
|
132
132
|
width: horizontal ? totalSize + "px" : "100%",
|
|
@@ -34,7 +34,9 @@ export interface WindowVirtualizerProps<T> {
|
|
|
34
34
|
*/
|
|
35
35
|
ssrCount?: number;
|
|
36
36
|
/**
|
|
37
|
-
*
|
|
37
|
+
* Set true only when items are added to or removed from the start of the list, such as when older items are loaded in reverse infinite scrolling. In that case, the scroll position is maintained from the end of the list instead of the start.
|
|
38
|
+
*
|
|
39
|
+
* **Do not set true in any other case, as it can cause unexpected behavior.**
|
|
38
40
|
*/
|
|
39
41
|
shift?: boolean;
|
|
40
42
|
/**
|
package/lib/svelte/index.d.ts
CHANGED
|
@@ -10,3 +10,5 @@ export type { WindowVirtualizerProps, WindowVirtualizerHandle, } from './WindowV
|
|
|
10
10
|
export { default as VGrid } from './VGrid.svelte';
|
|
11
11
|
export type { VGridProps, VGridHandle } from './VGrid.type.js';
|
|
12
12
|
export type { GridSize, GridSpan } from '../core/index.js';
|
|
13
|
+
export { default as VMasonry } from './VMasonry.svelte';
|
|
14
|
+
export type { VMasonryProps, VMasonryHandle } from './VMasonry.type.js';
|
package/lib/svelte/index.js
CHANGED
|
@@ -2,4 +2,5 @@ import VList from "./VList.svelte";
|
|
|
2
2
|
import Virtualizer from "./Virtualizer.svelte";
|
|
3
3
|
import WindowVirtualizer from "./WindowVirtualizer.svelte";
|
|
4
4
|
import VGrid from "./VGrid.svelte";
|
|
5
|
-
|
|
5
|
+
import VMasonry from "./VMasonry.svelte";
|
|
6
|
+
export { VGrid, VList, VMasonry, Virtualizer, WindowVirtualizer };
|
package/lib/svelte/types.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { HTMLAttributes
|
|
2
|
-
export type ViewportComponentAttributes =
|
|
1
|
+
import { HTMLAttributes } from 'svelte/elements';
|
|
2
|
+
export type ViewportComponentAttributes = Omit<HTMLAttributes<HTMLDivElement>, "children" | "onscroll" | "onscrollend">;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { VNode, PublicProps } from 'vue';
|
|
2
|
+
import { ScrollToIndexOpts, CacheSnapshot } from '../core/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Methods of {@link VMasonry}.
|
|
5
|
+
*/
|
|
6
|
+
export interface VMasonryHandle {
|
|
7
|
+
/**
|
|
8
|
+
* Get current {@link CacheSnapshot}.
|
|
9
|
+
*/
|
|
10
|
+
readonly cache: CacheSnapshot;
|
|
11
|
+
/**
|
|
12
|
+
* Get current scrollTop.
|
|
13
|
+
*/
|
|
14
|
+
readonly scrollOffset: number;
|
|
15
|
+
/**
|
|
16
|
+
* Get current scrollHeight.
|
|
17
|
+
*/
|
|
18
|
+
readonly scrollSize: number;
|
|
19
|
+
/**
|
|
20
|
+
* Get current clientHeight.
|
|
21
|
+
*/
|
|
22
|
+
readonly viewportSize: number;
|
|
23
|
+
/**
|
|
24
|
+
* Get item offset from start.
|
|
25
|
+
* @param index index of item
|
|
26
|
+
*/
|
|
27
|
+
getItemOffset(index: number): number;
|
|
28
|
+
/**
|
|
29
|
+
* Get item size.
|
|
30
|
+
* @param index index of item
|
|
31
|
+
*/
|
|
32
|
+
getItemSize(index: number): number;
|
|
33
|
+
/**
|
|
34
|
+
* Scroll to the item specified by index.
|
|
35
|
+
* @param index index of item
|
|
36
|
+
* @param opts options
|
|
37
|
+
*/
|
|
38
|
+
scrollToIndex(index: number, opts?: ScrollToIndexOpts): void;
|
|
39
|
+
/**
|
|
40
|
+
* Scroll to the given offset.
|
|
41
|
+
* @param offset offset from start
|
|
42
|
+
*/
|
|
43
|
+
scrollTo(offset: number): void;
|
|
44
|
+
/**
|
|
45
|
+
* Scroll by the given offset.
|
|
46
|
+
* @param offset offset from current position
|
|
47
|
+
*/
|
|
48
|
+
scrollBy(offset: number): void;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Props of {@link VMasonry}.
|
|
52
|
+
*/
|
|
53
|
+
export interface VMasonryProps<T> extends PublicProps {
|
|
54
|
+
/**
|
|
55
|
+
* The data items rendered by this component.
|
|
56
|
+
*/
|
|
57
|
+
data: T[];
|
|
58
|
+
/**
|
|
59
|
+
* The number of lanes (columns) which items are laid out into. Each item is placed into the shortest lane in order. It must be an integer and the minimum value is 1.
|
|
60
|
+
*/
|
|
61
|
+
lanes: number;
|
|
62
|
+
/**
|
|
63
|
+
* The gap between the items and the lanes in pixels, which is not included in the sizes.
|
|
64
|
+
* @defaultValue 0
|
|
65
|
+
*/
|
|
66
|
+
gap?: number;
|
|
67
|
+
/**
|
|
68
|
+
* Item size hint for unmeasured items in pixels. It will help to reduce scroll jump when items are measured if used properly.
|
|
69
|
+
*
|
|
70
|
+
* - If not set, initial item sizes will be automatically estimated from measured sizes. This is recommended for most cases.
|
|
71
|
+
* - If set, you can opt out estimation and use the value as initial item size.
|
|
72
|
+
*/
|
|
73
|
+
itemSize?: number;
|
|
74
|
+
/**
|
|
75
|
+
* Extra item space in pixels to render before/after the viewport. The minimum value is 0. Lower value will give better performance but you can increase to avoid showing blank items in fast scrolling.
|
|
76
|
+
* @defaultValue 200
|
|
77
|
+
*/
|
|
78
|
+
bufferSize?: number;
|
|
79
|
+
/**
|
|
80
|
+
* You can restore cache by passing a {@link CacheSnapshot} on mount. This is useful when you want to restore scroll position after navigation. The snapshot can be obtained from {@link VMasonryHandle.cache}.
|
|
81
|
+
*
|
|
82
|
+
* **The length of items should be the same as when you take the snapshot, otherwise restoration may not work as expected.**
|
|
83
|
+
*/
|
|
84
|
+
cache?: CacheSnapshot;
|
|
85
|
+
/**
|
|
86
|
+
* Callback invoked whenever scroll offset changes.
|
|
87
|
+
* @param offset Current scrollTop.
|
|
88
|
+
*/
|
|
89
|
+
onScroll?: (offset: number) => void;
|
|
90
|
+
/**
|
|
91
|
+
* Callback invoked when scrolling stops.
|
|
92
|
+
*/
|
|
93
|
+
onScrollEnd?: () => void;
|
|
94
|
+
}
|
|
95
|
+
interface VMasonryInstance<T> extends VMasonryHandle {
|
|
96
|
+
$props: VMasonryProps<T>;
|
|
97
|
+
$slots: {
|
|
98
|
+
default: (arg: {
|
|
99
|
+
item: T;
|
|
100
|
+
index: number;
|
|
101
|
+
}) => VNode[];
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Virtualized masonry component. See {@link VMasonryProps} and {@link VMasonryHandle}.
|
|
106
|
+
*/
|
|
107
|
+
export declare const VMasonry: {
|
|
108
|
+
new <T>(props: VMasonryProps<T>): VMasonryInstance<T>;
|
|
109
|
+
};
|
|
110
|
+
export {};
|
package/lib/vue/Virtualizer.d.ts
CHANGED
|
@@ -22,7 +22,9 @@ export interface VirtualizerProps<T = unknown> extends PublicProps {
|
|
|
22
22
|
*/
|
|
23
23
|
itemSize?: number;
|
|
24
24
|
/**
|
|
25
|
-
*
|
|
25
|
+
* Set true only when items are added to or removed from the start of the list, such as when older items are loaded in reverse infinite scrolling. In that case, the scroll position is maintained from the end of the list instead of the start.
|
|
26
|
+
*
|
|
27
|
+
* **Do not set true in any other case, as it can cause unexpected behavior.**
|
|
26
28
|
*/
|
|
27
29
|
shift?: boolean;
|
|
28
30
|
/**
|
|
@@ -25,7 +25,9 @@ export interface WindowVirtualizerProps<T = unknown> extends PublicProps {
|
|
|
25
25
|
*/
|
|
26
26
|
ssrCount?: number;
|
|
27
27
|
/**
|
|
28
|
-
*
|
|
28
|
+
* Set true only when items are added to or removed from the start of the list, such as when older items are loaded in reverse infinite scrolling. In that case, the scroll position is maintained from the end of the list instead of the start.
|
|
29
|
+
*
|
|
30
|
+
* **Do not set true in any other case, as it can cause unexpected behavior.**
|
|
29
31
|
*/
|
|
30
32
|
shift?: boolean;
|
|
31
33
|
/**
|