|
28 | 28 | children
|
29 | 29 | } = $props();
|
30 | 30 |
|
31 |
| - let wrapper = $state(); |
32 |
| - let items = $state.raw([]); |
| 31 | + let wrapper = $state.raw(); |
| 32 | +
|
| 33 | + let styleCache = $state({}); |
| 34 | + let wrapperStyle = $state.raw(''); |
| 35 | + let innerStyle = $state.raw(''); |
33 | 36 |
|
34 |
| - const _state = new ListState(scrollOffset || (scrollToIndex != null && items.length && getOffsetForIndex(scrollToIndex)) || 0); |
| 37 | + let items = $state.raw([]); |
35 | 38 |
|
36 | 39 | const _props = new ListProps(
|
37 | 40 | scrollToIndex,
|
|
45 | 48 | stickyIndices
|
46 | 49 | );
|
47 | 50 |
|
48 |
| - let styleCache = $state({}); |
49 |
| - let wrapperStyle = $state(''); |
50 |
| - let innerStyle = $state(''); |
| 51 | + const _state = new ListState(scrollOffset || 0); |
51 | 52 |
|
52 | 53 | const sizeAndPositionManager = new SizeAndPositionManager({
|
53 | 54 | itemCount,
|
|
63 | 64 | };
|
64 | 65 | });
|
65 | 66 |
|
66 |
| - // Effect 1: Updates props from user provided vars |
| 67 | + // Effect 1: Update props from user provided props |
67 | 68 | $effect(() => {
|
68 | 69 | _props.listen(scrollToIndex, scrollToAlignment, scrollOffset, itemCount, itemSize, estimatedItemSize, height, width, stickyIndices);
|
69 | 70 |
|
70 | 71 | untrack(() => {
|
| 72 | + let doRecomputeSizes = false; |
| 73 | +
|
71 | 74 | if (_props.haveSizesChanged) {
|
72 | 75 | sizeAndPositionManager.updateConfig({
|
73 | 76 | itemSize,
|
74 | 77 | itemCount,
|
75 | 78 | estimatedItemSize: _props.estimatedItemSize
|
76 | 79 | });
|
77 |
| - recomputeSizes(); |
| 80 | + doRecomputeSizes = true; |
78 | 81 | }
|
79 |
| -
|
80 | 82 |
|
81 |
| - if (_props.hasScrollOffsetChanged) { |
| 83 | + if (_props.hasScrollOffsetChanged) |
82 | 84 | _state.listen(_props.scrollOffset, SCROLL_CHANGE_REASON.REQUESTED);
|
83 |
| - } else if (_props.hasScrollIndexChanged) { |
84 |
| - _state.listen(getOffsetForIndex(scrollToIndex, scrollToAlignment, itemCount), SCROLL_CHANGE_REASON.REQUESTED); |
85 |
| - } |
| 85 | + else if (_props.hasScrollIndexChanged) |
| 86 | + _state.listen(getOffsetForIndex(scrollToIndex, scrollToAlignment), SCROLL_CHANGE_REASON.REQUESTED); |
86 | 87 |
|
87 |
| - if (_props.haveDimsOrStickyIndicesChanged) { |
88 |
| - recomputeSizes(0); |
89 |
| - } |
| 88 | + if (_props.haveDimsOrStickyIndicesChanged || doRecomputeSizes) |
| 89 | + recomputeSizes(); |
90 | 90 |
|
91 | 91 | _props.update();
|
92 | 92 | });
|
93 | 93 | });
|
94 | 94 |
|
95 |
| - // Effect 2: Update state offset from props scrollOffset |
96 |
| - $effect(() => { |
97 |
| - _state.listen(_props.scrollOffset); |
98 |
| - }) |
99 |
| -
|
100 |
| - // Effect 3: Update UI from state |
| 95 | + // Effect 2: Update UI from state |
101 | 96 | $effect(() => {
|
102 | 97 | _state.offset;
|
103 | 98 |
|
104 | 99 | untrack(() => {
|
105 |
| - if (_state.doRefresh) { |
| 100 | + if (_state.doRefresh) |
106 | 101 | refresh();
|
107 |
| - } |
108 | 102 |
|
109 |
| - if (_state.doScrollToOffset) { |
| 103 | + if (_state.doScrollToOffset) |
110 | 104 | scrollTo(_state.offset);
|
111 |
| - } |
112 | 105 |
|
113 | 106 | _state.update();
|
114 | 107 | });
|
|
121 | 114 | overscanCount
|
122 | 115 | });
|
123 | 116 |
|
124 |
| - const updatedItems = []; |
| 117 | + const visibleItems = []; |
125 | 118 |
|
126 | 119 | const totalSize = sizeAndPositionManager.getTotalSize();
|
127 | 120 | const heightUnit = typeof height === 'number' ? 'px' : '';
|
128 | 121 | const widthUnit = typeof width === 'number' ? 'px' : '';
|
| 122 | + |
129 | 123 | if (scrollDirection === DIRECTION.VERTICAL) {
|
130 | 124 | wrapperStyle = `height:${height}${heightUnit};width:${width}${widthUnit};`;
|
131 | 125 | innerStyle = `flex-direction:column;height:${totalSize}px;`;
|
|
134 | 128 | innerStyle = `min-height:100%;width:${totalSize}px;`;
|
135 | 129 | }
|
136 | 130 |
|
137 |
| - const hasStickyIndices = stickyIndices != null && stickyIndices.length !== 0; |
| 131 | + const hasStickyIndices = Array.isArray(stickyIndices) && stickyIndices.length > 0; |
138 | 132 | if (hasStickyIndices) {
|
139 | 133 | for (let i = 0; i < stickyIndices.length; i++) {
|
140 | 134 | const index = stickyIndices[i];
|
141 |
| - updatedItems.push({ |
| 135 | + visibleItems.push({ |
142 | 136 | index,
|
143 | 137 | style: getStyle(index, true)
|
144 | 138 | });
|
|
147 | 141 |
|
148 | 142 | if (start !== undefined && stop !== undefined) {
|
149 | 143 | for (let index = start; index <= stop; index++) {
|
150 |
| - if (hasStickyIndices && stickyIndices.includes(index)) { |
| 144 | + if (hasStickyIndices && stickyIndices.includes(index)) |
151 | 145 | continue;
|
152 |
| - } |
153 | 146 |
|
154 |
| - updatedItems.push({ |
| 147 | + visibleItems.push({ |
155 | 148 | index,
|
156 | 149 | style: getStyle(index, false)
|
157 | 150 | });
|
|
160 | 153 | onListItemsUpdate({ start, end: stop });
|
161 | 154 | }
|
162 | 155 |
|
163 |
| - items = updatedItems; |
| 156 | + items = visibleItems; |
164 | 157 | };
|
165 | 158 |
|
166 | 159 | const scrollTo = (value) => {
|
167 |
| - if ('scroll' in wrapper) { |
| 160 | + if ('scroll' in wrapper) |
168 | 161 | wrapper.scroll({
|
169 | 162 | [SCROLL_PROP[scrollDirection]]: value,
|
170 | 163 | behavior: scrollToBehaviour
|
171 | 164 | });
|
172 |
| - } else { |
| 165 | + else |
173 | 166 | wrapper[SCROLL_PROP_LEGACY[scrollDirection]] = value;
|
174 |
| - } |
175 | 167 | };
|
176 | 168 |
|
177 |
| - export const recomputeSizes = (startIndex = 0) => { |
| 169 | + export const recomputeSizes = (startIndex = scrollToIndex) => { |
178 | 170 | styleCache = {};
|
179 |
| - sizeAndPositionManager.resetItem(startIndex); |
| 171 | + if (startIndex >= 0) |
| 172 | + sizeAndPositionManager.resetItem(startIndex); |
180 | 173 | refresh();
|
181 | 174 | };
|
182 | 175 |
|
183 |
| - const getOffsetForIndex = (index, align = scrollToAlignment, _itemCount = itemCount) => { |
184 |
| - if (index < 0 || index >= _itemCount) { |
| 176 | + const getOffsetForIndex = (index, align = scrollToAlignment) => { |
| 177 | + if (index < 0 || index >= itemCount) |
185 | 178 | index = 0;
|
186 |
| - } |
187 | 179 |
|
188 | 180 | return sizeAndPositionManager.getUpdatedOffsetForIndex({
|
189 | 181 | align,
|
|
219 | 211 | if (scrollDirection === DIRECTION.VERTICAL) {
|
220 | 212 | style = `left:0;width:100%;height:${size}px;`;
|
221 | 213 |
|
222 |
| - if (sticky) { |
| 214 | + if (sticky) |
223 | 215 | style += `position:sticky;flex-grow:0;z-index:1;top:0;margin-top:${offset}px;margin-bottom:${-(offset + size)}px;`;
|
224 |
| - } else { |
| 216 | + else |
225 | 217 | style += `position:absolute;top:${offset}px;`;
|
226 |
| - } |
227 | 218 | } else {
|
228 | 219 | style = `top:0;width:${size}px;`;
|
229 | 220 |
|
230 |
| - if (sticky) { |
| 221 | + if (sticky) |
231 | 222 | style += `position:sticky;z-index:1;left:0;margin-left:${offset}px;margin-right:${-(offset + size)}px;`;
|
232 |
| - } else { |
| 223 | + else |
233 | 224 | style += `position:absolute;height:100%;left:${offset}px;`;
|
234 |
| - } |
235 | 225 | }
|
236 | 226 |
|
237 |
| - return (styleCache[index] = style); |
| 227 | + styleCache[index] = style; |
| 228 | +
|
| 229 | + return styleCache[index]; |
238 | 230 | };
|
239 | 231 | </script>
|
240 | 232 |
|
|
0 commit comments