@fluid-topics/ft-infinite-scroll 0.3.11 → 0.3.13

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.
@@ -0,0 +1,5 @@
1
+ export declare const FtInfiniteScrollCssVariables: {
2
+ padding: import("@fluid-topics/ft-wc-utils").FtCssVariable;
3
+ };
4
+ export declare const styles: import("lit").CSSResult;
5
+ //# sourceMappingURL=ft-infinite-scroll.css.d.ts.map
@@ -0,0 +1,41 @@
1
+ import { css } from "lit";
2
+ import { FtCssVariableFactory } from "@fluid-topics/ft-wc-utils";
3
+ export const FtInfiniteScrollCssVariables = {
4
+ padding: FtCssVariableFactory.create("--ft-infinite-scroll-padding", "SIZE", "0"),
5
+ };
6
+ // language=CSS
7
+ export const styles = css `
8
+ .items-container {
9
+ position: relative;
10
+ padding: ${FtInfiniteScrollCssVariables.padding};
11
+ outline: none;
12
+ }
13
+
14
+ .scrollable {
15
+ height: 100%;
16
+ overflow-y: auto;
17
+ }
18
+
19
+ .item-container {
20
+ height: 100vh;
21
+ }
22
+
23
+ .item-container + .item-container {
24
+ /*
25
+ We add a gap between items to be sure to hide the content above the targeted item
26
+ When a div is visible (even by a fraction of a pixel) if its height changes
27
+ the browser will try to keep the scroll stable in relation to the first visible element
28
+ By adding this gap we ensure that the previous item will be fully hidden and event if its size changes, it will not impact the scroll offset
29
+ */
30
+ margin-top: 4px;
31
+ }
32
+
33
+ .scrollable .item-container {
34
+ height: 100%;
35
+ }
36
+
37
+ .resizable:not(.rendered) {
38
+ width: 0;
39
+ }
40
+ `;
41
+ //# sourceMappingURL=ft-infinite-scroll.css.js.map
@@ -1,14 +1,6 @@
1
1
  import { PropertyValues, TemplateResult } from "lit";
2
2
  import { FtLitElement } from "@fluid-topics/ft-wc-utils";
