@fluid-topics/ft-infinite-scroll 1.1.59 → 1.1.60

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.
@@ -28,44 +28,47 @@ export declare class FtInfiniteScroll<T> extends FtLitElement implements FtInfin
28
28
  itemsContainer: HTMLDivElement;
29
29
  scrolledToTarget: boolean;
30
30
  private scrolling;
31
- private firstScrollableParent?;
32
31
  private renderApprovalTimeouts;
33
32
  private renderedIndexes;
33
+ private _scrollable?;
34
+ private initialOverflowAnchorValue?;
34
35
  get scrollable(): HTMLElement;
36
+ private set scrollable(value);
35
37
  protected render(): TemplateResult<1>;
36
38
  private renderItemContainer;
37
39
  private prepareRenderIfNeeded;
38
40
  private inRenderRange;
39
41
  private scrollDebouncer;
40
42
  private scrollDoneDebouncer;
41
- resetScroll(): void;
43
+ resetScroll(dispatchFindScrollableEvent?: boolean): void;
42
44
  private resolveScrollToIndex;
43
45
  private getItem;
44
46
  private scrollToTarget;
45
47
  private getOffset;
46
- private getLastKnownHeight;
47
48
  appendItems(...items: Array<T>): void;
48
49
  prependItems(...items: Array<T>): void;
49
- private onVisibilityChange;
50
- private intersectionObserver;
51
50
  connectedCallback(): void;
52
- private initIntersectionObserver;
53
- private triggerFindScrollableParent;
51
+ disconnectedCallback(): void;
54
52
  private findScrollableParent;
53
+ private elementCanScroll;
54
+ private onVisibilityChange;
55
+ private intersectionObserver;
56
+ private resetIntersectionObserver;
55
57
  private scrollingDebouncer;
56
58
  private scrollRestorationItem?;
57
59
  private scrollRestorationOffset?;
58
60
  private ignoreNextScrollEvent;
61
+ private lastScrollTop?;
59
62
  private scrollListener;
60
- private elementCanScroll;
61
- private onItemsResize;
62
- private restoreScroll;
63
63
  private searchFirstVisibleItem;
64
- private itemsResizeObserver;
65
- private scrollableResizeObserver;
64
+ private lastScrollHeight?;
65
+ private restoreScrollIfNeeded;
66
+ private _shouldRestoreScroll;
67
+ get shouldRestoreScroll(): boolean;
68
+ set shouldRestoreScroll(value: boolean);
69
+ private scrollAdjustment;
66
70
  private onMutation;
67
71
  private mutationObserver;
68
- disconnectedCallback(): void;
69
72
  protected update(props: PropertyValues<FtInfiniteScroll<T>>): void;
70
73
  protected updated(props: PropertyValues<FtInfiniteScroll<T>>): void;
71
74
  private lastNotOkVisibleItems?;
@@ -47,7 +47,7 @@ class FtInfiniteScroll extends FtLitElement {
47
47
  let visibleItems = new Set(this.visibleItems);
48
48
  let newItems = new Set();
49
49
  for (let item of items) {
50
- let index = +item.target.attributes.getNamedItem("data-item-index").value;
50
+ let index = +item.target.getAttribute("data-item-index");
51
51
  if (item.intersectionRect.height > 0) {
52
52
  visibleItems.add(index);
53
53
  newItems.add(index);
@@ -62,49 +62,74 @@ class FtInfiniteScroll extends FtLitElement {
62
62
  this.scrollingDebouncer = new Debouncer(50);
63
63
  this.ignoreNextScrollEvent = false;
64
64
  this.scrollListener = () => {
65
- if (!this.ignoreNextScrollEvent) {
65
+ var _a;
66
+ const ignoreThisScrollEvent = this.ignoreNextScrollEvent;
67
+ this.ignoreNextScrollEvent = false;
68
+ if (!ignoreThisScrollEvent) {
66
69
  this.scrolling = true;
67
70
  this.scrollingDebouncer.run(() => this.scrolling = false);
68
71
  }
69
- this.ignoreNextScrollEvent = false;
72
+ const currentScrollTop = this.scrollable.scrollTop;
73
+ const scrollDiff = currentScrollTop - ((_a = this.lastScrollTop) !== null && _a !== void 0 ? _a : 0);
74
+ this.lastScrollTop = currentScrollTop;
70
75
  if (this.scrolledToTarget) {
71
- const scrollRestorationElement = this.searchFirstVisibleItem(this.itemsContainer.children);
76
+ this.restoreScrollIfNeeded(ignoreThisScrollEvent ? 0 : scrollDiff);
77
+ const scrollRestorationElement = this.searchFirstVisibleItem(currentScrollTop, this.itemsContainer.children);
72
78
  this.scrollRestorationItem = scrollRestorationElement ? +scrollRestorationElement.getAttribute("data-item-index") : undefined;
73
- this.scrollRestorationOffset = this.scrollable.scrollTop - this.getOffset(scrollRestorationElement);
79
+ this.scrollRestorationOffset = currentScrollTop - this.getOffset(scrollRestorationElement);
74
80
  }
75
81
  };
76
- this.onItemsResize = (resizables) => {
77
- for (const resizable of resizables) {
78
- if (resizable.contentRect.height > 0) {
79
- resizable.target.setAttribute("data-last-known-height", "" + resizable.contentRect.height);
82
+ this.restoreScrollIfNeeded = (scrollCorrection = 0) => {
83
+ var _a;
84
+ const currentScrollHeight = this.scrollable.scrollHeight;
85
+ const heightDiff = currentScrollHeight - ((_a = this.lastScrollHeight) !== null && _a !== void 0 ? _a : currentScrollHeight);
86
+ this.lastScrollHeight = currentScrollHeight;
87
+ if (heightDiff !== 0 && this.scrollRestorationItem != null && this.scrollRestorationOffset != null && this.scrolledToTarget) {
88
+ const scrollRestorationElement = this.getItem(this.scrollRestorationItem);
89
+ const scrollTarget = this.getOffset(scrollRestorationElement);
90
+ const offset = minmax(this.scrollRestorationItem === 0 ? -scrollTarget : 1, this.scrollRestorationOffset, scrollRestorationElement.clientHeight - 1);
91
+ const scrollDiff = scrollTarget + offset + scrollCorrection - this.scrollable.scrollTop;
92
+ if (Math.abs(heightDiff - scrollDiff) < 4 || Math.abs(scrollDiff) > 5) {
93
+ this.ignoreNextScrollEvent = true;
94
+ this.scrollable.scrollTop += scrollDiff;
80
95
  }
81
96
  }
82
- this.restoreScroll();
83
97
  };
84
- this.restoreScroll = () => {
85
- if (this.scrollRestorationItem != null && this.scrollRestorationOffset != null && this.scrolledToTarget) {
86
- const scrollRestorationElement = this.getItem(this.scrollRestorationItem);
87
- const scrollTarget = this.getOffset(scrollRestorationElement);
88
- const offset = minmax(this.scrollRestorationItem === 0 ? -scrollTarget : 0, this.scrollRestorationOffset, this.getLastKnownHeight(scrollRestorationElement) + 1);
89
- this.ignoreNextScrollEvent = true;
90
- this.scrollable.scrollTop = scrollTarget + offset;
98
+ this._shouldRestoreScroll = false;
99
+ this.scrollAdjustment = () => {
100
+ this.restoreScrollIfNeeded();
101
+ if (this.shouldRestoreScroll) {
102
+ requestAnimationFrame(this.scrollAdjustment);
91
103
  }
92
104
  };
93
- this.itemsResizeObserver = new ResizeObserver(this.onItemsResize);
94
- this.scrollableResizeObserver = new ResizeObserver(this.restoreScroll);
95
105
  this.onMutation = () => {
96
- [...this.itemsContainer.children].forEach((item) => {
106
+ for (let item of this.itemsContainer.children) {
97
107
  this.intersectionObserver.observe(item);
98
- this.itemsResizeObserver.observe(item);
99
- });
100
- this.scrollableResizeObserver.observe(this.scrollable);
108
+ }
101
109
  };
102
110
  this.mutationObserver = new MutationObserver(this.onMutation);
103
111
  this.resetVisibleItemsDebouncer = new Debouncer(10);
104
112
  }
105
113
  get scrollable() {
106
114
  var _a;
107
- return (_a = (this.internalScroll ? this.internalScrollable : this.firstScrollableParent)) !== null && _a !== void 0 ? _a : document.body;
115
+ return (_a = this._scrollable) !== null && _a !== void 0 ? _a : document.body;
116
+ }
117
+ set scrollable(newScrollable) {
118
+ var _a, _b, _c, _d;
119
+ if (this._scrollable !== newScrollable) {
120
+ (_a = this._scrollable) === null || _a === void 0 ? void 0 : _a.removeEventListener("scroll", this.scrollListener);
121
+ if (this._scrollable && this.initialOverflowAnchorValue) {
122
+ this.scrollable.style.overflowAnchor = this.initialOverflowAnchorValue;
123
+ }
124
+ this._scrollable = newScrollable;
125
+ (_b = this._scrollable) === null || _b === void 0 ? void 0 : _b.addEventListener("scroll", this.scrollListener);
126
+ this.lastScrollTop = (_c = this._scrollable) === null || _c === void 0 ? void 0 : _c.scrollTop;
127
+ this.lastScrollHeight = (_d = this._scrollable) === null || _d === void 0 ? void 0 : _d.scrollHeight;
128
+ if (this._scrollable) {
129
+ this.initialOverflowAnchorValue = getComputedStyle(this._scrollable).overflowAnchor;
130
+ this._scrollable.style.overflowAnchor = "none";
131
+ }
132
+ }
108
133
  }
109
134
  render() {
110
135
  return html `
@@ -148,17 +173,22 @@ class FtInfiniteScroll extends FtLitElement {
148
173
  inRenderRange(index) {
149
174
  return index >= this.visibleItems[0] - this.renderBeforeFirst && index <= last(this.visibleItems) + this.renderAfterLast;
150
175
  }
151
- resetScroll() {
152
- this.triggerFindScrollableParent();
176
+ resetScroll(dispatchFindScrollableEvent = true) {
177
+ var _a;
178
+ this.shouldRestoreScroll = false;
153
179
  this.intersectionObserver.disconnect();
154
- this.itemsResizeObserver.disconnect();
155
- this.scrollableResizeObserver.disconnect();
156
180
  this.visibleItems = [];
181
+ this.scrolledToTarget = false;
182
+ if (this.internalScroll && this.scrollable !== this.internalScrollable) {
183
+ this.scrollable = this.internalScrollable;
184
+ }
185
+ else if (!this.internalScroll && dispatchFindScrollableEvent) {
186
+ (_a = this.itemsContainer) === null || _a === void 0 ? void 0 : _a.dispatchEvent(new Event("find-scrollable-parent", { composed: true }));
187
+ return;
188
+ }
157
189
  const targetIndex = this.resolveScrollToIndex();
158
190
  this.renderedIndexes.add(targetIndex);
159
- this.scrolledToTarget = false;
160
191
  this.scrollToTarget(targetIndex);
161
- this.onMutation();
162
192
  this.scrollDoneDebouncer.run(() => {
163
193
  if (this.ensureScrollToTarget && targetIndex >= 0) {
164
194
  this.scrollDebouncer.run(() => {
@@ -167,7 +197,10 @@ class FtInfiniteScroll extends FtLitElement {
167
197
  }
168
198
  }, 500);
169
199
  }
200
+ this.scrollToTarget(targetIndex);
170
201
  this.scrolledToTarget = true;
202
+ this.shouldRestoreScroll = true;
203
+ this.resetIntersectionObserver();
171
204
  });
172
205
  }
173
206
  resolveScrollToIndex() {
@@ -200,10 +233,6 @@ class FtInfiniteScroll extends FtLitElement {
200
233
  }
201
234
  return offset + ((_a = el === null || el === void 0 ? void 0 : el.offsetTop) !== null && _a !== void 0 ? _a : 0) - this.scrollable.offsetTop;
202
235
  }
203
- getLastKnownHeight(target) {
204
- var _a;
205
- return +((_a = target === null || target === void 0 ? void 0 : target.getAttribute("data-last-known-height")) !== null && _a !== void 0 ? _a : 1000); // default height is 1000px
206
- }
207
236
  appendItems(...items) {
208
237
  this.items = [...this.items, ...items];
209
238
  }
@@ -213,24 +242,17 @@ class FtInfiniteScroll extends FtLitElement {
213
242
  connectedCallback() {
214
243
  super.connectedCallback();
215
244
  setTimeout(() => {
216
- this.triggerFindScrollableParent();
217
- this.initIntersectionObserver();
218
245
  this.mutationObserver.disconnect();
219
246
  this.mutationObserver.observe(this.itemsContainer, { childList: true });
220
247
  this.resetScroll();
221
248
  }, 0);
222
249
  }
223
- initIntersectionObserver() {
250
+ disconnectedCallback() {
251
+ super.disconnectedCallback();
252
+ this.scrollable = undefined;
224
253
  this.intersectionObserver.disconnect();
225
- this.intersectionObserver = new IntersectionObserver(this.onVisibilityChange, {
226
- root: this.scrollable,
227
- rootMargin: "-8px",
228
- threshold: [0, 0.01, 0.1, 1]
229
- });
230
- }
231
- triggerFindScrollableParent() {
232
- var _a;
233
- (_a = this.itemsContainer) === null || _a === void 0 ? void 0 : _a.dispatchEvent(new Event("find-scrollable-parent", { composed: true }));
254
+ this.mutationObserver.disconnect();
255
+ this.shouldRestoreScroll = false;
234
256
  }
235
257
  findScrollableParent(e) {
236
258
  var _a;
@@ -244,18 +266,12 @@ class FtInfiniteScroll extends FtLitElement {
244
266
  scrollable = element;
245
267
  break;
246
268
  }
247
- else if (mayScroll) {
269
+ else if (mayScroll && maybeScrollable == null) {
248
270
  maybeScrollable = element;
249
271
  }
250
272
  }
251
- let newScrollable = scrollable || maybeScrollable;
252
- if (newScrollable !== this.firstScrollableParent) {
253
- (_a = this.firstScrollableParent) === null || _a === void 0 ? void 0 : _a.removeEventListener("scroll", this.scrollListener);
254
- newScrollable === null || newScrollable === void 0 ? void 0 : newScrollable.addEventListener("scroll", this.scrollListener);
255
- this.firstScrollableParent = newScrollable;
256
- this.initIntersectionObserver();
257
- this.resetScroll();
258
- }
273
+ this.scrollable = (_a = scrollable !== null && scrollable !== void 0 ? scrollable : maybeScrollable) !== null && _a !== void 0 ? _a : document.body;
274
+ this.resetScroll(false);
259
275
  }
260
276
  elementCanScroll(element) {
261
277
  try {
@@ -265,7 +281,16 @@ class FtInfiniteScroll extends FtLitElement {
265
281
  return false;
266
282
  }
267
283
  }
268
- searchFirstVisibleItem(items, from, to) {
284
+ resetIntersectionObserver() {
285
+ this.intersectionObserver.disconnect();
286
+ this.intersectionObserver = new IntersectionObserver(this.onVisibilityChange, {
287
+ root: this.scrollable,
288
+ rootMargin: "-8px",
289
+ threshold: [0, 0.01, 0.1, 1]
290
+ });
291
+ this.onMutation();
292
+ }
293
+ searchFirstVisibleItem(currentScrollTop, items, from, to) {
269
294
  from = from !== null && from !== void 0 ? from : 0;
270
295
  to = to !== null && to !== void 0 ? to : (items.length - 1);
271
296
  if (to <= from) {
@@ -273,20 +298,24 @@ class FtInfiniteScroll extends FtLitElement {
273
298
  }
274
299
  const middle = Math.floor((to - from) / 2) + from;
275
300
  const middleItem = items[middle];
276
- if (this.getOffset(middleItem) > this.scrollable.scrollTop) {
277
- return this.searchFirstVisibleItem(items, from, middle - 1);
301
+ let middleItemOffset = this.getOffset(middleItem);
302
+ if (middleItemOffset > currentScrollTop) {
303
+ return this.searchFirstVisibleItem(currentScrollTop, items, from, middle - 1);
278
304
  }
279
- else if (this.getOffset(middleItem) + this.getLastKnownHeight(middleItem) < this.scrollable.scrollTop) {
280
- return this.searchFirstVisibleItem(items, middle + 1, to);
305
+ else if (middleItemOffset + middleItem.clientHeight < currentScrollTop) {
306
+ return this.searchFirstVisibleItem(currentScrollTop, items, middle + 1, to);
281
307
  }
282
308
  return middleItem;
283
309
  }
284
- disconnectedCallback() {
285
- super.disconnectedCallback();
286
- this.intersectionObserver.disconnect();
287
- this.itemsResizeObserver.disconnect();
288
- this.scrollableResizeObserver.disconnect();
289
- this.mutationObserver.disconnect();
310
+ get shouldRestoreScroll() {
311
+ return this._shouldRestoreScroll;
312
+ }
313
+ set shouldRestoreScroll(value) {
314
+ let switchedOn = value && !this._shouldRestoreScroll;
315
+ this._shouldRestoreScroll = value;
316
+ if (switchedOn) {
317
+ requestAnimationFrame(this.scrollAdjustment);
318
+ }
290
319
  }
291
320
  update(props) {
292
321
  super.update(props);
@@ -294,7 +323,8 @@ class FtInfiniteScroll extends FtLitElement {
294
323
  this.renderedIndexes = new Set();
295
324
  this.renderApprovalTimeouts = [];
296
325
  }
297
- if ((props.has("scrollToItem") || props.has("scrollToIndex")) && (this.scrollToItem != null || this.scrollToIndex != null)) {
326
+ let scrollTargetUpdated = (props.has("scrollToItem") || props.has("scrollToIndex")) && (this.scrollToItem != null || this.scrollToIndex != null);
327
+ if (scrollTargetUpdated || props.has("internalScroll")) {
298
328
  this.resetScroll();
299
329
  }
300
330
  }
@@ -317,8 +347,7 @@ class FtInfiniteScroll extends FtLitElement {
317
347
  this.resetVisibleItemsDebouncer.run(() => {
318
348
  this.lastNotOkVisibleItems = [...this.visibleItems];
319
349
  this.visibleItems = [];
320
- this.initIntersectionObserver();
321
- this.onMutation();
350
+ this.resetIntersectionObserver();
322
351
  });
323
352
  }
324
353
  }
@@ -1,6 +1,6 @@
1
- !function(t,i,e,s,h,n){const l={padding:i.FtCssVariableFactory.create("--ft-infinite-scroll-padding","","SIZE","0"),itemsGap:i.FtCssVariableFactory.create("--ft-infinite-scroll-items-gap","","SIZE","4px"),itemContainerMinHeight:i.FtCssVariableFactory.create("--ft-infinite-scroll-item-container-min-height","","SIZE",".1px")},r=e.css`
1
+ !function(t,i,s,e,h,l){const n={padding:i.FtCssVariableFactory.create("--ft-infinite-scroll-padding","","SIZE","0"),itemsGap:i.FtCssVariableFactory.create("--ft-infinite-scroll-items-gap","","SIZE","4px"),itemContainerMinHeight:i.FtCssVariableFactory.create("--ft-infinite-scroll-item-container-min-height","","SIZE",".1px")},r=s.css`
2
2
  .items-container {
3
- padding: ${l.padding};
3
+ padding: ${n.padding};
4
4
  outline: none;
5
5
  }
6
6
 
@@ -17,7 +17,7 @@
17
17
  By adding this gap we ensure that the previous item will be fully hidden
18
18
  and even if its size changes, it will not impact the scroll offset
19
19
  */
20
- margin-top: ${l.itemsGap};
20
+ margin-top: ${n.itemsGap};
21
21
  }
22
22
 
23
23
  .item-container:not(.rendered) {
@@ -26,18 +26,18 @@
26
26
 
27
27
  .item-container.rendered {
28
28
  display: flow-root;
29
- min-height: ${l.itemContainerMinHeight};
29
+ min-height: ${n.itemContainerMinHeight};
30
30
  }
31
- `;var o=function(t,i,e,s){for(var h,n=arguments.length,l=n<3?i:null===s?s=Object.getOwnPropertyDescriptor(i,e):s,r=t.length-1;r>=0;r--)(h=t[r])&&(l=(n<3?h(l):n>3?h(i,e,l):h(i,e))||l);return n>3&&l&&Object.defineProperty(i,e,l),l};class a extends CustomEvent{constructor(t,i){super("visible-items-change",{detail:{visibleIndexes:t,visibleItems:i}})}}class d extends Event{constructor(){super("scrolled-to-target")}}class c extends i.FtLitElement{constructor(){super(...arguments),this.items=[],this.renderItem=()=>e.html``,this.getItemKey=(t,i)=>`${i} - ${JSON.stringify(t)}`,this.internalScroll=!1,this.renderBeforeFirst=1,this.renderAfterLast=1,this.ensureScrollToTarget=!1,this.visibleItems=[],this.scrolledToTarget=!1,this.scrolling=!1,this.renderApprovalTimeouts=[],this.renderedIndexes=new Set,this.scrollDebouncer=new i.Debouncer(5),this.scrollDoneDebouncer=new i.Debouncer(10),this.onVisibilityChange=t=>{let i=new Set(this.visibleItems),e=new Set;for(let s of t){let t=+s.target.attributes.getNamedItem("data-item-index").value;s.intersectionRect.height>0?(i.add(t),e.add(t)):e.has(t)||i.delete(t)}this.visibleItems=[...i].sort(((t,i)=>t-i))},this.intersectionObserver=new IntersectionObserver(this.onVisibilityChange),this.scrollingDebouncer=new i.Debouncer(50),this.ignoreNextScrollEvent=!1,this.scrollListener=()=>{if(this.ignoreNextScrollEvent||(this.scrolling=!0,this.scrollingDebouncer.run((()=>this.scrolling=!1))),this.ignoreNextScrollEvent=!1,this.scrolledToTarget){const t=this.searchFirstVisibleItem(this.itemsContainer.children);this.scrollRestorationItem=t?+t.getAttribute("data-item-index"):void 0,this.scrollRestorationOffset=this.scrollable.scrollTop-this.getOffset(t)}},this.onItemsResize=t=>{for(const i of t)i.contentRect.height>0&&i.target.setAttribute("data-last-known-height",""+i.contentRect.height);this.restoreScroll()},this.restoreScroll=()=>{if(null!=this.scrollRestorationItem&&null!=this.scrollRestorationOffset&&this.scrolledToTarget){const t=this.getItem(this.scrollRestorationItem),e=this.getOffset(t),s=i.minmax(0===this.scrollRestorationItem?-e:0,this.scrollRestorationOffset,this.getLastKnownHeight(t)+1);this.ignoreNextScrollEvent=!0,this.scrollable.scrollTop=e+s}},this.itemsResizeObserver=new ResizeObserver(this.onItemsResize),this.scrollableResizeObserver=new ResizeObserver(this.restoreScroll),this.onMutation=()=>{[...this.itemsContainer.children].forEach((t=>{this.intersectionObserver.observe(t),this.itemsResizeObserver.observe(t)})),this.scrollableResizeObserver.observe(this.scrollable)},this.mutationObserver=new MutationObserver(this.onMutation),this.resetVisibleItemsDebouncer=new i.Debouncer(10)}get scrollable(){var t;return null!==(t=this.internalScroll?this.internalScrollable:this.firstScrollableParent)&&void 0!==t?t:document.body}render(){return e.html`
31
+ `;var o=function(t,i,s,e){for(var h,l=arguments.length,n=l<3?i:null===e?e=Object.getOwnPropertyDescriptor(i,s):e,r=t.length-1;r>=0;r--)(h=t[r])&&(n=(l<3?h(n):l>3?h(i,s,n):h(i,s))||n);return l>3&&n&&Object.defineProperty(i,s,n),n};class a extends CustomEvent{constructor(t,i){super("visible-items-change",{detail:{visibleIndexes:t,visibleItems:i}})}}class d extends Event{constructor(){super("scrolled-to-target")}}class c extends i.FtLitElement{constructor(){super(...arguments),this.items=[],this.renderItem=()=>s.html``,this.getItemKey=(t,i)=>`${i} - ${JSON.stringify(t)}`,this.internalScroll=!1,this.renderBeforeFirst=1,this.renderAfterLast=1,this.ensureScrollToTarget=!1,this.visibleItems=[],this.scrolledToTarget=!1,this.scrolling=!1,this.renderApprovalTimeouts=[],this.renderedIndexes=new Set,this.scrollDebouncer=new i.Debouncer(5),this.scrollDoneDebouncer=new i.Debouncer(10),this.onVisibilityChange=t=>{let i=new Set(this.visibleItems),s=new Set;for(let e of t){let t=+e.target.getAttribute("data-item-index");e.intersectionRect.height>0?(i.add(t),s.add(t)):s.has(t)||i.delete(t)}this.visibleItems=[...i].sort(((t,i)=>t-i))},this.intersectionObserver=new IntersectionObserver(this.onVisibilityChange),this.scrollingDebouncer=new i.Debouncer(50),this.ignoreNextScrollEvent=!1,this.scrollListener=()=>{var t;const i=this.ignoreNextScrollEvent;this.ignoreNextScrollEvent=!1,i||(this.scrolling=!0,this.scrollingDebouncer.run((()=>this.scrolling=!1)));const s=this.scrollable.scrollTop,e=s-(null!==(t=this.lastScrollTop)&&void 0!==t?t:0);if(this.lastScrollTop=s,this.scrolledToTarget){this.restoreScrollIfNeeded(i?0:e);const t=this.searchFirstVisibleItem(s,this.itemsContainer.children);this.scrollRestorationItem=t?+t.getAttribute("data-item-index"):void 0,this.scrollRestorationOffset=s-this.getOffset(t)}},this.restoreScrollIfNeeded=(t=0)=>{var s;const e=this.scrollable.scrollHeight,h=e-(null!==(s=this.lastScrollHeight)&&void 0!==s?s:e);if(this.lastScrollHeight=e,0!==h&&null!=this.scrollRestorationItem&&null!=this.scrollRestorationOffset&&this.scrolledToTarget){const s=this.getItem(this.scrollRestorationItem),e=this.getOffset(s),l=e+i.minmax(0===this.scrollRestorationItem?-e:1,this.scrollRestorationOffset,s.clientHeight-1)+t-this.scrollable.scrollTop;(Math.abs(h-l)<4||Math.abs(l)>5)&&(this.ignoreNextScrollEvent=!0,this.scrollable.scrollTop+=l)}},this._shouldRestoreScroll=!1,this.scrollAdjustment=()=>{this.restoreScrollIfNeeded(),this.shouldRestoreScroll&&requestAnimationFrame(this.scrollAdjustment)},this.onMutation=()=>{for(let t of this.itemsContainer.children)this.intersectionObserver.observe(t)},this.mutationObserver=new MutationObserver(this.onMutation),this.resetVisibleItemsDebouncer=new i.Debouncer(10)}get scrollable(){var t;return null!==(t=this._scrollable)&&void 0!==t?t:document.body}set scrollable(t){var i,s,e,h;this._scrollable!==t&&(null===(i=this._scrollable)||void 0===i||i.removeEventListener("scroll",this.scrollListener),this._scrollable&&this.initialOverflowAnchorValue&&(this.scrollable.style.overflowAnchor=this.initialOverflowAnchorValue),this._scrollable=t,null===(s=this._scrollable)||void 0===s||s.addEventListener("scroll",this.scrollListener),this.lastScrollTop=null===(e=this._scrollable)||void 0===e?void 0:e.scrollTop,this.lastScrollHeight=null===(h=this._scrollable)||void 0===h?void 0:h.scrollHeight,this._scrollable&&(this.initialOverflowAnchorValue=getComputedStyle(this._scrollable).overflowAnchor,this._scrollable.style.overflowAnchor="none"))}render(){return s.html`
32
32
  <div class="items-container ${this.internalScroll?"scrollable":""}"
33
33
  tabindex="-1"
34
34
  @find-scrollable-parent=${this.findScrollableParent}>
35
35
  ${h.repeat(this.items,((t,i)=>this.getItemKey(t,i)),((t,i)=>this.renderItemContainer(t,i)))}
36
36
  </div>
37
- `}renderItemContainer(t,i){this.prepareRenderIfNeeded(i);const s=this.scrolledToTarget&&this.visibleItems.includes(i),h=this.renderedIndexes.has(i);return e.html`
37
+ `}renderItemContainer(t,i){this.prepareRenderIfNeeded(i);const e=this.scrolledToTarget&&this.visibleItems.includes(i),h=this.renderedIndexes.has(i);return s.html`
38
38
  <div id="item-${i}"
39
- class="item-container ${h?"rendered":""} ${s?"visible":""}"
39
+ class="item-container ${h?"rendered":""} ${e?"visible":""}"
40
40
  data-item-index="${i}">
41
- ${h?(()=>{const e=this.renderItem(t,i);return"string"==typeof e?n.unsafeHTML(e):e})():e.nothing}
41
+ ${h?(()=>{const s=this.renderItem(t,i);return"string"==typeof s?l.unsafeHTML(s):s})():s.nothing}
42
42
  </div>
43
- `}prepareRenderIfNeeded(t){const i=null!=this.renderApprovalTimeouts[t];this.inRenderRange(t)&&!i&&(this.renderApprovalTimeouts[t]=setTimeout((()=>{this.inRenderRange(t)?this.renderedIndexes.add(t):this.renderApprovalTimeouts[t]=void 0,this.requestUpdate()}),300))}inRenderRange(t){return t>=this.visibleItems[0]-this.renderBeforeFirst&&t<=(null!=(i=this.visibleItems)?i:[])[(null!=i?i:[]).length-1]+this.renderAfterLast;var i}resetScroll(){this.triggerFindScrollableParent(),this.intersectionObserver.disconnect(),this.itemsResizeObserver.disconnect(),this.scrollableResizeObserver.disconnect(),this.visibleItems=[];const t=this.resolveScrollToIndex();this.renderedIndexes.add(t),this.scrolledToTarget=!1,this.scrollToTarget(t),this.onMutation(),this.scrollDoneDebouncer.run((()=>{this.ensureScrollToTarget&&t>=0&&this.scrollDebouncer.run((()=>{Math.abs(this.scrollable.scrollTop-this.getOffset(t))>5&&this.scrollToTarget(t)}),500),this.scrolledToTarget=!0}))}resolveScrollToIndex(){var t;let i=null!==(t=this.scrollToIndex)&&void 0!==t?t:this.scrollToItem?this.items.indexOf(this.scrollToItem):-1;return i>=this.items.length?-1:i}getItem(t){var i,e,s;return null!==(e=null===(i=this.shadowRoot)||void 0===i?void 0:i.querySelector(`#item-${t}`))&&void 0!==e?e:null===(s=this.shadowRoot)||void 0===s?void 0:s.querySelector("#item-0")}scrollToTarget(t){t<=0?(this.scrollable.scrollTop=0,this.scrollRestorationOffset=-this.getOffset(t)):(this.scrollable.scrollTop=this.getOffset(t),this.scrollRestorationOffset=0),this.scrollRestorationItem=t>=0?t:void 0}getOffset(t){var i;let e=0,s="number"==typeof t?this.getItem(t):t;for(;s&&s.offsetParent!==this.scrollable.offsetParent;)e+=s.offsetTop,s=s.offsetParent;return e+(null!==(i=null==s?void 0:s.offsetTop)&&void 0!==i?i:0)-this.scrollable.offsetTop}getLastKnownHeight(t){var i;return+(null!==(i=null==t?void 0:t.getAttribute("data-last-known-height"))&&void 0!==i?i:1e3)}appendItems(...t){this.items=[...this.items,...t]}prependItems(...t){this.items=[...t,...this.items]}connectedCallback(){super.connectedCallback(),setTimeout((()=>{this.triggerFindScrollableParent(),this.initIntersectionObserver(),this.mutationObserver.disconnect(),this.mutationObserver.observe(this.itemsContainer,{childList:!0}),this.resetScroll()}),0)}initIntersectionObserver(){this.intersectionObserver.disconnect(),this.intersectionObserver=new IntersectionObserver(this.onVisibilityChange,{root:this.scrollable,rootMargin:"-8px",threshold:[0,.01,.1,1]})}triggerFindScrollableParent(){var t;null===(t=this.itemsContainer)||void 0===t||t.dispatchEvent(new Event("find-scrollable-parent",{composed:!0}))}findScrollableParent(t){var i;let e,s;t.stopPropagation();for(let i of t.composedPath()){const t=i,h=this.elementCanScroll(t);if(h&&t.clientHeight&&t.clientHeight<t.scrollHeight){e=t;break}h&&(s=t)}let h=e||s;h!==this.firstScrollableParent&&(null===(i=this.firstScrollableParent)||void 0===i||i.removeEventListener("scroll",this.scrollListener),null==h||h.addEventListener("scroll",this.scrollListener),this.firstScrollableParent=h,this.initIntersectionObserver(),this.resetScroll())}elementCanScroll(t){try{return["auto","scroll"].includes(getComputedStyle(t).overflowY)}catch(t){return!1}}searchFirstVisibleItem(t,i,e){if(i=null!=i?i:0,(e=null!=e?e:t.length-1)<=i)return t[i];const s=Math.floor((e-i)/2)+i,h=t[s];return this.getOffset(h)>this.scrollable.scrollTop?this.searchFirstVisibleItem(t,i,s-1):this.getOffset(h)+this.getLastKnownHeight(h)<this.scrollable.scrollTop?this.searchFirstVisibleItem(t,s+1,e):h}disconnectedCallback(){super.disconnectedCallback(),this.intersectionObserver.disconnect(),this.itemsResizeObserver.disconnect(),this.scrollableResizeObserver.disconnect(),this.mutationObserver.disconnect()}update(t){super.update(t),t.has("items")&&(this.renderedIndexes=new Set,this.renderApprovalTimeouts=[]),!t.has("scrollToItem")&&!t.has("scrollToIndex")||null==this.scrollToItem&&null==this.scrollToIndex||this.resetScroll()}updated(t){super.updated(t),(t.has("visibleItems")||t.has("items"))&&this.onVisibleItemsChange(),t.has("scrolledToTarget")&&this.scrolledToTarget&&(null!=this.scrollToItem||null!=this.scrollToIndex)&&this.dispatchEvent(new d)}onVisibleItemsChange(){this.visibleItems.every(((t,i)=>null==this.visibleItems[i+1]||t+1===this.visibleItems[i+1]))||i.deepEqual(this.visibleItems,this.lastNotOkVisibleItems)?(this.resetVisibleItemsDebouncer.cancel(),this.dispatchVisibleItemsEvent()):this.resetVisibleItemsDebouncer.run((()=>{this.lastNotOkVisibleItems=[...this.visibleItems],this.visibleItems=[],this.initIntersectionObserver(),this.onMutation()}))}dispatchVisibleItemsEvent(){var t;null===(t=this.cancelableDispatchEvent)||void 0===t||t.cancel(),this.cancelableDispatchEvent=i.cancelable(i.waitUntil((()=>!this.scrolling))),this.cancelableDispatchEvent.then((()=>this.dispatchEvent(new a(this.visibleItems,this.visibleItems.map((t=>this.items[t])))))).catch((()=>null))}}c.styles=r,o([s.property({type:Array})],c.prototype,"items",void 0),o([s.property({attribute:!1})],c.prototype,"renderItem",void 0),o([s.property({attribute:!1})],c.prototype,"getItemKey",void 0),o([s.property({type:Object})],c.prototype,"scrollToItem",void 0),o([s.property({type:Number})],c.prototype,"scrollToIndex",void 0),o([s.property({type:Boolean})],c.prototype,"internalScroll",void 0),o([s.property({type:Number})],c.prototype,"renderBeforeFirst",void 0),o([s.property({type:Number})],c.prototype,"renderAfterLast",void 0),o([s.property({type:Boolean})],c.prototype,"ensureScrollToTarget",void 0),o([s.state({hasChanged:(t,i)=>null!=t&&null==i||t.length!==i.length||t[0]!==i[0]})],c.prototype,"visibleItems",void 0),o([s.query(".scrollable")],c.prototype,"internalScrollable",void 0),o([s.query(".items-container")],c.prototype,"itemsContainer",void 0),o([s.state()],c.prototype,"scrolledToTarget",void 0),o([s.state()],c.prototype,"scrolling",void 0),o([s.state({hasChanged:(t,e)=>!i.deepEqual(t,e)})],c.prototype,"renderedIndexes",void 0),i.customElement("ft-infinite-scroll")(c),t.FtInfiniteScroll=c,t.FtInfiniteScrollCssVariables=l,t.ScrolledToTargetEvent=d,t.VisibleItemsChangeEvent=a,t.styles=r}({},ftGlobals.wcUtils,ftGlobals.lit,ftGlobals.litDecorators,ftGlobals.litRepeat,ftGlobals.litUnsafeHTML);
43
+ `}prepareRenderIfNeeded(t){const i=null!=this.renderApprovalTimeouts[t];this.inRenderRange(t)&&!i&&(this.renderApprovalTimeouts[t]=setTimeout((()=>{this.inRenderRange(t)?this.renderedIndexes.add(t):this.renderApprovalTimeouts[t]=void 0,this.requestUpdate()}),300))}inRenderRange(t){return t>=this.visibleItems[0]-this.renderBeforeFirst&&t<=(null!=(i=this.visibleItems)?i:[])[(null!=i?i:[]).length-1]+this.renderAfterLast;var i}resetScroll(t=!0){var i;if(this.shouldRestoreScroll=!1,this.intersectionObserver.disconnect(),this.visibleItems=[],this.scrolledToTarget=!1,this.internalScroll&&this.scrollable!==this.internalScrollable)this.scrollable=this.internalScrollable;else if(!this.internalScroll&&t)return void(null===(i=this.itemsContainer)||void 0===i||i.dispatchEvent(new Event("find-scrollable-parent",{composed:!0})));const s=this.resolveScrollToIndex();this.renderedIndexes.add(s),this.scrollToTarget(s),this.scrollDoneDebouncer.run((()=>{this.ensureScrollToTarget&&s>=0&&this.scrollDebouncer.run((()=>{Math.abs(this.scrollable.scrollTop-this.getOffset(s))>5&&this.scrollToTarget(s)}),500),this.scrollToTarget(s),this.scrolledToTarget=!0,this.shouldRestoreScroll=!0,this.resetIntersectionObserver()}))}resolveScrollToIndex(){var t;let i=null!==(t=this.scrollToIndex)&&void 0!==t?t:this.scrollToItem?this.items.indexOf(this.scrollToItem):-1;return i>=this.items.length?-1:i}getItem(t){var i,s,e;return null!==(s=null===(i=this.shadowRoot)||void 0===i?void 0:i.querySelector(`#item-${t}`))&&void 0!==s?s:null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector("#item-0")}scrollToTarget(t){t<=0?(this.scrollable.scrollTop=0,this.scrollRestorationOffset=-this.getOffset(t)):(this.scrollable.scrollTop=this.getOffset(t),this.scrollRestorationOffset=0),this.scrollRestorationItem=t>=0?t:void 0}getOffset(t){var i;let s=0,e="number"==typeof t?this.getItem(t):t;for(;e&&e.offsetParent!==this.scrollable.offsetParent;)s+=e.offsetTop,e=e.offsetParent;return s+(null!==(i=null==e?void 0:e.offsetTop)&&void 0!==i?i:0)-this.scrollable.offsetTop}appendItems(...t){this.items=[...this.items,...t]}prependItems(...t){this.items=[...t,...this.items]}connectedCallback(){super.connectedCallback(),setTimeout((()=>{this.mutationObserver.disconnect(),this.mutationObserver.observe(this.itemsContainer,{childList:!0}),this.resetScroll()}),0)}disconnectedCallback(){super.disconnectedCallback(),this.scrollable=void 0,this.intersectionObserver.disconnect(),this.mutationObserver.disconnect(),this.shouldRestoreScroll=!1}findScrollableParent(t){var i;let s,e;t.stopPropagation();for(let i of t.composedPath()){const t=i,h=this.elementCanScroll(t);if(h&&t.clientHeight&&t.clientHeight<t.scrollHeight){s=t;break}h&&null==e&&(e=t)}this.scrollable=null!==(i=null!=s?s:e)&&void 0!==i?i:document.body,this.resetScroll(!1)}elementCanScroll(t){try{return["auto","scroll"].includes(getComputedStyle(t).overflowY)}catch(t){return!1}}resetIntersectionObserver(){this.intersectionObserver.disconnect(),this.intersectionObserver=new IntersectionObserver(this.onVisibilityChange,{root:this.scrollable,rootMargin:"-8px",threshold:[0,.01,.1,1]}),this.onMutation()}searchFirstVisibleItem(t,i,s,e){if(s=null!=s?s:0,(e=null!=e?e:i.length-1)<=s)return i[s];const h=Math.floor((e-s)/2)+s,l=i[h];let n=this.getOffset(l);return n>t?this.searchFirstVisibleItem(t,i,s,h-1):n+l.clientHeight<t?this.searchFirstVisibleItem(t,i,h+1,e):l}get shouldRestoreScroll(){return this._shouldRestoreScroll}set shouldRestoreScroll(t){let i=t&&!this._shouldRestoreScroll;this._shouldRestoreScroll=t,i&&requestAnimationFrame(this.scrollAdjustment)}update(t){super.update(t),t.has("items")&&(this.renderedIndexes=new Set,this.renderApprovalTimeouts=[]),((t.has("scrollToItem")||t.has("scrollToIndex"))&&(null!=this.scrollToItem||null!=this.scrollToIndex)||t.has("internalScroll"))&&this.resetScroll()}updated(t){super.updated(t),(t.has("visibleItems")||t.has("items"))&&this.onVisibleItemsChange(),t.has("scrolledToTarget")&&this.scrolledToTarget&&(null!=this.scrollToItem||null!=this.scrollToIndex)&&this.dispatchEvent(new d)}onVisibleItemsChange(){this.visibleItems.every(((t,i)=>null==this.visibleItems[i+1]||t+1===this.visibleItems[i+1]))||i.deepEqual(this.visibleItems,this.lastNotOkVisibleItems)?(this.resetVisibleItemsDebouncer.cancel(),this.dispatchVisibleItemsEvent()):this.resetVisibleItemsDebouncer.run((()=>{this.lastNotOkVisibleItems=[...this.visibleItems],this.visibleItems=[],this.resetIntersectionObserver()}))}dispatchVisibleItemsEvent(){var t;null===(t=this.cancelableDispatchEvent)||void 0===t||t.cancel(),this.cancelableDispatchEvent=i.cancelable(i.waitUntil((()=>!this.scrolling))),this.cancelableDispatchEvent.then((()=>this.dispatchEvent(new a(this.visibleItems,this.visibleItems.map((t=>this.items[t])))))).catch((()=>null))}}c.styles=r,o([e.property({type:Array})],c.prototype,"items",void 0),o([e.property({attribute:!1})],c.prototype,"renderItem",void 0),o([e.property({attribute:!1})],c.prototype,"getItemKey",void 0),o([e.property({type:Object})],c.prototype,"scrollToItem",void 0),o([e.property({type:Number})],c.prototype,"scrollToIndex",void 0),o([e.property({type:Boolean})],c.prototype,"internalScroll",void 0),o([e.property({type:Number})],c.prototype,"renderBeforeFirst",void 0),o([e.property({type:Number})],c.prototype,"renderAfterLast",void 0),o([e.property({type:Boolean})],c.prototype,"ensureScrollToTarget",void 0),o([e.state({hasChanged:(t,i)=>null!=t&&null==i||t.length!==i.length||t[0]!==i[0]})],c.prototype,"visibleItems",void 0),o([e.query(".scrollable")],c.prototype,"internalScrollable",void 0),o([e.query(".items-container")],c.prototype,"itemsContainer",void 0),o([e.state()],c.prototype,"scrolledToTarget",void 0),o([e.state()],c.prototype,"scrolling",void 0),o([e.state({hasChanged:(t,s)=>!i.deepEqual(t,s)})],c.prototype,"renderedIndexes",void 0),i.customElement("ft-infinite-scroll")(c),t.FtInfiniteScroll=c,t.FtInfiniteScrollCssVariables=n,t.ScrolledToTargetEvent=d,t.VisibleItemsChangeEvent=a,t.styles=r}({},ftGlobals.wcUtils,ftGlobals.lit,ftGlobals.litDecorators,ftGlobals.litRepeat,ftGlobals.litUnsafeHTML);
@@ -204,7 +204,7 @@ function(t){return(e,o)=>{const{slot:r,selector:n}=t??{},i="slot"+(r?`[name=${r}
204
204
  display: flow-root;
205
205
  min-height: ${nl.itemContainerMinHeight};
206
206
  }
207
- `;var al=function(t,e,o,r){for(var n,i=arguments.length,a=i<3?e:null===r?r=Object.getOwnPropertyDescriptor(e,o):r,l=t.length-1;l>=0;l--)(n=t[l])&&(a=(i<3?n(a):i>3?n(e,o,a):n(e,o))||a);return i>3&&a&&Object.defineProperty(e,o,a),a};class ll extends CustomEvent{constructor(t,e){super("visible-items-change",{detail:{visibleIndexes:t,visibleItems:e}})}}class cl extends Event{constructor(){super("scrolled-to-target")}}class sl extends An{constructor(){super(...arguments),this.items=[],this.renderItem=()=>Yt``,this.getItemKey=(t,e)=>`${e} - ${JSON.stringify(t)}`,this.internalScroll=!1,this.renderBeforeFirst=1,this.renderAfterLast=1,this.ensureScrollToTarget=!1,this.visibleItems=[],this.scrolledToTarget=!1,this.scrolling=!1,this.renderApprovalTimeouts=[],this.renderedIndexes=new Set,this.scrollDebouncer=new oo(5),this.scrollDoneDebouncer=new oo(10),this.onVisibilityChange=t=>{let e=new Set(this.visibleItems),o=new Set;for(let r of t){let t=+r.target.attributes.getNamedItem("data-item-index").value;r.intersectionRect.height>0?(e.add(t),o.add(t)):o.has(t)||e.delete(t)}this.visibleItems=[...e].sort(((t,e)=>t-e))},this.intersectionObserver=new IntersectionObserver(this.onVisibilityChange),this.scrollingDebouncer=new oo(50),this.ignoreNextScrollEvent=!1,this.scrollListener=()=>{if(this.ignoreNextScrollEvent||(this.scrolling=!0,this.scrollingDebouncer.run((()=>this.scrolling=!1))),this.ignoreNextScrollEvent=!1,this.scrolledToTarget){const t=this.searchFirstVisibleItem(this.itemsContainer.children);this.scrollRestorationItem=t?+t.getAttribute("data-item-index"):void 0,this.scrollRestorationOffset=this.scrollable.scrollTop-this.getOffset(t)}},this.onItemsResize=t=>{for(const e of t)e.contentRect.height>0&&e.target.setAttribute("data-last-known-height",""+e.contentRect.height);this.restoreScroll()},this.restoreScroll=()=>{if(null!=this.scrollRestorationItem&&null!=this.scrollRestorationOffset&&this.scrolledToTarget){const t=this.getItem(this.scrollRestorationItem),e=this.getOffset(t),o=so(0===this.scrollRestorationItem?-e:0,this.scrollRestorationOffset,this.getLastKnownHeight(t)+1);this.ignoreNextScrollEvent=!0,this.scrollable.scrollTop=e+o}},this.itemsResizeObserver=new ResizeObserver(this.onItemsResize),this.scrollableResizeObserver=new ResizeObserver(this.restoreScroll),this.onMutation=()=>{[...this.itemsContainer.children].forEach((t=>{this.intersectionObserver.observe(t),this.itemsResizeObserver.observe(t)})),this.scrollableResizeObserver.observe(this.scrollable)},this.mutationObserver=new MutationObserver(this.onMutation),this.resetVisibleItemsDebouncer=new oo(10)}get scrollable(){var t;return null!==(t=this.internalScroll?this.internalScrollable:this.firstScrollableParent)&&void 0!==t?t:document.body}render(){return Yt`
207
+ `;var al=function(t,e,o,r){for(var n,i=arguments.length,a=i<3?e:null===r?r=Object.getOwnPropertyDescriptor(e,o):r,l=t.length-1;l>=0;l--)(n=t[l])&&(a=(i<3?n(a):i>3?n(e,o,a):n(e,o))||a);return i>3&&a&&Object.defineProperty(e,o,a),a};class ll extends CustomEvent{constructor(t,e){super("visible-items-change",{detail:{visibleIndexes:t,visibleItems:e}})}}class cl extends Event{constructor(){super("scrolled-to-target")}}class sl extends An{constructor(){super(...arguments),this.items=[],this.renderItem=()=>Yt``,this.getItemKey=(t,e)=>`${e} - ${JSON.stringify(t)}`,this.internalScroll=!1,this.renderBeforeFirst=1,this.renderAfterLast=1,this.ensureScrollToTarget=!1,this.visibleItems=[],this.scrolledToTarget=!1,this.scrolling=!1,this.renderApprovalTimeouts=[],this.renderedIndexes=new Set,this.scrollDebouncer=new oo(5),this.scrollDoneDebouncer=new oo(10),this.onVisibilityChange=t=>{let e=new Set(this.visibleItems),o=new Set;for(let r of t){let t=+r.target.getAttribute("data-item-index");r.intersectionRect.height>0?(e.add(t),o.add(t)):o.has(t)||e.delete(t)}this.visibleItems=[...e].sort(((t,e)=>t-e))},this.intersectionObserver=new IntersectionObserver(this.onVisibilityChange),this.scrollingDebouncer=new oo(50),this.ignoreNextScrollEvent=!1,this.scrollListener=()=>{var t;const e=this.ignoreNextScrollEvent;this.ignoreNextScrollEvent=!1,e||(this.scrolling=!0,this.scrollingDebouncer.run((()=>this.scrolling=!1)));const o=this.scrollable.scrollTop,r=o-(null!==(t=this.lastScrollTop)&&void 0!==t?t:0);if(this.lastScrollTop=o,this.scrolledToTarget){this.restoreScrollIfNeeded(e?0:r);const t=this.searchFirstVisibleItem(o,this.itemsContainer.children);this.scrollRestorationItem=t?+t.getAttribute("data-item-index"):void 0,this.scrollRestorationOffset=o-this.getOffset(t)}},this.restoreScrollIfNeeded=(t=0)=>{var e;const o=this.scrollable.scrollHeight,r=o-(null!==(e=this.lastScrollHeight)&&void 0!==e?e:o);if(this.lastScrollHeight=o,0!==r&&null!=this.scrollRestorationItem&&null!=this.scrollRestorationOffset&&this.scrolledToTarget){const e=this.getItem(this.scrollRestorationItem),o=this.getOffset(e),n=o+so(0===this.scrollRestorationItem?-o:1,this.scrollRestorationOffset,e.clientHeight-1)+t-this.scrollable.scrollTop;(Math.abs(r-n)<4||Math.abs(n)>5)&&(this.ignoreNextScrollEvent=!0,this.scrollable.scrollTop+=n)}},this._shouldRestoreScroll=!1,this.scrollAdjustment=()=>{this.restoreScrollIfNeeded(),this.shouldRestoreScroll&&requestAnimationFrame(this.scrollAdjustment)},this.onMutation=()=>{for(let t of this.itemsContainer.children)this.intersectionObserver.observe(t)},this.mutationObserver=new MutationObserver(this.onMutation),this.resetVisibleItemsDebouncer=new oo(10)}get scrollable(){var t;return null!==(t=this._scrollable)&&void 0!==t?t:document.body}set scrollable(t){var e,o,r,n;this._scrollable!==t&&(null===(e=this._scrollable)||void 0===e||e.removeEventListener("scroll",this.scrollListener),this._scrollable&&this.initialOverflowAnchorValue&&(this.scrollable.style.overflowAnchor=this.initialOverflowAnchorValue),this._scrollable=t,null===(o=this._scrollable)||void 0===o||o.addEventListener("scroll",this.scrollListener),this.lastScrollTop=null===(r=this._scrollable)||void 0===r?void 0:r.scrollTop,this.lastScrollHeight=null===(n=this._scrollable)||void 0===n?void 0:n.scrollHeight,this._scrollable&&(this.initialOverflowAnchorValue=getComputedStyle(this._scrollable).overflowAnchor,this._scrollable.style.overflowAnchor="none"))}render(){return Yt`
208
208
  <div class="items-container ${this.internalScroll?"scrollable":""}"
209
209
  tabindex="-1"
210
210
  @find-scrollable-parent=${this.findScrollableParent}>
@@ -216,4 +216,4 @@ function(t){return(e,o)=>{const{slot:r,selector:n}=t??{},i="slot"+(r?`[name=${r}
216
216
  data-item-index="${e}">
217
217
  ${r?(()=>{const o=this.renderItem(t,e);return"string"==typeof o?Ge(o):o})():Qt}
218
218
  </div>
219
- `}prepareRenderIfNeeded(t){const e=null!=this.renderApprovalTimeouts[t];this.inRenderRange(t)&&!e&&(this.renderApprovalTimeouts[t]=setTimeout((()=>{this.inRenderRange(t)?this.renderedIndexes.add(t):this.renderApprovalTimeouts[t]=void 0,this.requestUpdate()}),300))}inRenderRange(t){return t>=this.visibleItems[0]-this.renderBeforeFirst&&t<=(null!=(e=this.visibleItems)?e:[])[(null!=e?e:[]).length-1]+this.renderAfterLast;var e}resetScroll(){this.triggerFindScrollableParent(),this.intersectionObserver.disconnect(),this.itemsResizeObserver.disconnect(),this.scrollableResizeObserver.disconnect(),this.visibleItems=[];const t=this.resolveScrollToIndex();this.renderedIndexes.add(t),this.scrolledToTarget=!1,this.scrollToTarget(t),this.onMutation(),this.scrollDoneDebouncer.run((()=>{this.ensureScrollToTarget&&t>=0&&this.scrollDebouncer.run((()=>{Math.abs(this.scrollable.scrollTop-this.getOffset(t))>5&&this.scrollToTarget(t)}),500),this.scrolledToTarget=!0}))}resolveScrollToIndex(){var t;let e=null!==(t=this.scrollToIndex)&&void 0!==t?t:this.scrollToItem?this.items.indexOf(this.scrollToItem):-1;return e>=this.items.length?-1:e}getItem(t){var e,o,r;return null!==(o=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector(`#item-${t}`))&&void 0!==o?o:null===(r=this.shadowRoot)||void 0===r?void 0:r.querySelector("#item-0")}scrollToTarget(t){t<=0?(this.scrollable.scrollTop=0,this.scrollRestorationOffset=-this.getOffset(t)):(this.scrollable.scrollTop=this.getOffset(t),this.scrollRestorationOffset=0),this.scrollRestorationItem=t>=0?t:void 0}getOffset(t){var e;let o=0,r="number"==typeof t?this.getItem(t):t;for(;r&&r.offsetParent!==this.scrollable.offsetParent;)o+=r.offsetTop,r=r.offsetParent;return o+(null!==(e=null==r?void 0:r.offsetTop)&&void 0!==e?e:0)-this.scrollable.offsetTop}getLastKnownHeight(t){var e;return+(null!==(e=null==t?void 0:t.getAttribute("data-last-known-height"))&&void 0!==e?e:1e3)}appendItems(...t){this.items=[...this.items,...t]}prependItems(...t){this.items=[...t,...this.items]}connectedCallback(){super.connectedCallback(),setTimeout((()=>{this.triggerFindScrollableParent(),this.initIntersectionObserver(),this.mutationObserver.disconnect(),this.mutationObserver.observe(this.itemsContainer,{childList:!0}),this.resetScroll()}),0)}initIntersectionObserver(){this.intersectionObserver.disconnect(),this.intersectionObserver=new IntersectionObserver(this.onVisibilityChange,{root:this.scrollable,rootMargin:"-8px",threshold:[0,.01,.1,1]})}triggerFindScrollableParent(){var t;null===(t=this.itemsContainer)||void 0===t||t.dispatchEvent(new Event("find-scrollable-parent",{composed:!0}))}findScrollableParent(t){var e;let o,r;t.stopPropagation();for(let e of t.composedPath()){const t=e,n=this.elementCanScroll(t);if(n&&t.clientHeight&&t.clientHeight<t.scrollHeight){o=t;break}n&&(r=t)}let n=o||r;n!==this.firstScrollableParent&&(null===(e=this.firstScrollableParent)||void 0===e||e.removeEventListener("scroll",this.scrollListener),null==n||n.addEventListener("scroll",this.scrollListener),this.firstScrollableParent=n,this.initIntersectionObserver(),this.resetScroll())}elementCanScroll(t){try{return["auto","scroll"].includes(getComputedStyle(t).overflowY)}catch(t){return!1}}searchFirstVisibleItem(t,e,o){if(e=null!=e?e:0,(o=null!=o?o:t.length-1)<=e)return t[e];const r=Math.floor((o-e)/2)+e,n=t[r];return this.getOffset(n)>this.scrollable.scrollTop?this.searchFirstVisibleItem(t,e,r-1):this.getOffset(n)+this.getLastKnownHeight(n)<this.scrollable.scrollTop?this.searchFirstVisibleItem(t,r+1,o):n}disconnectedCallback(){super.disconnectedCallback(),this.intersectionObserver.disconnect(),this.itemsResizeObserver.disconnect(),this.scrollableResizeObserver.disconnect(),this.mutationObserver.disconnect()}update(t){super.update(t),t.has("items")&&(this.renderedIndexes=new Set,this.renderApprovalTimeouts=[]),!t.has("scrollToItem")&&!t.has("scrollToIndex")||null==this.scrollToItem&&null==this.scrollToIndex||this.resetScroll()}updated(t){super.updated(t),(t.has("visibleItems")||t.has("items"))&&this.onVisibleItemsChange(),t.has("scrolledToTarget")&&this.scrolledToTarget&&(null!=this.scrollToItem||null!=this.scrollToIndex)&&this.dispatchEvent(new cl)}onVisibleItemsChange(){const t=this.visibleItems.every(((t,e)=>null==this.visibleItems[e+1]||t+1===this.visibleItems[e+1]));t||co(this.visibleItems,this.lastNotOkVisibleItems)?(this.resetVisibleItemsDebouncer.cancel(),this.dispatchVisibleItemsEvent()):this.resetVisibleItemsDebouncer.run((()=>{this.lastNotOkVisibleItems=[...this.visibleItems],this.visibleItems=[],this.initIntersectionObserver(),this.onMutation()}))}dispatchVisibleItemsEvent(){var t;null===(t=this.cancelableDispatchEvent)||void 0===t||t.cancel(),this.cancelableDispatchEvent=Je(io((()=>!this.scrolling))),this.cancelableDispatchEvent.then((()=>this.dispatchEvent(new ll(this.visibleItems,this.visibleItems.map((t=>this.items[t])))))).catch((()=>null))}}sl.styles=il,al([Se({type:Array})],sl.prototype,"items",void 0),al([Se({attribute:!1})],sl.prototype,"renderItem",void 0),al([Se({attribute:!1})],sl.prototype,"getItemKey",void 0),al([Se({type:Object})],sl.prototype,"scrollToItem",void 0),al([Se({type:Number})],sl.prototype,"scrollToIndex",void 0),al([Se({type:Boolean})],sl.prototype,"internalScroll",void 0),al([Se({type:Number})],sl.prototype,"renderBeforeFirst",void 0),al([Se({type:Number})],sl.prototype,"renderAfterLast",void 0),al([Se({type:Boolean})],sl.prototype,"ensureScrollToTarget",void 0),al([xe({hasChanged:(t,e)=>null!=t&&null==e||t.length!==e.length||t[0]!==e[0]})],sl.prototype,"visibleItems",void 0),al([Ce(".scrollable")],sl.prototype,"internalScrollable",void 0),al([Ce(".items-container")],sl.prototype,"itemsContainer",void 0),al([xe()],sl.prototype,"scrolledToTarget",void 0),al([xe()],sl.prototype,"scrolling",void 0),al([xe({hasChanged:(t,e)=>!co(t,e)})],sl.prototype,"renderedIndexes",void 0),uo("ft-infinite-scroll")(sl),t.FtInfiniteScroll=sl,t.FtInfiniteScrollCssVariables=nl,t.ScrolledToTargetEvent=cl,t.VisibleItemsChangeEvent=ll,t.styles=il}({});
219
+ `}prepareRenderIfNeeded(t){const e=null!=this.renderApprovalTimeouts[t];this.inRenderRange(t)&&!e&&(this.renderApprovalTimeouts[t]=setTimeout((()=>{this.inRenderRange(t)?this.renderedIndexes.add(t):this.renderApprovalTimeouts[t]=void 0,this.requestUpdate()}),300))}inRenderRange(t){return t>=this.visibleItems[0]-this.renderBeforeFirst&&t<=(null!=(e=this.visibleItems)?e:[])[(null!=e?e:[]).length-1]+this.renderAfterLast;var e}resetScroll(t=!0){var e;if(this.shouldRestoreScroll=!1,this.intersectionObserver.disconnect(),this.visibleItems=[],this.scrolledToTarget=!1,this.internalScroll&&this.scrollable!==this.internalScrollable)this.scrollable=this.internalScrollable;else if(!this.internalScroll&&t)return void(null===(e=this.itemsContainer)||void 0===e||e.dispatchEvent(new Event("find-scrollable-parent",{composed:!0})));const o=this.resolveScrollToIndex();this.renderedIndexes.add(o),this.scrollToTarget(o),this.scrollDoneDebouncer.run((()=>{this.ensureScrollToTarget&&o>=0&&this.scrollDebouncer.run((()=>{Math.abs(this.scrollable.scrollTop-this.getOffset(o))>5&&this.scrollToTarget(o)}),500),this.scrollToTarget(o),this.scrolledToTarget=!0,this.shouldRestoreScroll=!0,this.resetIntersectionObserver()}))}resolveScrollToIndex(){var t;let e=null!==(t=this.scrollToIndex)&&void 0!==t?t:this.scrollToItem?this.items.indexOf(this.scrollToItem):-1;return e>=this.items.length?-1:e}getItem(t){var e,o,r;return null!==(o=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector(`#item-${t}`))&&void 0!==o?o:null===(r=this.shadowRoot)||void 0===r?void 0:r.querySelector("#item-0")}scrollToTarget(t){t<=0?(this.scrollable.scrollTop=0,this.scrollRestorationOffset=-this.getOffset(t)):(this.scrollable.scrollTop=this.getOffset(t),this.scrollRestorationOffset=0),this.scrollRestorationItem=t>=0?t:void 0}getOffset(t){var e;let o=0,r="number"==typeof t?this.getItem(t):t;for(;r&&r.offsetParent!==this.scrollable.offsetParent;)o+=r.offsetTop,r=r.offsetParent;return o+(null!==(e=null==r?void 0:r.offsetTop)&&void 0!==e?e:0)-this.scrollable.offsetTop}appendItems(...t){this.items=[...this.items,...t]}prependItems(...t){this.items=[...t,...this.items]}connectedCallback(){super.connectedCallback(),setTimeout((()=>{this.mutationObserver.disconnect(),this.mutationObserver.observe(this.itemsContainer,{childList:!0}),this.resetScroll()}),0)}disconnectedCallback(){super.disconnectedCallback(),this.scrollable=void 0,this.intersectionObserver.disconnect(),this.mutationObserver.disconnect(),this.shouldRestoreScroll=!1}findScrollableParent(t){var e;let o,r;t.stopPropagation();for(let e of t.composedPath()){const t=e,n=this.elementCanScroll(t);if(n&&t.clientHeight&&t.clientHeight<t.scrollHeight){o=t;break}n&&null==r&&(r=t)}this.scrollable=null!==(e=null!=o?o:r)&&void 0!==e?e:document.body,this.resetScroll(!1)}elementCanScroll(t){try{return["auto","scroll"].includes(getComputedStyle(t).overflowY)}catch(t){return!1}}resetIntersectionObserver(){this.intersectionObserver.disconnect(),this.intersectionObserver=new IntersectionObserver(this.onVisibilityChange,{root:this.scrollable,rootMargin:"-8px",threshold:[0,.01,.1,1]}),this.onMutation()}searchFirstVisibleItem(t,e,o,r){if(o=null!=o?o:0,(r=null!=r?r:e.length-1)<=o)return e[o];const n=Math.floor((r-o)/2)+o,i=e[n];let a=this.getOffset(i);return a>t?this.searchFirstVisibleItem(t,e,o,n-1):a+i.clientHeight<t?this.searchFirstVisibleItem(t,e,n+1,r):i}get shouldRestoreScroll(){return this._shouldRestoreScroll}set shouldRestoreScroll(t){let e=t&&!this._shouldRestoreScroll;this._shouldRestoreScroll=t,e&&requestAnimationFrame(this.scrollAdjustment)}update(t){super.update(t),t.has("items")&&(this.renderedIndexes=new Set,this.renderApprovalTimeouts=[]),((t.has("scrollToItem")||t.has("scrollToIndex"))&&(null!=this.scrollToItem||null!=this.scrollToIndex)||t.has("internalScroll"))&&this.resetScroll()}updated(t){super.updated(t),(t.has("visibleItems")||t.has("items"))&&this.onVisibleItemsChange(),t.has("scrolledToTarget")&&this.scrolledToTarget&&(null!=this.scrollToItem||null!=this.scrollToIndex)&&this.dispatchEvent(new cl)}onVisibleItemsChange(){const t=this.visibleItems.every(((t,e)=>null==this.visibleItems[e+1]||t+1===this.visibleItems[e+1]));t||co(this.visibleItems,this.lastNotOkVisibleItems)?(this.resetVisibleItemsDebouncer.cancel(),this.dispatchVisibleItemsEvent()):this.resetVisibleItemsDebouncer.run((()=>{this.lastNotOkVisibleItems=[...this.visibleItems],this.visibleItems=[],this.resetIntersectionObserver()}))}dispatchVisibleItemsEvent(){var t;null===(t=this.cancelableDispatchEvent)||void 0===t||t.cancel(),this.cancelableDispatchEvent=Je(io((()=>!this.scrolling))),this.cancelableDispatchEvent.then((()=>this.dispatchEvent(new ll(this.visibleItems,this.visibleItems.map((t=>this.items[t])))))).catch((()=>null))}}sl.styles=il,al([Se({type:Array})],sl.prototype,"items",void 0),al([Se({attribute:!1})],sl.prototype,"renderItem",void 0),al([Se({attribute:!1})],sl.prototype,"getItemKey",void 0),al([Se({type:Object})],sl.prototype,"scrollToItem",void 0),al([Se({type:Number})],sl.prototype,"scrollToIndex",void 0),al([Se({type:Boolean})],sl.prototype,"internalScroll",void 0),al([Se({type:Number})],sl.prototype,"renderBeforeFirst",void 0),al([Se({type:Number})],sl.prototype,"renderAfterLast",void 0),al([Se({type:Boolean})],sl.prototype,"ensureScrollToTarget",void 0),al([xe({hasChanged:(t,e)=>null!=t&&null==e||t.length!==e.length||t[0]!==e[0]})],sl.prototype,"visibleItems",void 0),al([Ce(".scrollable")],sl.prototype,"internalScrollable",void 0),al([Ce(".items-container")],sl.prototype,"itemsContainer",void 0),al([xe()],sl.prototype,"scrolledToTarget",void 0),al([xe()],sl.prototype,"scrolling",void 0),al([xe({hasChanged:(t,e)=>!co(t,e)})],sl.prototype,"renderedIndexes",void 0),uo("ft-infinite-scroll")(sl),t.FtInfiniteScroll=sl,t.FtInfiniteScrollCssVariables=nl,t.ScrolledToTargetEvent=cl,t.VisibleItemsChangeEvent=ll,t.styles=il}({});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluid-topics/ft-infinite-scroll",
3
- "version": "1.1.59",
3
+ "version": "1.1.60",
4
4
  "description": "An infinite scroller.",
5
5
  "keywords": [
6
6
  "Lit"
@@ -19,8 +19,8 @@
19
19
  "url": "ssh://git@scm.mrs.antidot.net:2222/fluidtopics/ft-web-components.git"
20
20
  },
21
21
  "dependencies": {
22
- "@fluid-topics/ft-wc-utils": "1.1.59",
22
+ "@fluid-topics/ft-wc-utils": "1.1.60",
23
23
  "lit": "3.1.0"
24
24
  },
25
- "gitHead": "b966417cfb62df1b965a2736005adb98bb7b7f61"
25
+ "gitHead": "508d561509be8c615dfc3de6780ab51e87c2fb22"
26
26
  }