3
- export interface FtInfiniteScrollProperties<T> {
4
- items: Array<T>;
5
- renderItem: (item: T, index: number) => TemplateResult | string;
6
- scrollToItem?: T;
7
- scrollToIndex?: number;
8
- }
9
- export declare const FtInfiniteScrollCssVariables: {
10
- padding: import("@fluid-topics/ft-wc-utils").FtCssVariable;
11
- };
3
+ import { FtInfiniteScrollProperties } from "./ft-infinite-scroll.properties";
12
4
  export declare type VisibleItems<T> = {
13
5
  visibleIndexes: Array<number>;
14
6
  visibleItems: Array<T>;
@@ -4,14 +4,12 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { css, html } from "lit";
7
+ import { html } from "lit";
8
8
  import { property, query, state } from "lit/decorators.js";
9
9
  import { repeat } from "lit/directives/repeat.js";
10
- import { Debouncer, FtCssVariableFactory, FtLitElement, isSafari } from "@fluid-topics/ft-wc-utils";
10
+ import { Debouncer, FtLitElement, isSafari } from "@fluid-topics/ft-wc-utils";
11
11
  import { unsafeHTML } from "lit/directives/unsafe-html.js";
12
- export const FtInfiniteScrollCssVariables = {
13
- padding: FtCssVariableFactory.create("--ft-infinite-scroll-padding", "SIZE", "0"),
14
- };
12
+ import { styles } from "./ft-infinite-scroll.css";
15
13
  export class VisibleItemsChangeEvent extends CustomEvent {
16
14
  constructor(indexes, items) {
17
15
  super("visible-items-change", {
@@ -215,40 +213,7 @@ export class FtInfiniteScroll extends FtLitElement {
215
213
  }
216
214
  }
217
215
  // language=CSS
218
- FtInfiniteScroll.styles = css `
219
- .items-container {
220
- position: relative;
221
- padding: ${FtInfiniteScrollCssVariables.padding};
222
- outline: none;
223
- }
224
-
225
- .scrollable {
226
- height: 100%;
227
- overflow-y: auto;
228
- }
229
-
230
- .item-container {
231
- height: 100vh;
232
- }
233
-
234
- .item-container + .item-container {
235
- /*
236
- We add a gap between items to be sure to hide the content above the targeted item
237
- When a div is visible (even by a fraction of a pixel) if its height changes
238
- the browser will try to keep the scroll stable in relation to the first visible element
239
- By adding this gap we ensure that the previous item will be fully hidden and event if its size changes, it will not impact the scroll offset
240
- */
241
- margin-top: 4px;
242
- }
243
-
244
- .scrollable .item-container {
245
- height: 100%;
246
- }
247
-
248
- .resizable:not(.rendered) {
249
- width: 0;
250
- }
251
- `;
216
+ FtInfiniteScroll.styles = styles;
252
217
  __decorate([
253
218
  property({ type: Array })
254
219
  ], FtInfiniteScroll.prototype, "items", void 0);
@@ -1,4 +1,37 @@
1
- !function(t,e,i,s,l,n){var r=function(t,e,i,s){for(var l,n=arguments.length,r=n<3?e:null===s?s=Object.getOwnPropertyDescriptor(e,i):s,o=t.length-1;o>=0;o--)(l=t[o])&&(r=(n<3?l(r):n>3?l(e,i,r):l(e,i))||r);return n>3&&r&&Object.defineProperty(e,i,r),r};const o={padding:e.FtCssVariableFactory.create("--ft-infinite-scroll-padding","SIZE","0")};class h extends CustomEvent{constructor(t,e){super("visible-items-change",{detail:{visibleIndexes:t,visibleItems:e}})}}class a extends Event{constructor(){super("scrolled-to-target")}}class d extends e.FtLitElement{constructor(){super(...arguments),this.items=[],this.renderItem=()=>i.html``,this.internalScroll=!1,this.renderBeforeFirst=1,this.renderAfterLast=1,this.visibleItems=[],this.scrolledToTarget=!1,this.alreadyRenderedIndexes=new Set,this.scrollDebouncer=new e.Debouncer(5),this.onVisibilityChange=t=>{const e=t.filter((t=>t.intersectionRect.height>1)).map((t=>+t.target.attributes.getNamedItem("data-item-index").value)).filter((t=>!this.visibleItems.includes(t))),i=t.filter((t=>t.intersectionRect.height<=1)).map((t=>+t.target.attributes.getNamedItem("data-item-index").value)).filter((t=>this.visibleItems.includes(t))),s=[...this.visibleItems].filter((t=>!i.includes(t)));this.visibleItems=[...e,...s].sort(((t,e)=>t-e))},this.intersectionObserver=new IntersectionObserver(this.onVisibilityChange),this.onResize=t=>{this.triggerFindScrollableParent();let i=0;t=t.sort(((t,e)=>t.contentRect.top-e.contentRect.top));for(const e of t){const t=+e.target.parentElement.getAttribute("data-item-index"),s=e.target.parentElement.clientHeight,l=e.contentRect.height;this.alreadyRenderedIndexes.has(t)&&(e.target.parentElement.style.height=l+"px",i+=this.scrollable&&this.getOffset(e.target.parentElement)<this.scrollable.scrollTop+i?l-s:0)}this.scrollable&&e.isSafari&&(this.scrollable.scrollTop+=i)},this.resizeObserver=new ResizeObserver(this.onResize),this.onMutation=()=>{[...this.itemsContainer.children].forEach((t=>{this.intersectionObserver.observe(t),this.resizeObserver.observe(t.children.item(0))}))},this.mutationObserver=new MutationObserver(this.onMutation)}get scrollable(){return this.internalScroll?this.internalScrollable:this.firstScrollableParent}render(){return i.html`
1
+ !function(t,e,i,s,l,n){const r={padding:e.FtCssVariableFactory.create("--ft-infinite-scroll-padding","SIZE","0")},o=i.css`
2
+ .items-container {
3
+ position: relative;
4
+ padding: ${r.padding};
5
+ outline: none;
6
+ }
7
+
8
+ .scrollable {
9
+ height: 100%;
10
+ overflow-y: auto;
11
+ }
12
+
13
+ .item-container {
14
+ height: 100vh;
15
+ }
16
+
17
+ .item-container + .item-container {
18
+ /*
19
+ We add a gap between items to be sure to hide the content above the targeted item
20
+ When a div is visible (even by a fraction of a pixel) if its height changes
21
+ the browser will try to keep the scroll stable in relation to the first visible element
22
+ By adding this gap we ensure that the previous item will be fully hidden and event if its size changes, it will not impact the scroll offset
23
+ */
24
+ margin-top: 4px;
25
+ }
26
+
27
+ .scrollable .item-container {
28
+ height: 100%;
29
+ }
30
+
31
+ .resizable:not(.rendered) {
32
+ width: 0;
33
+ }
34
+ `;var h=function(t,e,i,s){for(var l,n=arguments.length,r=n<3?e:null===s?s=Object.getOwnPropertyDescriptor(e,i):s,o=t.length-1;o>=0;o--)(l=t[o])&&(r=(n<3?l(r):n>3?l(e,i,r):l(e,i))||r);return n>3&&r&&Object.defineProperty(e,i,r),r};class a extends CustomEvent{constructor(t,e){super("visible-items-change",{detail:{visibleIndexes:t,visibleItems:e}})}}class d extends Event{constructor(){super("scrolled-to-target")}}class c extends e.FtLitElement{constructor(){super(...arguments),this.items=[],this.renderItem=()=>i.html``,this.internalScroll=!1,this.renderBeforeFirst=1,this.renderAfterLast=1,this.visibleItems=[],this.scrolledToTarget=!1,this.alreadyRenderedIndexes=new Set,this.scrollDebouncer=new e.Debouncer(5),this.onVisibilityChange=t=>{const e=t.filter((t=>t.intersectionRect.height>1)).map((t=>+t.target.attributes.getNamedItem("data-item-index").value)).filter((t=>!this.visibleItems.includes(t))),i=t.filter((t=>t.intersectionRect.height<=1)).map((t=>+t.target.attributes.getNamedItem("data-item-index").value)).filter((t=>this.visibleItems.includes(t))),s=[...this.visibleItems].filter((t=>!i.includes(t)));this.visibleItems=[...e,...s].sort(((t,e)=>t-e))},this.intersectionObserver=new IntersectionObserver(this.onVisibilityChange),this.onResize=t=>{this.triggerFindScrollableParent();let i=0;t=t.sort(((t,e)=>t.contentRect.top-e.contentRect.top));for(const e of t){const t=+e.target.parentElement.getAttribute("data-item-index"),s=e.target.parentElement.clientHeight,l=e.contentRect.height;this.alreadyRenderedIndexes.has(t)&&(e.target.parentElement.style.height=l+"px",i+=this.scrollable&&this.getOffset(e.target.parentElement)<this.scrollable.scrollTop+i?l-s:0)}this.scrollable&&e.isSafari&&(this.scrollable.scrollTop+=i)},this.resizeObserver=new ResizeObserver(this.onResize),this.onMutation=()=>{[...this.itemsContainer.children].forEach((t=>{this.intersectionObserver.observe(t),this.resizeObserver.observe(t.children.item(0))}))},this.mutationObserver=new MutationObserver(this.onMutation)}get scrollable(){return this.internalScroll?this.internalScrollable:this.firstScrollableParent}render(){return i.html`
2
35
  <div class="items-container ${this.internalScroll?"scrollable":""}"
3
36
  tabindex="-1"
4
37
  @find-scrollable-parent=${this.findScrollableParent}>
@@ -12,37 +45,4 @@
12
45
  ${l?(()=>{const s=this.renderItem(t,e);return"string"==typeof s?i.html`${n.unsafeHTML(s)}`:s})():null}
13
46
  </div>
14
47
  </div>
15
- `}resetScroll(){this.intersectionObserver.disconnect(),this.resizeObserver.disconnect(),this.visibleItems=[],this.scrolledToTarget=!1,this.scrollDebouncer.run((()=>{var t,e;let i=null!==(t=this.scrollToIndex)&&void 0!==t?t:this.scrollToItem?this.items.indexOf(this.scrollToItem):-1;i>=this.items.length&&(i=-1);let s=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector(`#item-${i}`);this.scrollToTarget(s),this.onMutation(),setTimeout((()=>{this.scrolledToTarget=!0}),10)}))}scrollToTarget(t){var e;if(t){let i=+(null!==(e=t.getAttribute("data-item-index"))&&void 0!==e?e:"0");this.scrollable?this.scrollable.scrollTop=i>0?this.getOffset(t)+1:0:t.scrollIntoView({block:"start"})}}getOffset(t){var e;let i=0,s=t;for(;s&&s.offsetParent!==this.scrollable.offsetParent;)i+=s.offsetTop,s=s.offsetParent;return i+(null!==(e=null==s?void 0:s.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.triggerFindScrollableParent(),this.intersectionObserver.disconnect(),this.intersectionObserver=new IntersectionObserver(this.onVisibilityChange,{rootMargin:"-2px",threshold:[0,.01,.1]}),this.mutationObserver.disconnect(),this.mutationObserver.observe(this.itemsContainer,{childList:!0})}),0)}triggerFindScrollableParent(){this.itemsContainer.dispatchEvent(new Event("find-scrollable-parent",{composed:!0}))}findScrollableParent(t){t.stopPropagation();for(let e of t.composedPath()){const t=e;if(t.clientHeight&&t.clientHeight<t.scrollHeight&&["auto","scroll"].includes(getComputedStyle(t).overflowY)){this.firstScrollableParent=t;break}}}disconnectedCallback(){super.disconnectedCallback(),this.intersectionObserver.disconnect(),this.resizeObserver.disconnect(),this.mutationObserver.disconnect()}firstUpdated(t){super.firstUpdated(t),this.resetScroll()}update(t){super.update(t),t.has("items")&&(this.alreadyRenderedIndexes=new Set),(t.has("scrollToItem")||t.has("scrollToIndex"))&&this.resetScroll()}updated(t){super.updated(t),(t.has("visibleItems")||t.has("items"))&&this.dispatchEvent(new h(this.visibleItems,this.visibleItems.map((t=>this.items[t])))),t.has("scrolledToTarget")&&this.scrolledToTarget&&this.dispatchEvent(new a)}}d.styles=i.css`
16
- .items-container {
17
- position: relative;
18
- padding: ${o.padding};
19
- outline: none;
20
- }
21
-
22
- .scrollable {
23
- height: 100%;
24
- overflow-y: auto;
25
- }
26
-
27
- .item-container {
28
- height: 100vh;
29
- }
30
-
31
- .item-container + .item-container {
32
- /*
33
- We add a gap between items to be sure to hide the content above the targeted item
34
- When a div is visible (even by a fraction of a pixel) if its height changes
35
- the browser will try to keep the scroll stable in relation to the first visible element
36
- By adding this gap we ensure that the previous item will be fully hidden and event if its size changes, it will not impact the scroll offset
37
- */
38
- margin-top: 4px;
39
- }
40
-
41
- .scrollable .item-container {
42
- height: 100%;
43
- }
44
-
45
- .resizable:not(.rendered) {
46
- width: 0;
47
- }
48
- `,r([s.property({type:Array})],d.prototype,"items",void 0),r([s.property({attribute:!1})],d.prototype,"renderItem",void 0),r([s.property({type:Object})],d.prototype,"scrollToItem",void 0),r([s.property({type:Number})],d.prototype,"scrollToIndex",void 0),r([s.property({type:Boolean})],d.prototype,"internalScroll",void 0),r([s.property({type:Number})],d.prototype,"renderBeforeFirst",void 0),r([s.property({type:Number})],d.prototype,"renderAfterLast",void 0),r([s.state({hasChanged:(t,e)=>null!=t&&null==e||t.length!==e.length||t[0]!==e[0]})],d.prototype,"visibleItems",void 0),r([s.query(".scrollable")],d.prototype,"internalScrollable",void 0),r([s.query(".items-container")],d.prototype,"itemsContainer",void 0),r([s.state()],d.prototype,"scrolledToTarget",void 0),e.customElement("ft-infinite-scroll")(d),t.FtInfiniteScroll=d,t.FtInfiniteScrollCssVariables=o,t.ScrolledToTargetEvent=a,t.VisibleItemsChangeEvent=h,Object.defineProperty(t,"t",{value:!0})}({},ftGlobals.wcUtils,ftGlobals.lit,ftGlobals.litDecorators,ftGlobals.litRepeat,ftGlobals.litUnsafeHTML);
48
+ `}resetScroll(){this.intersectionObserver.disconnect(),this.resizeObserver.disconnect(),this.visibleItems=[],this.scrolledToTarget=!1,this.scrollDebouncer.run((()=>{var t,e;let i=null!==(t=this.scrollToIndex)&&void 0!==t?t:this.scrollToItem?this.items.indexOf(this.scrollToItem):-1;i>=this.items.length&&(i=-1);let s=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector(`#item-${i}`);this.scrollToTarget(s),this.onMutation(),setTimeout((()=>{this.scrolledToTarget=!0}),10)}))}scrollToTarget(t){var e;if(t){let i=+(null!==(e=t.getAttribute("data-item-index"))&&void 0!==e?e:"0");this.scrollable?this.scrollable.scrollTop=i>0?this.getOffset(t)+1:0:t.scrollIntoView({block:"start"})}}getOffset(t){var e;let i=0,s=t;for(;s&&s.offsetParent!==this.scrollable.offsetParent;)i+=s.offsetTop,s=s.offsetParent;return i+(null!==(e=null==s?void 0:s.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.triggerFindScrollableParent(),this.intersectionObserver.disconnect(),this.intersectionObserver=new IntersectionObserver(this.onVisibilityChange,{rootMargin:"-2px",threshold:[0,.01,.1]}),this.mutationObserver.disconnect(),this.mutationObserver.observe(this.itemsContainer,{childList:!0})}),0)}triggerFindScrollableParent(){this.itemsContainer.dispatchEvent(new Event("find-scrollable-parent",{composed:!0}))}findScrollableParent(t){t.stopPropagation();for(let e of t.composedPath()){const t=e;if(t.clientHeight&&t.clientHeight<t.scrollHeight&&["auto","scroll"].includes(getComputedStyle(t).overflowY)){this.firstScrollableParent=t;break}}}disconnectedCallback(){super.disconnectedCallback(),this.intersectionObserver.disconnect(),this.resizeObserver.disconnect(),this.mutationObserver.disconnect()}firstUpdated(t){super.firstUpdated(t),this.resetScroll()}update(t){super.update(t),t.has("items")&&(this.alreadyRenderedIndexes=new Set),(t.has("scrollToItem")||t.has("scrollToIndex"))&&this.resetScroll()}updated(t){super.updated(t),(t.has("visibleItems")||t.has("items"))&&this.dispatchEvent(new a(this.visibleItems,this.visibleItems.map((t=>this.items[t])))),t.has("scrolledToTarget")&&this.scrolledToTarget&&this.dispatchEvent(new d)}}c.styles=o,h([s.property({type:Array})],c.prototype,"items",void 0),h([s.property({attribute:!1})],c.prototype,"renderItem",void 0),h([s.property({type:Object})],c.prototype,"scrollToItem",void 0),h([s.property({type:Number})],c.prototype,"scrollToIndex",void 0),h([s.property({type:Boolean})],c.prototype,"internalScroll",void 0),h([s.property({type:Number})],c.prototype,"renderBeforeFirst",void 0),h([s.property({type:Number})],c.prototype,"renderAfterLast",void 0),h([s.state({hasChanged:(t,e)=>null!=t&&null==e||t.length!==e.length||t[0]!==e[0]})],c.prototype,"visibleItems",void 0),h([s.query(".scrollable")],c.prototype,"internalScrollable",void 0),h([s.query(".items-container")],c.prototype,"itemsContainer",void 0),h([s.state()],c.prototype,"scrolledToTarget",void 0),e.customElement("ft-infinite-scroll")(c),t.FtInfiniteScroll=c,t.FtInfiniteScrollCssVariables=r,t.ScrolledToTargetEvent=d,t.VisibleItemsChangeEvent=a,t.styles=o,Object.defineProperty(t,"t",{value:!0})}({},ftGlobals.wcUtils,ftGlobals.lit,ftGlobals.litDecorators,ftGlobals.litRepeat,ftGlobals.litUnsafeHTML);
@@ -104,7 +104,40 @@ function(t){return class extends t{createRenderRoot(){const t=this.constructor,{
104
104
  * Copyright 2017 Google LLC
105
105
  * SPDX-License-Identifier: BSD-3-Clause
106
106
  */
107
- class Rt extends xt{constructor(t){if(super(t),this.it=H,t.type!==bt)throw Error(this.constructor.directiveName+"() can only be used in child bindings")}render(t){if(t===H||null==t)return this._t=void 0,this.it=t;if(t===D)return t;if("string"!=typeof t)throw Error(this.constructor.directiveName+"() called with a non-string value");if(t===this.it)return this._t;this.it=t;const e=[t];return e.raw=e,this._t={_$litType$:this.constructor.resultType,strings:e,values:[]}}}Rt.directiveName="unsafeHTML",Rt.resultType=1;const St=mt(Rt);var Mt=function(t,e,i,s){for(var n,o=arguments.length,r=o<3?e:null===s?s=Object.getOwnPropertyDescriptor(e,i):s,l=t.length-1;l>=0;l--)(n=t[l])&&(r=(o<3?n(r):o>3?n(e,i,r):n(e,i))||r);return o>3&&r&&Object.defineProperty(e,i,r),r};const Ut={padding:ht.create("--ft-infinite-scroll-padding","SIZE","0")};class kt extends CustomEvent{constructor(t,e){super("visible-items-change",{detail:{visibleIndexes:t,visibleItems:e}})}}class Tt extends Event{constructor(){super("scrolled-to-target")}}class At extends ft{constructor(){super(...arguments),this.items=[],this.renderItem=()=>K``,this.internalScroll=!1,this.renderBeforeFirst=1,this.renderAfterLast=1,this.visibleItems=[],this.scrolledToTarget=!1,this.alreadyRenderedIndexes=new Set,this.scrollDebouncer=new e(5),this.onVisibilityChange=t=>{const e=t.filter((t=>t.intersectionRect.height>1)).map((t=>+t.target.attributes.getNamedItem("data-item-index").value)).filter((t=>!this.visibleItems.includes(t))),i=t.filter((t=>t.intersectionRect.height<=1)).map((t=>+t.target.attributes.getNamedItem("data-item-index").value)).filter((t=>this.visibleItems.includes(t))),s=[...this.visibleItems].filter((t=>!i.includes(t)));this.visibleItems=[...e,...s].sort(((t,e)=>t-e))},this.intersectionObserver=new IntersectionObserver(this.onVisibilityChange),this.onResize=t=>{this.triggerFindScrollableParent();let e=0;t=t.sort(((t,e)=>t.contentRect.top-e.contentRect.top));for(const i of t){const t=+i.target.parentElement.getAttribute("data-item-index"),s=i.target.parentElement.clientHeight,n=i.contentRect.height;this.alreadyRenderedIndexes.has(t)&&(i.target.parentElement.style.height=n+"px",e+=this.scrollable&&this.getOffset(i.target.parentElement)<this.scrollable.scrollTop+e?n-s:0)}this.scrollable&&vt&&(this.scrollable.scrollTop+=e)},this.resizeObserver=new ResizeObserver(this.onResize),this.onMutation=()=>{[...this.itemsContainer.children].forEach((t=>{this.intersectionObserver.observe(t),this.resizeObserver.observe(t.children.item(0))}))},this.mutationObserver=new MutationObserver(this.onMutation)}get scrollable(){return this.internalScroll?this.internalScrollable:this.firstScrollableParent}render(){return K`
107
+ class Rt extends xt{constructor(t){if(super(t),this.it=H,t.type!==bt)throw Error(this.constructor.directiveName+"() can only be used in child bindings")}render(t){if(t===H||null==t)return this._t=void 0,this.it=t;if(t===D)return t;if("string"!=typeof t)throw Error(this.constructor.directiveName+"() called with a non-string value");if(t===this.it)return this._t;this.it=t;const e=[t];return e.raw=e,this._t={_$litType$:this.constructor.resultType,strings:e,values:[]}}}Rt.directiveName="unsafeHTML",Rt.resultType=1;const St=mt(Rt),Mt={padding:ht.create("--ft-infinite-scroll-padding","SIZE","0")},Ut=u`
108
+ .items-container {
109
+ position: relative;
110
+ padding: ${Mt.padding};
111
+ outline: none;
112
+ }
113
+
114
+ .scrollable {
115
+ height: 100%;
116
+ overflow-y: auto;
117
+ }
118
+
119
+ .item-container {
120
+ height: 100vh;
121
+ }
122
+
123
+ .item-container + .item-container {
124
+ /*
125
+ We add a gap between items to be sure to hide the content above the targeted item
126
+ When a div is visible (even by a fraction of a pixel) if its height changes
127
+ the browser will try to keep the scroll stable in relation to the first visible element
128
+ By adding this gap we ensure that the previous item will be fully hidden and event if its size changes, it will not impact the scroll offset
129
+ */
130
+ margin-top: 4px;
131
+ }
132
+
133
+ .scrollable .item-container {
134
+ height: 100%;
135
+ }
136
+
137
+ .resizable:not(.rendered) {
138
+ width: 0;
139
+ }
140
+ `;var kt=function(t,e,i,s){for(var n,o=arguments.length,r=o<3?e:null===s?s=Object.getOwnPropertyDescriptor(e,i):s,l=t.length-1;l>=0;l--)(n=t[l])&&(r=(o<3?n(r):o>3?n(e,i,r):n(e,i))||r);return o>3&&r&&Object.defineProperty(e,i,r),r};class Tt extends CustomEvent{constructor(t,e){super("visible-items-change",{detail:{visibleIndexes:t,visibleItems:e}})}}class At extends Event{constructor(){super("scrolled-to-target")}}class Ft extends ft{constructor(){super(...arguments),this.items=[],this.renderItem=()=>K``,this.internalScroll=!1,this.renderBeforeFirst=1,this.renderAfterLast=1,this.visibleItems=[],this.scrolledToTarget=!1,this.alreadyRenderedIndexes=new Set,this.scrollDebouncer=new e(5),this.onVisibilityChange=t=>{const e=t.filter((t=>t.intersectionRect.height>1)).map((t=>+t.target.attributes.getNamedItem("data-item-index").value)).filter((t=>!this.visibleItems.includes(t))),i=t.filter((t=>t.intersectionRect.height<=1)).map((t=>+t.target.attributes.getNamedItem("data-item-index").value)).filter((t=>this.visibleItems.includes(t))),s=[...this.visibleItems].filter((t=>!i.includes(t)));this.visibleItems=[...e,...s].sort(((t,e)=>t-e))},this.intersectionObserver=new IntersectionObserver(this.onVisibilityChange),this.onResize=t=>{this.triggerFindScrollableParent();let e=0;t=t.sort(((t,e)=>t.contentRect.top-e.contentRect.top));for(const i of t){const t=+i.target.parentElement.getAttribute("data-item-index"),s=i.target.parentElement.clientHeight,n=i.contentRect.height;this.alreadyRenderedIndexes.has(t)&&(i.target.parentElement.style.height=n+"px",e+=this.scrollable&&this.getOffset(i.target.parentElement)<this.scrollable.scrollTop+e?n-s:0)}this.scrollable&&vt&&(this.scrollable.scrollTop+=e)},this.resizeObserver=new ResizeObserver(this.onResize),this.onMutation=()=>{[...this.itemsContainer.children].forEach((t=>{this.intersectionObserver.observe(t),this.resizeObserver.observe(t.children.item(0))}))},this.mutationObserver=new MutationObserver(this.onMutation)}get scrollable(){return this.internalScroll?this.internalScrollable:this.firstScrollableParent}render(){return K`
108
141
  <div class="items-container ${this.internalScroll?"scrollable":""}"
109
142
  tabindex="-1"
110
143
  @find-scrollable-parent=${this.findScrollableParent}>
@@ -118,37 +151,4 @@ class Rt extends xt{constructor(t){if(super(t),this.it=H,t.type!==bt)throw Error
118
151
  ${s?(()=>{const i=this.renderItem(t,e);return"string"==typeof i?K`${St(i)}`:i})():null}
119
152
  </div>
120
153
  </div>
121
- `}resetScroll(){this.intersectionObserver.disconnect(),this.resizeObserver.disconnect(),this.visibleItems=[],this.scrolledToTarget=!1,this.scrollDebouncer.run((()=>{var t,e;let i=null!==(t=this.scrollToIndex)&&void 0!==t?t:this.scrollToItem?this.items.indexOf(this.scrollToItem):-1;i>=this.items.length&&(i=-1);let s=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector(`#item-${i}`);this.scrollToTarget(s),this.onMutation(),setTimeout((()=>{this.scrolledToTarget=!0}),10)}))}scrollToTarget(t){var e;if(t){let i=+(null!==(e=t.getAttribute("data-item-index"))&&void 0!==e?e:"0");this.scrollable?this.scrollable.scrollTop=i>0?this.getOffset(t)+1:0:t.scrollIntoView({block:"start"})}}getOffset(t){var e;let i=0,s=t;for(;s&&s.offsetParent!==this.scrollable.offsetParent;)i+=s.offsetTop,s=s.offsetParent;return i+(null!==(e=null==s?void 0:s.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.triggerFindScrollableParent(),this.intersectionObserver.disconnect(),this.intersectionObserver=new IntersectionObserver(this.onVisibilityChange,{rootMargin:"-2px",threshold:[0,.01,.1]}),this.mutationObserver.disconnect(),this.mutationObserver.observe(this.itemsContainer,{childList:!0})}),0)}triggerFindScrollableParent(){this.itemsContainer.dispatchEvent(new Event("find-scrollable-parent",{composed:!0}))}findScrollableParent(t){t.stopPropagation();for(let e of t.composedPath()){const t=e;if(t.clientHeight&&t.clientHeight<t.scrollHeight&&["auto","scroll"].includes(getComputedStyle(t).overflowY)){this.firstScrollableParent=t;break}}}disconnectedCallback(){super.disconnectedCallback(),this.intersectionObserver.disconnect(),this.resizeObserver.disconnect(),this.mutationObserver.disconnect()}firstUpdated(t){super.firstUpdated(t),this.resetScroll()}update(t){super.update(t),t.has("items")&&(this.alreadyRenderedIndexes=new Set),(t.has("scrollToItem")||t.has("scrollToIndex"))&&this.resetScroll()}updated(t){super.updated(t),(t.has("visibleItems")||t.has("items"))&&this.dispatchEvent(new kt(this.visibleItems,this.visibleItems.map((t=>this.items[t])))),t.has("scrolledToTarget")&&this.scrolledToTarget&&this.dispatchEvent(new Tt)}}var Ft;At.styles=u`
122
- .items-container {
123
- position: relative;
124
- padding: ${Ut.padding};
125
- outline: none;
126
- }
127
-
128
- .scrollable {
129
- height: 100%;
130
- overflow-y: auto;
131
- }
132
-
133
- .item-container {
134
- height: 100vh;
135
- }
136
-
137
- .item-container + .item-container {
138
- /*
139
- We add a gap between items to be sure to hide the content above the targeted item
140
- When a div is visible (even by a fraction of a pixel) if its height changes
141
- the browser will try to keep the scroll stable in relation to the first visible element
142
- By adding this gap we ensure that the previous item will be fully hidden and event if its size changes, it will not impact the scroll offset
143
- */
144
- margin-top: 4px;
145
- }
146
-
147
- .scrollable .item-container {
148
- height: 100%;
149
- }
150
-
151
- .resizable:not(.rendered) {
152
- width: 0;
153
- }
154
- `,Mt([s({type:Array})],At.prototype,"items",void 0),Mt([s({attribute:!1})],At.prototype,"renderItem",void 0),Mt([s({type:Object})],At.prototype,"scrollToItem",void 0),Mt([s({type:Number})],At.prototype,"scrollToIndex",void 0),Mt([s({type:Boolean})],At.prototype,"internalScroll",void 0),Mt([s({type:Number})],At.prototype,"renderBeforeFirst",void 0),Mt([s({type:Number})],At.prototype,"renderAfterLast",void 0),Mt([n({hasChanged:(t,e)=>null!=t&&null==e||t.length!==e.length||t[0]!==e[0]})],At.prototype,"visibleItems",void 0),Mt([o(".scrollable")],At.prototype,"internalScrollable",void 0),Mt([o(".items-container")],At.prototype,"itemsContainer",void 0),Mt([n()],At.prototype,"scrolledToTarget",void 0),(Ft="ft-infinite-scroll",t=>{window.customElements.get(Ft)||window.customElements.define(Ft,t)})(At),t.FtInfiniteScroll=At,t.FtInfiniteScrollCssVariables=Ut,t.ScrolledToTargetEvent=Tt,t.VisibleItemsChangeEvent=kt,Object.defineProperty(t,"i",{value:!0})}({});
154
+ `}resetScroll(){this.intersectionObserver.disconnect(),this.resizeObserver.disconnect(),this.visibleItems=[],this.scrolledToTarget=!1,this.scrollDebouncer.run((()=>{var t,e;let i=null!==(t=this.scrollToIndex)&&void 0!==t?t:this.scrollToItem?this.items.indexOf(this.scrollToItem):-1;i>=this.items.length&&(i=-1);let s=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector(`#item-${i}`);this.scrollToTarget(s),this.onMutation(),setTimeout((()=>{this.scrolledToTarget=!0}),10)}))}scrollToTarget(t){var e;if(t){let i=+(null!==(e=t.getAttribute("data-item-index"))&&void 0!==e?e:"0");this.scrollable?this.scrollable.scrollTop=i>0?this.getOffset(t)+1:0:t.scrollIntoView({block:"start"})}}getOffset(t){var e;let i=0,s=t;for(;s&&s.offsetParent!==this.scrollable.offsetParent;)i+=s.offsetTop,s=s.offsetParent;return i+(null!==(e=null==s?void 0:s.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.triggerFindScrollableParent(),this.intersectionObserver.disconnect(),this.intersectionObserver=new IntersectionObserver(this.onVisibilityChange,{rootMargin:"-2px",threshold:[0,.01,.1]}),this.mutationObserver.disconnect(),this.mutationObserver.observe(this.itemsContainer,{childList:!0})}),0)}triggerFindScrollableParent(){this.itemsContainer.dispatchEvent(new Event("find-scrollable-parent",{composed:!0}))}findScrollableParent(t){t.stopPropagation();for(let e of t.composedPath()){const t=e;if(t.clientHeight&&t.clientHeight<t.scrollHeight&&["auto","scroll"].includes(getComputedStyle(t).overflowY)){this.firstScrollableParent=t;break}}}disconnectedCallback(){super.disconnectedCallback(),this.intersectionObserver.disconnect(),this.resizeObserver.disconnect(),this.mutationObserver.disconnect()}firstUpdated(t){super.firstUpdated(t),this.resetScroll()}update(t){super.update(t),t.has("items")&&(this.alreadyRenderedIndexes=new Set),(t.has("scrollToItem")||t.has("scrollToIndex"))&&this.resetScroll()}updated(t){super.updated(t),(t.has("visibleItems")||t.has("items"))&&this.dispatchEvent(new Tt(this.visibleItems,this.visibleItems.map((t=>this.items[t])))),t.has("scrolledToTarget")&&this.scrolledToTarget&&this.dispatchEvent(new At)}}var Lt;Ft.styles=Ut,kt([s({type:Array})],Ft.prototype,"items",void 0),kt([s({attribute:!1})],Ft.prototype,"renderItem",void 0),kt([s({type:Object})],Ft.prototype,"scrollToItem",void 0),kt([s({type:Number})],Ft.prototype,"scrollToIndex",void 0),kt([s({type:Boolean})],Ft.prototype,"internalScroll",void 0),kt([s({type:Number})],Ft.prototype,"renderBeforeFirst",void 0),kt([s({type:Number})],Ft.prototype,"renderAfterLast",void 0),kt([n({hasChanged:(t,e)=>null!=t&&null==e||t.length!==e.length||t[0]!==e[0]})],Ft.prototype,"visibleItems",void 0),kt([o(".scrollable")],Ft.prototype,"internalScrollable",void 0),kt([o(".items-container")],Ft.prototype,"itemsContainer",void 0),kt([n()],Ft.prototype,"scrolledToTarget",void 0),(Lt="ft-infinite-scroll",t=>{window.customElements.get(Lt)||window.customElements.define(Lt,t)})(Ft),t.FtInfiniteScroll=Ft,t.FtInfiniteScrollCssVariables=Mt,t.ScrolledToTargetEvent=At,t.VisibleItemsChangeEvent=Tt,t.styles=Ut,Object.defineProperty(t,"i",{value:!0})}({});
@@ -0,0 +1,8 @@
1
+ import { TemplateResult } from "lit";
2
+ export interface FtInfiniteScrollProperties<T> {
3
+ items: Array<T>;
4
+ renderItem: (item: T, index: number) => TemplateResult | string;
5
+ scrollToItem?: T;
6
+ scrollToIndex?: number;
7
+ }
8
+ //# sourceMappingURL=ft-infinite-scroll.properties.d.ts.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ft-infinite-scroll.properties.js.map
package/build/index.d.ts CHANGED
@@ -1,2 +1,4 @@
1
+ export * from "./ft-infinite-scroll.css";
2
+ export * from "./ft-infinite-scroll.properties";
1
3
  export * from "./ft-infinite-scroll";
2
4
  //# sourceMappingURL=index.d.ts.map
package/build/index.js CHANGED
@@ -1,5 +1,7 @@
1
1
  import { customElement } from "@fluid-topics/ft-wc-utils";
2
2
  import { FtInfiniteScroll } from "./ft-infinite-scroll";
3
+ export * from "./ft-infinite-scroll.css";
4
+ export * from "./ft-infinite-scroll.properties";
3
5
  export * from "./ft-infinite-scroll";
4
6
  customElement("ft-infinite-scroll")(FtInfiniteScroll);
5
7
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluid-topics/ft-infinite-scroll",
3
- "version": "0.3.11",
3
+ "version": "0.3.13",
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": "0.3.11",
22
+ "@fluid-topics/ft-wc-utils": "0.3.13",
23
23
  "lit": "2.2.8"
24
24
  },
25
- "gitHead": "35c790329a8e7f9902aad2ea8d41386e5c0b36c9"
25
+ "gitHead": "84b5fc920bc5d2bdb646b5da8815ad51caaf228e"
26
26
  }