jb-infinite-scroll 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +135 -0
  3. package/dist/jb-infinite-scroll.cjs.js +2 -0
  4. package/dist/jb-infinite-scroll.cjs.js.br +0 -0
  5. package/dist/jb-infinite-scroll.cjs.js.gz +0 -0
  6. package/dist/jb-infinite-scroll.cjs.js.map +1 -0
  7. package/dist/jb-infinite-scroll.js +2 -0
  8. package/dist/jb-infinite-scroll.js.br +0 -0
  9. package/dist/jb-infinite-scroll.js.gz +0 -0
  10. package/dist/jb-infinite-scroll.js.map +1 -0
  11. package/dist/jb-infinite-scroll.umd.js +2 -0
  12. package/dist/jb-infinite-scroll.umd.js.br +0 -0
  13. package/dist/jb-infinite-scroll.umd.js.gz +0 -0
  14. package/dist/jb-infinite-scroll.umd.js.map +1 -0
  15. package/dist/web-component/jb-infinite-scroll/lib/Types.d.ts +11 -0
  16. package/dist/web-component/jb-infinite-scroll/lib/jb-infinite-scroll.d.ts +36 -0
  17. package/index.js +1 -0
  18. package/lib/jb-infinite-scroll.html +19 -0
  19. package/lib/jb-infinite-scroll.scss +44 -0
  20. package/lib/jb-infinite-scroll.ts +236 -0
  21. package/lib/types.ts +14 -0
  22. package/package.json +35 -0
  23. package/react/LICENSE +21 -0
  24. package/react/README.md +2 -0
  25. package/react/dist/JBInfiniteScroll.cjs.js +92 -0
  26. package/react/dist/JBInfiniteScroll.cjs.js.map +1 -0
  27. package/react/dist/JBInfiniteScroll.js +86 -0
  28. package/react/dist/JBInfiniteScroll.js.map +1 -0
  29. package/react/dist/JBInfiniteScroll.umd.js +95 -0
  30. package/react/dist/JBInfiniteScroll.umd.js.map +1 -0
  31. package/react/dist/common/hooks/use-event.d.ts +3 -0
  32. package/react/dist/common/hooks/useLazyRef.d.ts +4 -0
  33. package/react/dist/common/hooks/useMobx.d.ts +4 -0
  34. package/react/dist/common/scripts/device-detection.d.ts +1 -0
  35. package/react/dist/common/scripts/persian-helper.d.ts +3 -0
  36. package/react/dist/web-component/jb-infinite-scroll/react/lib/JBInfiniteScroll.d.ts +33 -0
  37. package/react/index.js +1 -0
  38. package/react/lib/JBInfiniteScroll.tsx +107 -0
  39. package/react/package.json +33 -0
  40. package/react/tsconfig.json +18 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2020 javad
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,135 @@
1
+ # jb-infinite-scroll
2
+
3
+ [![Published on webcomponents.org](https://img.shields.io/badge/webcomponents.org-published-blue.svg)](https://www.webcomponents.org/element/jb-infinite-scroll)
4
+ [![GitHub license](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://raw.githubusercontent.com/javadbat/jb-infinite-scroll/main/LICENSE)
5
+ [![NPM Downloads](https://img.shields.io/npm/dw/jb-infinite-scroll)](https://www.npmjs.com/package/jb-infinite-scroll)
6
+
7
+ Infinite scroll web-component with additional features including:
8
+
9
+ - custom list ui
10
+ - empty list state and custom empty list ui
11
+ - end of the list state
12
+ - enable/disable scroll capture
13
+ - support loading state with customizable ui
14
+
15
+ ## installation
16
+ ```js
17
+ import "jb-infinite-scroll" from jb-infinite-scroll;
18
+ ```
19
+ ## usage
20
+ ```html
21
+
22
+ <jb-infinite-scroll></jb-infinite-scroll>
23
+
24
+ ```
25
+
26
+ ## instruction
27
+
28
+ ### show content
29
+
30
+ you can show your content by placing any element with slot attribute `slot="infinite-scroll-content"` like the example below:
31
+
32
+ ```html
33
+ <jb-infinite-scroll>
34
+ <div slot="infinite-scroll-content">
35
+ <div>item 1</div>
36
+ <div>item 2</div>
37
+ <div>item 3</div>
38
+ </div>
39
+ </jb-infinite-scroll>
40
+
41
+ ```
42
+
43
+ ### set loading
44
+
45
+ you can show loading by setting `is-loading ="true"` attribute or `isLoading` property.
46
+
47
+ ```js
48
+ const jbInfiniteScroll = document.getElementByTagName('jb-infinite-scroll');
49
+ jbInfiniteScroll.isLoading = true;
50
+ ```
51
+ you can also set your own loading ui by adding a slot with `slot="loading-content"` like the example below:
52
+
53
+ ```html
54
+ <jb-infinite-scroll is-loading="true">
55
+ <div slot="loading-content">
56
+ <p>your loading</p>
57
+ </div>
58
+ </jb-infinite-scroll>
59
+
60
+ ```
61
+
62
+ ### set list empty
63
+
64
+ if there is no data to show you can set `is-list-empty = "true"`.
65
+
66
+ ```js
67
+ const jbInfiniteScroll = document.getElementByTagName('jb-infinite-scroll');
68
+ jbInfiniteScroll.isListEmpty = true;
69
+ ```
70
+ you can set your own empty list ui by adding a slot with `slot="empty-list-content"` like the example below:
71
+ ```html
72
+ <jb-infinite-scroll is-list-empty="true">
73
+ <div slot="empty-list-content">
74
+ <p>list is empty</p>
75
+ </div>
76
+ </jb-infinite-scroll>
77
+
78
+ ```
79
+ ### set list ended
80
+ if there is no more data to show you can set `is-list-ended = "true"`.this disables scroll capturing and `scrollEnd` event won't be called after.
81
+
82
+ ```js
83
+ const jbInfiniteScroll = document.getElementByTagName('jb-infinite-scroll');
84
+ jbInfiniteScroll.isListEnded = true;
85
+ ```
86
+ ```html
87
+ <jb-infinite-scroll is-list-ended="true">
88
+ </jb-infinite-scroll>
89
+
90
+ ```
91
+
92
+ ### disable scroll capture
93
+ in some cases if you want to disable capture scroll you can set `disable-capture-scroll = "true"`'
94
+
95
+ ```js
96
+ const InfiniteScroll = document.getElementByTagName('jb-infinite-scroll');
97
+ InfiniteScroll.disableCaptureScroll = true;
98
+ ```
99
+
100
+
101
+ ### add scroll callback
102
+ you can add your onscroll callback function to `scrollEnd` event listener.
103
+
104
+ if `is-loading` ,`is-list-empty` ,`is-list-ended` or `disable-capture-scroll` is true the callback function won't be executed.
105
+
106
+ ```js
107
+ const InfiniteScroll = document.getElementByTagName('jb-infinite-scroll');
108
+ jbInfiniteScroll.addEventListener('scrollEnd',() => {
109
+ //load your content here
110
+ console.log('scroll');
111
+ })
112
+ ```
113
+
114
+ ### state-change-waiting-behavior
115
+
116
+ by default `state-change-waiting-behavior` is `FORCE_WAIT` thats means when an scroll event fires,scroll is not captured until on of the `is-loading` ,`is-list-empty` ,`is-list-ended` states updates.
117
+ if you want to change this behavior you can set `state-change-waiting-behavior` to `NO_WAIT`. thats means the scroll callback in not dependent on `is-loading`,`is-list-empty`,`is-list-ended` state update.
118
+
119
+
120
+ ### usage overview
121
+ ```html
122
+ <jb-infinite-scroll is-list-empty="true" is-loading="true">
123
+ <div slot="infinite-scroll-content">
124
+ <div>item 1</div>
125
+ <div>item 2</div>
126
+ <div>item 3</div>
127
+ </div>
128
+ <div slot="empty-list-content">
129
+ <p>list is empty</p>
130
+ </div>
131
+ <div slot="loading-content">
132
+ <p>loading</p>
133
+ </div>
134
+ </jb-infinite-scroll>
135
+ ```
@@ -0,0 +1,2 @@
1
+ "use strict";function t(t,e,n,i){if("a"===n&&!i)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof e?t!==e||!i:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===n?i:"a"===n?i.call(t):i?i.value:e.get(t)}function e(t,e,n,i,s){if("m"===i)throw new TypeError("Private method is not writable");if("a"===i&&!s)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof e?t!==e||!s:!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===i?s.call(t,n):s?s.value=n:e.set(t,n),n}require("jb-loading"),"function"==typeof SuppressedError&&SuppressedError;var n,i,s,a,r,o,l,c,h;exports.StateChangeWaitingBehavior=void 0,(n=exports.StateChangeWaitingBehavior||(exports.StateChangeWaitingBehavior={})).forceWait="FORCE_WAIT",n.noWait="NO_WAIT";class p extends HTMLElement{constructor(){super(),i.set(this,!1),s.set(this,0),a.set(this,!1),r.set(this,!1),o.set(this,!1),l.set(this,!1),c.set(this,!1),h.set(this,exports.StateChangeWaitingBehavior.forceWait),this.initWebComponent()}mapStateChangeWaitingBehavior(t){switch(t){case"FORCE_WAIT":default:return exports.StateChangeWaitingBehavior.forceWait;case"NO_WAIT":return exports.StateChangeWaitingBehavior.noWait}}set stateChangeWaitingBehavior(t){e(this,h,this.mapStateChangeWaitingBehavior(t),"f")}get stateChangeWaitingBehavior(){return t(this,h,"f")}get disableCaptureScroll(){return t(this,l,"f")}set disableCaptureScroll(t){e(this,l,t,"f"),this.setIsWaitingForStatChange(!1)}get isListEnded(){return t(this,r,"f")}set isListEnded(t){e(this,r,t,"f"),this.setIsWaitingForStatChange(!1)}get isLoading(){return t(this,i,"f")}set isLoading(t){e(this,i,t,"f"),this.setIsWaitingForStatChange(!1),t?this.elements?.loading.classList.add("--show"):(this.elements?.loading.classList.remove("--show"),this.checkEmptyListState(),this.checkScrollHeight())}get isListEmpty(){return t(this,c,"f")}set isListEmpty(t){e(this,c,t,"f"),this.setIsWaitingForStatChange(!1)}get isLastPage(){return t(this,a,"f")}set isLastPage(t){e(this,a,t,"f")}checkEmptyListState(){t(this,c,"f")?(this.elements?.emptyListWrapper.classList.add("--show"),this.elements?.contentWrapper.classList.remove("--show")):(this.elements?.contentWrapper.classList.add("--show"),this.elements?.emptyListWrapper.classList.remove("--show"))}connectedCallback(){this.callOnLoadEvent(),this.initProp(),this.callOnInitEvent()}callOnLoadEvent(){const t=new CustomEvent("load",{bubbles:!0,composed:!0});this.dispatchEvent(t)}callOnInitEvent(){const t=new CustomEvent("init",{bubbles:!0,composed:!0});this.dispatchEvent(t)}initWebComponent(){const t=this.attachShadow({mode:"open"}),e=document.createElement("template");e.innerHTML='<style>.infinite-scroll-component {\n height: 100%;\n display: grid;\n grid-template-rows: auto 1fr;\n}\n.infinite-scroll-component .content-wrapper {\n width: 100%;\n height: auto;\n display: none;\n overflow: auto;\n}\n.infinite-scroll-component .content-wrapper.--show {\n display: inline-block;\n}\n.infinite-scroll-component .empty-list-wrapper {\n width: 100%;\n height: 100%;\n display: none;\n}\n.infinite-scroll-component .empty-list-wrapper.--show {\n display: flex;\n justify-content: center;\n align-items: center;\n}\n.infinite-scroll-component .loading-wrapper {\n display: none;\n --jb-loading-color: var(--captcha-component-loading-color, #1565D8);\n}\n.infinite-scroll-component .loading-wrapper .default-loading {\n width: 40px;\n height: 40px;\n margin: 0 auto;\n}\n.infinite-scroll-component .loading-wrapper.--show {\n display: inline-block;\n}</style>\n<div class="infinite-scroll-component">\r\n <div class="content-wrapper" part="content-wrapper">\r\n <slot name="infinite-scroll-content"></slot>\r\n </div>\r\n <div class="empty-list-wrapper" part="empty-list-wrapper">\r\n <slot name="empty-list-content">\r\n <div class="default-empty-list">\r\n <p>empty list</p>\r\n </div>\r\n </slot>\r\n </div>\r\n <div class="loading-wrapper" part="loading-wrapper">\r\n <slot name="loading-content">\r\n <div class="default-loading">\r\n <jb-loading></jb-loading>\r\n </div>\r\n </slot>\r\n </div>\r\n</div>',t.appendChild(e.content.cloneNode(!0)),this.elements={loading:t.querySelector(".loading-wrapper"),componentWrapper:t.querySelector(".Infinite-scroll-component"),contentWrapper:t.querySelector(".content-wrapper"),loadingWrapper:t.querySelector(".loading-wrapper"),emptyListWrapper:t.querySelector(".empty-list-wrapper")}}registerEventListener(){this.elements.contentWrapper.addEventListener("scroll",this.onScroll.bind(this),{passive:!0})}initProp(){this.registerEventListener(),this.checkScrollHeight()}checkScrollHeight(){const{scrollHeight:t,clientHeight:e}=this.elements.contentWrapper;t<=e&&this.canCaptureScroll&&this.onScrollEnd()}onScrollEnd(){this.setIsWaitingForStatChange(!0);const t=new CustomEvent("scrollEnd");this.dispatchEvent(t)}onScroll(){const{scrollTop:e,scrollHeight:n,clientHeight:i}=this.elements.contentWrapper;e+i+t(this,s,"f")>=n&&this.canCaptureScroll&&this.onScrollEnd()}setIsWaitingForStatChange(n){if(n)if(t(this,h,"f")===exports.StateChangeWaitingBehavior.forceWait)e(this,o,!0,"f");else if(t(this,h,"f")===exports.StateChangeWaitingBehavior.noWait)return;e(this,o,!1,"f")}get canCaptureScroll(){return!(t(this,i,"f")||t(this,c,"f")||t(this,r,"f")||t(this,o,"f")||t(this,l,"f"))}static get observedAttributes(){return["is-loading","is-list-empty","is-list-ended","disable-capture-scroll","state-change-waiting-behavior"]}attributeChangedCallback(t,e,n){this.onAttributeChange(t,n)}onAttributeChange(t,n){switch(t){case"is-loading":this.isLoading="true"===n;break;case"is-list-empty":this.isListEmpty="true"===n;break;case"is-list-ended":e(this,r,"true"===n,"f");break;case"disable-capture-scroll":e(this,l,"true"===n,"f");break;case"state-change-waiting-behavior":e(this,h,this.mapStateChangeWaitingBehavior(n),"f")}}}i=new WeakMap,s=new WeakMap,a=new WeakMap,r=new WeakMap,o=new WeakMap,l=new WeakMap,c=new WeakMap,h=new WeakMap;!customElements.get("jb-infinite-scroll")&&window.customElements.define("jb-infinite-scroll",p),exports.JBInfiniteScrollWebComponent=p;
2
+ //# sourceMappingURL=jb-infinite-scroll.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jb-infinite-scroll.cjs.js","sources":["../lib/types.ts","../lib/jb-infinite-scroll.ts"],"sourcesContent":["export type Elements = {\r\n loading: HTMLDivElement,\r\n contentWrapper: HTMLDivElement,\r\n componentWrapper: HTMLDivElement,\r\n emptyListWrapper: HTMLDivElement,\r\n loadingWrapper: HTMLDivElement,\r\n}\r\n\r\nexport enum StateChangeWaitingBehavior {\r\n // when user scroll we lock event call and wait for user to change isLoading (good for React or any other ui framework solution)\r\n forceWait = \"FORCE_WAIT\",\r\n // when user scroll we dont lock its event listener and developer should handle extra scroll by it self (good for pure js solution)\r\n noWait = \"NO_WAIT\",\r\n}","import HTML from './jb-infinite-scroll.html';\r\nimport CSS from './jb-infinite-scroll.scss';\r\nimport { Elements, StateChangeWaitingBehavior } from './types.js';\r\nimport \"jb-loading\";\r\n\r\nexport * from \"./types.js\";\r\n\r\nexport class JBInfiniteScrollWebComponent extends HTMLElement {\r\n elements!: Elements;\r\n #isLoading = false;\r\n //the amount of space that we listen to for trigger refresh \r\n #endPageGap = 0;\r\n #isLastPage = false;\r\n\r\n #isListEnded = false;\r\n //used when user scroll and we dont want to capture multiple scroll at one and wait for prev scroll event to finish\r\n #isWaitingForStateChange = false;\r\n #disableCaptureScroll = false;\r\n #isListEmpty = false;\r\n #stateChangeWaitingBehavior: StateChangeWaitingBehavior = StateChangeWaitingBehavior.forceWait;\r\n\r\n\r\n constructor() {\r\n super();\r\n this.initWebComponent();\r\n }\r\n mapStateChangeWaitingBehavior(state: string) {\r\n switch (state) {\r\n case \"FORCE_WAIT\":\r\n return StateChangeWaitingBehavior.forceWait;\r\n case \"NO_WAIT\":\r\n return StateChangeWaitingBehavior.noWait;\r\n\r\n default:\r\n return StateChangeWaitingBehavior.forceWait;\r\n\r\n }\r\n\r\n }\r\n set stateChangeWaitingBehavior(value: string) {\r\n this.#stateChangeWaitingBehavior = this.mapStateChangeWaitingBehavior(value);\r\n }\r\n get stateChangeWaitingBehavior() {\r\n return this.#stateChangeWaitingBehavior;\r\n }\r\n get disableCaptureScroll() {\r\n return this.#disableCaptureScroll;\r\n }\r\n\r\n set disableCaptureScroll(value: boolean) {\r\n this.#disableCaptureScroll = value;\r\n this.setIsWaitingForStatChange(false);\r\n }\r\n get isListEnded() {\r\n return this.#isListEnded;\r\n }\r\n set isListEnded(value: boolean) {\r\n this.#isListEnded = value;\r\n this.setIsWaitingForStatChange(false);\r\n\r\n }\r\n get isLoading() {\r\n return this.#isLoading;\r\n }\r\n set isLoading(value: boolean) {\r\n this.#isLoading = value;\r\n this.setIsWaitingForStatChange(false);\r\n if (value) {\r\n this.elements?.loading.classList.add('--show');\r\n } else {\r\n this.elements?.loading.classList.remove('--show');\r\n this.checkEmptyListState();\r\n this.checkScrollHeight();\r\n }\r\n }\r\n get isListEmpty() {\r\n return this.#isListEmpty;\r\n }\r\n set isListEmpty(value: boolean) {\r\n this.#isListEmpty = value;\r\n this.setIsWaitingForStatChange(false);\r\n\r\n\r\n }\r\n get isLastPage() {\r\n return this.#isLastPage;\r\n }\r\n set isLastPage(value: boolean) {\r\n this.#isLastPage = value;\r\n }\r\n checkEmptyListState() {\r\n if (this.#isListEmpty) {\r\n this.elements?.emptyListWrapper.classList.add('--show');\r\n this.elements?.contentWrapper.classList.remove('--show');\r\n\r\n } else {\r\n this.elements?.contentWrapper.classList.add('--show');\r\n this.elements?.emptyListWrapper.classList.remove('--show');\r\n\r\n }\r\n }\r\n connectedCallback() {\r\n // standard web component event that called when all of dom is bounded\r\n this.callOnLoadEvent();\r\n this.initProp();\r\n this.callOnInitEvent();\r\n\r\n }\r\n callOnLoadEvent() {\r\n const event = new CustomEvent('load', { bubbles: true, composed: true });\r\n this.dispatchEvent(event);\r\n }\r\n callOnInitEvent() {\r\n const event = new CustomEvent('init', { bubbles: true, composed: true });\r\n this.dispatchEvent(event);\r\n }\r\n initWebComponent() {\r\n const shadowRoot = this.attachShadow({\r\n mode: 'open'\r\n });\r\n const html = `<style>${CSS}</style>` + '\\n' + HTML;\r\n const element = document.createElement('template');\r\n element.innerHTML = html;\r\n shadowRoot.appendChild(element.content.cloneNode(true));\r\n this.elements = {\r\n loading: shadowRoot.querySelector('.loading-wrapper')!,\r\n componentWrapper: shadowRoot.querySelector('.Infinite-scroll-component')!,\r\n contentWrapper: shadowRoot.querySelector('.content-wrapper')!,\r\n loadingWrapper: shadowRoot.querySelector('.loading-wrapper')!,\r\n emptyListWrapper: shadowRoot.querySelector('.empty-list-wrapper')!,\r\n };\r\n\r\n }\r\n registerEventListener() {\r\n this.elements.contentWrapper.addEventListener('scroll', this.onScroll.bind(this), { passive: true });\r\n }\r\n initProp() {\r\n this.registerEventListener();\r\n this.checkScrollHeight();\r\n }\r\n checkScrollHeight() {\r\n //check if our container is bigger than our content we call scroll end event\r\n const { scrollHeight, clientHeight } = this.elements.contentWrapper;\r\n if (scrollHeight <= clientHeight && this.canCaptureScroll) {\r\n this.onScrollEnd();\r\n }\r\n }\r\n onScrollEnd() { \r\n this.setIsWaitingForStatChange(true);\r\n const event = new CustomEvent('scrollEnd');\r\n this.dispatchEvent(event);\r\n }\r\n onScroll() {\r\n const { scrollTop, scrollHeight, clientHeight } = this.elements.contentWrapper;\r\n if (scrollTop + clientHeight + this.#endPageGap >= scrollHeight) {\r\n if (this.canCaptureScroll) {\r\n this.onScrollEnd();\r\n }\r\n }\r\n }\r\n setIsWaitingForStatChange(isWaitingStatus: boolean) {\r\n\r\n if (isWaitingStatus) {\r\n if (this.#stateChangeWaitingBehavior === StateChangeWaitingBehavior.forceWait) {\r\n this.#isWaitingForStateChange = true;\r\n } else if (this.#stateChangeWaitingBehavior === StateChangeWaitingBehavior.noWait) {\r\n return;\r\n }\r\n }\r\n this.#isWaitingForStateChange = false;\r\n\r\n\r\n\r\n }\r\n get canCaptureScroll() {\r\n if (!(this.#isLoading || this.#isListEmpty || this.#isListEnded || this.#isWaitingForStateChange || this.#disableCaptureScroll)) {\r\n return true;\r\n\r\n }\r\n return false;\r\n }\r\n\r\n static get observedAttributes() {\r\n return ['is-loading', 'is-list-empty', 'is-list-ended', 'disable-capture-scroll', 'state-change-waiting-behavior'];\r\n }\r\n attributeChangedCallback(name: string, oldValue: string, newValue: string) {\r\n // do something when an attribute has changed\r\n this.onAttributeChange(name, newValue);\r\n }\r\n onAttributeChange(name: string, value: string) {\r\n switch (name) {\r\n case 'is-loading':\r\n if (value === 'true') {\r\n this.isLoading = true;\r\n } else {\r\n this.isLoading = false;\r\n }\r\n break;\r\n case 'is-list-empty':\r\n if (value === 'true') {\r\n this.isListEmpty = true;\r\n } else {\r\n this.isListEmpty = false;\r\n\r\n }\r\n break;\r\n case 'is-list-ended':\r\n if (value === 'true') {\r\n this.#isListEnded = true;\r\n } else {\r\n this.#isListEnded = false;\r\n\r\n }\r\n break;\r\n\r\n case 'disable-capture-scroll':\r\n if (value === 'true') {\r\n this.#disableCaptureScroll = true;\r\n } else {\r\n this.#disableCaptureScroll = false;\r\n\r\n }\r\n break;\r\n case 'state-change-waiting-behavior':\r\n this.#stateChangeWaitingBehavior = this.mapStateChangeWaitingBehavior(value);\r\n break;\r\n\r\n\r\n }\r\n\r\n }\r\n}\r\nconst myElementNotExists = !customElements.get('jb-infinite-scroll');\r\nif (myElementNotExists) {\r\n window.customElements.define('jb-infinite-scroll', JBInfiniteScrollWebComponent);\r\n}\r\n"],"names":["StateChangeWaitingBehavior","JBInfiniteScrollWebComponent","HTMLElement","constructor","super","_JBInfiniteScrollWebComponent_isLoading","set","this","_JBInfiniteScrollWebComponent_endPageGap","_JBInfiniteScrollWebComponent_isLastPage","_JBInfiniteScrollWebComponent_isListEnded","_JBInfiniteScrollWebComponent_isWaitingForStateChange","_JBInfiniteScrollWebComponent_disableCaptureScroll","_JBInfiniteScrollWebComponent_isListEmpty","_JBInfiniteScrollWebComponent_stateChangeWaitingBehavior","forceWait","initWebComponent","mapStateChangeWaitingBehavior","state","noWait","stateChangeWaitingBehavior","value","__classPrivateFieldSet","__classPrivateFieldGet","disableCaptureScroll","setIsWaitingForStatChange","isListEnded","isLoading","elements","loading","classList","add","remove","checkEmptyListState","checkScrollHeight","isListEmpty","isLastPage","emptyListWrapper","contentWrapper","connectedCallback","callOnLoadEvent","initProp","callOnInitEvent","event","CustomEvent","bubbles","composed","dispatchEvent","shadowRoot","attachShadow","mode","element","document","createElement","innerHTML","appendChild","content","cloneNode","querySelector","componentWrapper","loadingWrapper","registerEventListener","addEventListener","onScroll","bind","passive","scrollHeight","clientHeight","canCaptureScroll","onScrollEnd","scrollTop","isWaitingStatus","observedAttributes","attributeChangedCallback","name","oldValue","newValue","onAttributeChange","customElements","get","window","define"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import"jb-loading";function t(t,e,n,i){if("a"===n&&!i)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof e?t!==e||!i:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===n?i:"a"===n?i.call(t):i?i.value:e.get(t)}function e(t,e,n,i,s){if("m"===i)throw new TypeError("Private method is not writable");if("a"===i&&!s)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof e?t!==e||!s:!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===i?s.call(t,n):s?s.value=n:e.set(t,n),n}"function"==typeof SuppressedError&&SuppressedError;var n,i,s,r,a,o,l,c,p;!function(t){t.forceWait="FORCE_WAIT",t.noWait="NO_WAIT"}(n||(n={}));class h extends HTMLElement{constructor(){super(),i.set(this,!1),s.set(this,0),r.set(this,!1),a.set(this,!1),o.set(this,!1),l.set(this,!1),c.set(this,!1),p.set(this,n.forceWait),this.initWebComponent()}mapStateChangeWaitingBehavior(t){switch(t){case"FORCE_WAIT":default:return n.forceWait;case"NO_WAIT":return n.noWait}}set stateChangeWaitingBehavior(t){e(this,p,this.mapStateChangeWaitingBehavior(t),"f")}get stateChangeWaitingBehavior(){return t(this,p,"f")}get disableCaptureScroll(){return t(this,l,"f")}set disableCaptureScroll(t){e(this,l,t,"f"),this.setIsWaitingForStatChange(!1)}get isListEnded(){return t(this,a,"f")}set isListEnded(t){e(this,a,t,"f"),this.setIsWaitingForStatChange(!1)}get isLoading(){return t(this,i,"f")}set isLoading(t){e(this,i,t,"f"),this.setIsWaitingForStatChange(!1),t?this.elements?.loading.classList.add("--show"):(this.elements?.loading.classList.remove("--show"),this.checkEmptyListState(),this.checkScrollHeight())}get isListEmpty(){return t(this,c,"f")}set isListEmpty(t){e(this,c,t,"f"),this.setIsWaitingForStatChange(!1)}get isLastPage(){return t(this,r,"f")}set isLastPage(t){e(this,r,t,"f")}checkEmptyListState(){t(this,c,"f")?(this.elements?.emptyListWrapper.classList.add("--show"),this.elements?.contentWrapper.classList.remove("--show")):(this.elements?.contentWrapper.classList.add("--show"),this.elements?.emptyListWrapper.classList.remove("--show"))}connectedCallback(){this.callOnLoadEvent(),this.initProp(),this.callOnInitEvent()}callOnLoadEvent(){const t=new CustomEvent("load",{bubbles:!0,composed:!0});this.dispatchEvent(t)}callOnInitEvent(){const t=new CustomEvent("init",{bubbles:!0,composed:!0});this.dispatchEvent(t)}initWebComponent(){const t=this.attachShadow({mode:"open"}),e=document.createElement("template");e.innerHTML='<style>.infinite-scroll-component {\n height: 100%;\n display: grid;\n grid-template-rows: auto 1fr;\n}\n.infinite-scroll-component .content-wrapper {\n width: 100%;\n height: auto;\n display: none;\n overflow: auto;\n}\n.infinite-scroll-component .content-wrapper.--show {\n display: inline-block;\n}\n.infinite-scroll-component .empty-list-wrapper {\n width: 100%;\n height: 100%;\n display: none;\n}\n.infinite-scroll-component .empty-list-wrapper.--show {\n display: flex;\n justify-content: center;\n align-items: center;\n}\n.infinite-scroll-component .loading-wrapper {\n display: none;\n --jb-loading-color: var(--captcha-component-loading-color, #1565D8);\n}\n.infinite-scroll-component .loading-wrapper .default-loading {\n width: 40px;\n height: 40px;\n margin: 0 auto;\n}\n.infinite-scroll-component .loading-wrapper.--show {\n display: inline-block;\n}</style>\n<div class="infinite-scroll-component">\r\n <div class="content-wrapper" part="content-wrapper">\r\n <slot name="infinite-scroll-content"></slot>\r\n </div>\r\n <div class="empty-list-wrapper" part="empty-list-wrapper">\r\n <slot name="empty-list-content">\r\n <div class="default-empty-list">\r\n <p>empty list</p>\r\n </div>\r\n </slot>\r\n </div>\r\n <div class="loading-wrapper" part="loading-wrapper">\r\n <slot name="loading-content">\r\n <div class="default-loading">\r\n <jb-loading></jb-loading>\r\n </div>\r\n </slot>\r\n </div>\r\n</div>',t.appendChild(e.content.cloneNode(!0)),this.elements={loading:t.querySelector(".loading-wrapper"),componentWrapper:t.querySelector(".Infinite-scroll-component"),contentWrapper:t.querySelector(".content-wrapper"),loadingWrapper:t.querySelector(".loading-wrapper"),emptyListWrapper:t.querySelector(".empty-list-wrapper")}}registerEventListener(){this.elements.contentWrapper.addEventListener("scroll",this.onScroll.bind(this),{passive:!0})}initProp(){this.registerEventListener(),this.checkScrollHeight()}checkScrollHeight(){const{scrollHeight:t,clientHeight:e}=this.elements.contentWrapper;t<=e&&this.canCaptureScroll&&this.onScrollEnd()}onScrollEnd(){this.setIsWaitingForStatChange(!0);const t=new CustomEvent("scrollEnd");this.dispatchEvent(t)}onScroll(){const{scrollTop:e,scrollHeight:n,clientHeight:i}=this.elements.contentWrapper;e+i+t(this,s,"f")>=n&&this.canCaptureScroll&&this.onScrollEnd()}setIsWaitingForStatChange(i){if(i)if(t(this,p,"f")===n.forceWait)e(this,o,!0,"f");else if(t(this,p,"f")===n.noWait)return;e(this,o,!1,"f")}get canCaptureScroll(){return!(t(this,i,"f")||t(this,c,"f")||t(this,a,"f")||t(this,o,"f")||t(this,l,"f"))}static get observedAttributes(){return["is-loading","is-list-empty","is-list-ended","disable-capture-scroll","state-change-waiting-behavior"]}attributeChangedCallback(t,e,n){this.onAttributeChange(t,n)}onAttributeChange(t,n){switch(t){case"is-loading":this.isLoading="true"===n;break;case"is-list-empty":this.isListEmpty="true"===n;break;case"is-list-ended":e(this,a,"true"===n,"f");break;case"disable-capture-scroll":e(this,l,"true"===n,"f");break;case"state-change-waiting-behavior":e(this,p,this.mapStateChangeWaitingBehavior(n),"f")}}}i=new WeakMap,s=new WeakMap,r=new WeakMap,a=new WeakMap,o=new WeakMap,l=new WeakMap,c=new WeakMap,p=new WeakMap;!customElements.get("jb-infinite-scroll")&&window.customElements.define("jb-infinite-scroll",h);export{h as JBInfiniteScrollWebComponent,n as StateChangeWaitingBehavior};
2
+ //# sourceMappingURL=jb-infinite-scroll.js.map
Binary file
Binary file
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jb-infinite-scroll.js","sources":["../lib/types.ts","../lib/jb-infinite-scroll.ts"],"sourcesContent":["export type Elements = {\r\n loading: HTMLDivElement,\r\n contentWrapper: HTMLDivElement,\r\n componentWrapper: HTMLDivElement,\r\n emptyListWrapper: HTMLDivElement,\r\n loadingWrapper: HTMLDivElement,\r\n}\r\n\r\nexport enum StateChangeWaitingBehavior {\r\n // when user scroll we lock event call and wait for user to change isLoading (good for React or any other ui framework solution)\r\n forceWait = \"FORCE_WAIT\",\r\n // when user scroll we dont lock its event listener and developer should handle extra scroll by it self (good for pure js solution)\r\n noWait = \"NO_WAIT\",\r\n}","import HTML from './jb-infinite-scroll.html';\r\nimport CSS from './jb-infinite-scroll.scss';\r\nimport { Elements, StateChangeWaitingBehavior } from './types.js';\r\nimport \"jb-loading\";\r\n\r\nexport * from \"./types.js\";\r\n\r\nexport class JBInfiniteScrollWebComponent extends HTMLElement {\r\n elements!: Elements;\r\n #isLoading = false;\r\n //the amount of space that we listen to for trigger refresh \r\n #endPageGap = 0;\r\n #isLastPage = false;\r\n\r\n #isListEnded = false;\r\n //used when user scroll and we dont want to capture multiple scroll at one and wait for prev scroll event to finish\r\n #isWaitingForStateChange = false;\r\n #disableCaptureScroll = false;\r\n #isListEmpty = false;\r\n #stateChangeWaitingBehavior: StateChangeWaitingBehavior = StateChangeWaitingBehavior.forceWait;\r\n\r\n\r\n constructor() {\r\n super();\r\n this.initWebComponent();\r\n }\r\n mapStateChangeWaitingBehavior(state: string) {\r\n switch (state) {\r\n case \"FORCE_WAIT\":\r\n return StateChangeWaitingBehavior.forceWait;\r\n case \"NO_WAIT\":\r\n return StateChangeWaitingBehavior.noWait;\r\n\r\n default:\r\n return StateChangeWaitingBehavior.forceWait;\r\n\r\n }\r\n\r\n }\r\n set stateChangeWaitingBehavior(value: string) {\r\n this.#stateChangeWaitingBehavior = this.mapStateChangeWaitingBehavior(value);\r\n }\r\n get stateChangeWaitingBehavior() {\r\n return this.#stateChangeWaitingBehavior;\r\n }\r\n get disableCaptureScroll() {\r\n return this.#disableCaptureScroll;\r\n }\r\n\r\n set disableCaptureScroll(value: boolean) {\r\n this.#disableCaptureScroll = value;\r\n this.setIsWaitingForStatChange(false);\r\n }\r\n get isListEnded() {\r\n return this.#isListEnded;\r\n }\r\n set isListEnded(value: boolean) {\r\n this.#isListEnded = value;\r\n this.setIsWaitingForStatChange(false);\r\n\r\n }\r\n get isLoading() {\r\n return this.#isLoading;\r\n }\r\n set isLoading(value: boolean) {\r\n this.#isLoading = value;\r\n this.setIsWaitingForStatChange(false);\r\n if (value) {\r\n this.elements?.loading.classList.add('--show');\r\n } else {\r\n this.elements?.loading.classList.remove('--show');\r\n this.checkEmptyListState();\r\n this.checkScrollHeight();\r\n }\r\n }\r\n get isListEmpty() {\r\n return this.#isListEmpty;\r\n }\r\n set isListEmpty(value: boolean) {\r\n this.#isListEmpty = value;\r\n this.setIsWaitingForStatChange(false);\r\n\r\n\r\n }\r\n get isLastPage() {\r\n return this.#isLastPage;\r\n }\r\n set isLastPage(value: boolean) {\r\n this.#isLastPage = value;\r\n }\r\n checkEmptyListState() {\r\n if (this.#isListEmpty) {\r\n this.elements?.emptyListWrapper.classList.add('--show');\r\n this.elements?.contentWrapper.classList.remove('--show');\r\n\r\n } else {\r\n this.elements?.contentWrapper.classList.add('--show');\r\n this.elements?.emptyListWrapper.classList.remove('--show');\r\n\r\n }\r\n }\r\n connectedCallback() {\r\n // standard web component event that called when all of dom is bounded\r\n this.callOnLoadEvent();\r\n this.initProp();\r\n this.callOnInitEvent();\r\n\r\n }\r\n callOnLoadEvent() {\r\n const event = new CustomEvent('load', { bubbles: true, composed: true });\r\n this.dispatchEvent(event);\r\n }\r\n callOnInitEvent() {\r\n const event = new CustomEvent('init', { bubbles: true, composed: true });\r\n this.dispatchEvent(event);\r\n }\r\n initWebComponent() {\r\n const shadowRoot = this.attachShadow({\r\n mode: 'open'\r\n });\r\n const html = `<style>${CSS}</style>` + '\\n' + HTML;\r\n const element = document.createElement('template');\r\n element.innerHTML = html;\r\n shadowRoot.appendChild(element.content.cloneNode(true));\r\n this.elements = {\r\n loading: shadowRoot.querySelector('.loading-wrapper')!,\r\n componentWrapper: shadowRoot.querySelector('.Infinite-scroll-component')!,\r\n contentWrapper: shadowRoot.querySelector('.content-wrapper')!,\r\n loadingWrapper: shadowRoot.querySelector('.loading-wrapper')!,\r\n emptyListWrapper: shadowRoot.querySelector('.empty-list-wrapper')!,\r\n };\r\n\r\n }\r\n registerEventListener() {\r\n this.elements.contentWrapper.addEventListener('scroll', this.onScroll.bind(this), { passive: true });\r\n }\r\n initProp() {\r\n this.registerEventListener();\r\n this.checkScrollHeight();\r\n }\r\n checkScrollHeight() {\r\n //check if our container is bigger than our content we call scroll end event\r\n const { scrollHeight, clientHeight } = this.elements.contentWrapper;\r\n if (scrollHeight <= clientHeight && this.canCaptureScroll) {\r\n this.onScrollEnd();\r\n }\r\n }\r\n onScrollEnd() { \r\n this.setIsWaitingForStatChange(true);\r\n const event = new CustomEvent('scrollEnd');\r\n this.dispatchEvent(event);\r\n }\r\n onScroll() {\r\n const { scrollTop, scrollHeight, clientHeight } = this.elements.contentWrapper;\r\n if (scrollTop + clientHeight + this.#endPageGap >= scrollHeight) {\r\n if (this.canCaptureScroll) {\r\n this.onScrollEnd();\r\n }\r\n }\r\n }\r\n setIsWaitingForStatChange(isWaitingStatus: boolean) {\r\n\r\n if (isWaitingStatus) {\r\n if (this.#stateChangeWaitingBehavior === StateChangeWaitingBehavior.forceWait) {\r\n this.#isWaitingForStateChange = true;\r\n } else if (this.#stateChangeWaitingBehavior === StateChangeWaitingBehavior.noWait) {\r\n return;\r\n }\r\n }\r\n this.#isWaitingForStateChange = false;\r\n\r\n\r\n\r\n }\r\n get canCaptureScroll() {\r\n if (!(this.#isLoading || this.#isListEmpty || this.#isListEnded || this.#isWaitingForStateChange || this.#disableCaptureScroll)) {\r\n return true;\r\n\r\n }\r\n return false;\r\n }\r\n\r\n static get observedAttributes() {\r\n return ['is-loading', 'is-list-empty', 'is-list-ended', 'disable-capture-scroll', 'state-change-waiting-behavior'];\r\n }\r\n attributeChangedCallback(name: string, oldValue: string, newValue: string) {\r\n // do something when an attribute has changed\r\n this.onAttributeChange(name, newValue);\r\n }\r\n onAttributeChange(name: string, value: string) {\r\n switch (name) {\r\n case 'is-loading':\r\n if (value === 'true') {\r\n this.isLoading = true;\r\n } else {\r\n this.isLoading = false;\r\n }\r\n break;\r\n case 'is-list-empty':\r\n if (value === 'true') {\r\n this.isListEmpty = true;\r\n } else {\r\n this.isListEmpty = false;\r\n\r\n }\r\n break;\r\n case 'is-list-ended':\r\n if (value === 'true') {\r\n this.#isListEnded = true;\r\n } else {\r\n this.#isListEnded = false;\r\n\r\n }\r\n break;\r\n\r\n case 'disable-capture-scroll':\r\n if (value === 'true') {\r\n this.#disableCaptureScroll = true;\r\n } else {\r\n this.#disableCaptureScroll = false;\r\n\r\n }\r\n break;\r\n case 'state-change-waiting-behavior':\r\n this.#stateChangeWaitingBehavior = this.mapStateChangeWaitingBehavior(value);\r\n break;\r\n\r\n\r\n }\r\n\r\n }\r\n}\r\nconst myElementNotExists = !customElements.get('jb-infinite-scroll');\r\nif (myElementNotExists) {\r\n window.customElements.define('jb-infinite-scroll', JBInfiniteScrollWebComponent);\r\n}\r\n"],"names":["StateChangeWaitingBehavior","JBInfiniteScrollWebComponent","HTMLElement","constructor","super","_JBInfiniteScrollWebComponent_isLoading","set","this","_JBInfiniteScrollWebComponent_endPageGap","_JBInfiniteScrollWebComponent_isLastPage","_JBInfiniteScrollWebComponent_isListEnded","_JBInfiniteScrollWebComponent_isWaitingForStateChange","_JBInfiniteScrollWebComponent_disableCaptureScroll","_JBInfiniteScrollWebComponent_isListEmpty","_JBInfiniteScrollWebComponent_stateChangeWaitingBehavior","forceWait","initWebComponent","mapStateChangeWaitingBehavior","state","noWait","stateChangeWaitingBehavior","value","__classPrivateFieldSet","__classPrivateFieldGet","disableCaptureScroll","setIsWaitingForStatChange","isListEnded","isLoading","elements","loading","classList","add","remove","checkEmptyListState","checkScrollHeight","isListEmpty","isLastPage","emptyListWrapper","contentWrapper","connectedCallback","callOnLoadEvent","initProp","callOnInitEvent","event","CustomEvent","bubbles","composed","dispatchEvent","shadowRoot","attachShadow","mode","element","document","createElement","innerHTML","appendChild","content","cloneNode","querySelector","componentWrapper","loadingWrapper","registerEventListener","addEventListener","onScroll","bind","passive","scrollHeight","clientHeight","canCaptureScroll","onScrollEnd","scrollTop","isWaitingStatus","observedAttributes","attributeChangedCallback","name","oldValue","newValue","onAttributeChange","customElements","get","window","define"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("jb-loading")):"function"==typeof define&&define.amd?define(["exports","jb-loading"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).JBInfiniteScroll={})}(this,(function(t){"use strict";function e(t,e,n,i){if("a"===n&&!i)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof e?t!==e||!i:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===n?i:"a"===n?i.call(t):i?i.value:e.get(t)}function n(t,e,n,i,s){if("m"===i)throw new TypeError("Private method is not writable");if("a"===i&&!s)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof e?t!==e||!s:!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===i?s.call(t,n):s?s.value=n:e.set(t,n),n}"function"==typeof SuppressedError&&SuppressedError;var i,s,a,r,o,l,c,h,p;t.StateChangeWaitingBehavior=void 0,(i=t.StateChangeWaitingBehavior||(t.StateChangeWaitingBehavior={})).forceWait="FORCE_WAIT",i.noWait="NO_WAIT";class d extends HTMLElement{constructor(){super(),s.set(this,!1),a.set(this,0),r.set(this,!1),o.set(this,!1),l.set(this,!1),c.set(this,!1),h.set(this,!1),p.set(this,t.StateChangeWaitingBehavior.forceWait),this.initWebComponent()}mapStateChangeWaitingBehavior(e){switch(e){case"FORCE_WAIT":default:return t.StateChangeWaitingBehavior.forceWait;case"NO_WAIT":return t.StateChangeWaitingBehavior.noWait}}set stateChangeWaitingBehavior(t){n(this,p,this.mapStateChangeWaitingBehavior(t),"f")}get stateChangeWaitingBehavior(){return e(this,p,"f")}get disableCaptureScroll(){return e(this,c,"f")}set disableCaptureScroll(t){n(this,c,t,"f"),this.setIsWaitingForStatChange(!1)}get isListEnded(){return e(this,o,"f")}set isListEnded(t){n(this,o,t,"f"),this.setIsWaitingForStatChange(!1)}get isLoading(){return e(this,s,"f")}set isLoading(t){n(this,s,t,"f"),this.setIsWaitingForStatChange(!1),t?this.elements?.loading.classList.add("--show"):(this.elements?.loading.classList.remove("--show"),this.checkEmptyListState(),this.checkScrollHeight())}get isListEmpty(){return e(this,h,"f")}set isListEmpty(t){n(this,h,t,"f"),this.setIsWaitingForStatChange(!1)}get isLastPage(){return e(this,r,"f")}set isLastPage(t){n(this,r,t,"f")}checkEmptyListState(){e(this,h,"f")?(this.elements?.emptyListWrapper.classList.add("--show"),this.elements?.contentWrapper.classList.remove("--show")):(this.elements?.contentWrapper.classList.add("--show"),this.elements?.emptyListWrapper.classList.remove("--show"))}connectedCallback(){this.callOnLoadEvent(),this.initProp(),this.callOnInitEvent()}callOnLoadEvent(){const t=new CustomEvent("load",{bubbles:!0,composed:!0});this.dispatchEvent(t)}callOnInitEvent(){const t=new CustomEvent("init",{bubbles:!0,composed:!0});this.dispatchEvent(t)}initWebComponent(){const t=this.attachShadow({mode:"open"}),e=document.createElement("template");e.innerHTML='<style>.infinite-scroll-component {\n height: 100%;\n display: grid;\n grid-template-rows: auto 1fr;\n}\n.infinite-scroll-component .content-wrapper {\n width: 100%;\n height: auto;\n display: none;\n overflow: auto;\n}\n.infinite-scroll-component .content-wrapper.--show {\n display: inline-block;\n}\n.infinite-scroll-component .empty-list-wrapper {\n width: 100%;\n height: 100%;\n display: none;\n}\n.infinite-scroll-component .empty-list-wrapper.--show {\n display: flex;\n justify-content: center;\n align-items: center;\n}\n.infinite-scroll-component .loading-wrapper {\n display: none;\n --jb-loading-color: var(--captcha-component-loading-color, #1565D8);\n}\n.infinite-scroll-component .loading-wrapper .default-loading {\n width: 40px;\n height: 40px;\n margin: 0 auto;\n}\n.infinite-scroll-component .loading-wrapper.--show {\n display: inline-block;\n}</style>\n<div class="infinite-scroll-component">\r\n <div class="content-wrapper" part="content-wrapper">\r\n <slot name="infinite-scroll-content"></slot>\r\n </div>\r\n <div class="empty-list-wrapper" part="empty-list-wrapper">\r\n <slot name="empty-list-content">\r\n <div class="default-empty-list">\r\n <p>empty list</p>\r\n </div>\r\n </slot>\r\n </div>\r\n <div class="loading-wrapper" part="loading-wrapper">\r\n <slot name="loading-content">\r\n <div class="default-loading">\r\n <jb-loading></jb-loading>\r\n </div>\r\n </slot>\r\n </div>\r\n</div>',t.appendChild(e.content.cloneNode(!0)),this.elements={loading:t.querySelector(".loading-wrapper"),componentWrapper:t.querySelector(".Infinite-scroll-component"),contentWrapper:t.querySelector(".content-wrapper"),loadingWrapper:t.querySelector(".loading-wrapper"),emptyListWrapper:t.querySelector(".empty-list-wrapper")}}registerEventListener(){this.elements.contentWrapper.addEventListener("scroll",this.onScroll.bind(this),{passive:!0})}initProp(){this.registerEventListener(),this.checkScrollHeight()}checkScrollHeight(){const{scrollHeight:t,clientHeight:e}=this.elements.contentWrapper;t<=e&&this.canCaptureScroll&&this.onScrollEnd()}onScrollEnd(){this.setIsWaitingForStatChange(!0);const t=new CustomEvent("scrollEnd");this.dispatchEvent(t)}onScroll(){const{scrollTop:t,scrollHeight:n,clientHeight:i}=this.elements.contentWrapper;t+i+e(this,a,"f")>=n&&this.canCaptureScroll&&this.onScrollEnd()}setIsWaitingForStatChange(i){if(i)if(e(this,p,"f")===t.StateChangeWaitingBehavior.forceWait)n(this,l,!0,"f");else if(e(this,p,"f")===t.StateChangeWaitingBehavior.noWait)return;n(this,l,!1,"f")}get canCaptureScroll(){return!(e(this,s,"f")||e(this,h,"f")||e(this,o,"f")||e(this,l,"f")||e(this,c,"f"))}static get observedAttributes(){return["is-loading","is-list-empty","is-list-ended","disable-capture-scroll","state-change-waiting-behavior"]}attributeChangedCallback(t,e,n){this.onAttributeChange(t,n)}onAttributeChange(t,e){switch(t){case"is-loading":this.isLoading="true"===e;break;case"is-list-empty":this.isListEmpty="true"===e;break;case"is-list-ended":n(this,o,"true"===e,"f");break;case"disable-capture-scroll":n(this,c,"true"===e,"f");break;case"state-change-waiting-behavior":n(this,p,this.mapStateChangeWaitingBehavior(e),"f")}}}s=new WeakMap,a=new WeakMap,r=new WeakMap,o=new WeakMap,l=new WeakMap,c=new WeakMap,h=new WeakMap,p=new WeakMap;!customElements.get("jb-infinite-scroll")&&window.customElements.define("jb-infinite-scroll",d),t.JBInfiniteScrollWebComponent=d}));
2
+ //# sourceMappingURL=jb-infinite-scroll.umd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jb-infinite-scroll.umd.js","sources":["../lib/types.ts","../lib/jb-infinite-scroll.ts"],"sourcesContent":["export type Elements = {\r\n loading: HTMLDivElement,\r\n contentWrapper: HTMLDivElement,\r\n componentWrapper: HTMLDivElement,\r\n emptyListWrapper: HTMLDivElement,\r\n loadingWrapper: HTMLDivElement,\r\n}\r\n\r\nexport enum StateChangeWaitingBehavior {\r\n // when user scroll we lock event call and wait for user to change isLoading (good for React or any other ui framework solution)\r\n forceWait = \"FORCE_WAIT\",\r\n // when user scroll we dont lock its event listener and developer should handle extra scroll by it self (good for pure js solution)\r\n noWait = \"NO_WAIT\",\r\n}","import HTML from './jb-infinite-scroll.html';\r\nimport CSS from './jb-infinite-scroll.scss';\r\nimport { Elements, StateChangeWaitingBehavior } from './types.js';\r\nimport \"jb-loading\";\r\n\r\nexport * from \"./types.js\";\r\n\r\nexport class JBInfiniteScrollWebComponent extends HTMLElement {\r\n elements!: Elements;\r\n #isLoading = false;\r\n //the amount of space that we listen to for trigger refresh \r\n #endPageGap = 0;\r\n #isLastPage = false;\r\n\r\n #isListEnded = false;\r\n //used when user scroll and we dont want to capture multiple scroll at one and wait for prev scroll event to finish\r\n #isWaitingForStateChange = false;\r\n #disableCaptureScroll = false;\r\n #isListEmpty = false;\r\n #stateChangeWaitingBehavior: StateChangeWaitingBehavior = StateChangeWaitingBehavior.forceWait;\r\n\r\n\r\n constructor() {\r\n super();\r\n this.initWebComponent();\r\n }\r\n mapStateChangeWaitingBehavior(state: string) {\r\n switch (state) {\r\n case \"FORCE_WAIT\":\r\n return StateChangeWaitingBehavior.forceWait;\r\n case \"NO_WAIT\":\r\n return StateChangeWaitingBehavior.noWait;\r\n\r\n default:\r\n return StateChangeWaitingBehavior.forceWait;\r\n\r\n }\r\n\r\n }\r\n set stateChangeWaitingBehavior(value: string) {\r\n this.#stateChangeWaitingBehavior = this.mapStateChangeWaitingBehavior(value);\r\n }\r\n get stateChangeWaitingBehavior() {\r\n return this.#stateChangeWaitingBehavior;\r\n }\r\n get disableCaptureScroll() {\r\n return this.#disableCaptureScroll;\r\n }\r\n\r\n set disableCaptureScroll(value: boolean) {\r\n this.#disableCaptureScroll = value;\r\n this.setIsWaitingForStatChange(false);\r\n }\r\n get isListEnded() {\r\n return this.#isListEnded;\r\n }\r\n set isListEnded(value: boolean) {\r\n this.#isListEnded = value;\r\n this.setIsWaitingForStatChange(false);\r\n\r\n }\r\n get isLoading() {\r\n return this.#isLoading;\r\n }\r\n set isLoading(value: boolean) {\r\n this.#isLoading = value;\r\n this.setIsWaitingForStatChange(false);\r\n if (value) {\r\n this.elements?.loading.classList.add('--show');\r\n } else {\r\n this.elements?.loading.classList.remove('--show');\r\n this.checkEmptyListState();\r\n this.checkScrollHeight();\r\n }\r\n }\r\n get isListEmpty() {\r\n return this.#isListEmpty;\r\n }\r\n set isListEmpty(value: boolean) {\r\n this.#isListEmpty = value;\r\n this.setIsWaitingForStatChange(false);\r\n\r\n\r\n }\r\n get isLastPage() {\r\n return this.#isLastPage;\r\n }\r\n set isLastPage(value: boolean) {\r\n this.#isLastPage = value;\r\n }\r\n checkEmptyListState() {\r\n if (this.#isListEmpty) {\r\n this.elements?.emptyListWrapper.classList.add('--show');\r\n this.elements?.contentWrapper.classList.remove('--show');\r\n\r\n } else {\r\n this.elements?.contentWrapper.classList.add('--show');\r\n this.elements?.emptyListWrapper.classList.remove('--show');\r\n\r\n }\r\n }\r\n connectedCallback() {\r\n // standard web component event that called when all of dom is bounded\r\n this.callOnLoadEvent();\r\n this.initProp();\r\n this.callOnInitEvent();\r\n\r\n }\r\n callOnLoadEvent() {\r\n const event = new CustomEvent('load', { bubbles: true, composed: true });\r\n this.dispatchEvent(event);\r\n }\r\n callOnInitEvent() {\r\n const event = new CustomEvent('init', { bubbles: true, composed: true });\r\n this.dispatchEvent(event);\r\n }\r\n initWebComponent() {\r\n const shadowRoot = this.attachShadow({\r\n mode: 'open'\r\n });\r\n const html = `<style>${CSS}</style>` + '\\n' + HTML;\r\n const element = document.createElement('template');\r\n element.innerHTML = html;\r\n shadowRoot.appendChild(element.content.cloneNode(true));\r\n this.elements = {\r\n loading: shadowRoot.querySelector('.loading-wrapper')!,\r\n componentWrapper: shadowRoot.querySelector('.Infinite-scroll-component')!,\r\n contentWrapper: shadowRoot.querySelector('.content-wrapper')!,\r\n loadingWrapper: shadowRoot.querySelector('.loading-wrapper')!,\r\n emptyListWrapper: shadowRoot.querySelector('.empty-list-wrapper')!,\r\n };\r\n\r\n }\r\n registerEventListener() {\r\n this.elements.contentWrapper.addEventListener('scroll', this.onScroll.bind(this), { passive: true });\r\n }\r\n initProp() {\r\n this.registerEventListener();\r\n this.checkScrollHeight();\r\n }\r\n checkScrollHeight() {\r\n //check if our container is bigger than our content we call scroll end event\r\n const { scrollHeight, clientHeight } = this.elements.contentWrapper;\r\n if (scrollHeight <= clientHeight && this.canCaptureScroll) {\r\n this.onScrollEnd();\r\n }\r\n }\r\n onScrollEnd() { \r\n this.setIsWaitingForStatChange(true);\r\n const event = new CustomEvent('scrollEnd');\r\n this.dispatchEvent(event);\r\n }\r\n onScroll() {\r\n const { scrollTop, scrollHeight, clientHeight } = this.elements.contentWrapper;\r\n if (scrollTop + clientHeight + this.#endPageGap >= scrollHeight) {\r\n if (this.canCaptureScroll) {\r\n this.onScrollEnd();\r\n }\r\n }\r\n }\r\n setIsWaitingForStatChange(isWaitingStatus: boolean) {\r\n\r\n if (isWaitingStatus) {\r\n if (this.#stateChangeWaitingBehavior === StateChangeWaitingBehavior.forceWait) {\r\n this.#isWaitingForStateChange = true;\r\n } else if (this.#stateChangeWaitingBehavior === StateChangeWaitingBehavior.noWait) {\r\n return;\r\n }\r\n }\r\n this.#isWaitingForStateChange = false;\r\n\r\n\r\n\r\n }\r\n get canCaptureScroll() {\r\n if (!(this.#isLoading || this.#isListEmpty || this.#isListEnded || this.#isWaitingForStateChange || this.#disableCaptureScroll)) {\r\n return true;\r\n\r\n }\r\n return false;\r\n }\r\n\r\n static get observedAttributes() {\r\n return ['is-loading', 'is-list-empty', 'is-list-ended', 'disable-capture-scroll', 'state-change-waiting-behavior'];\r\n }\r\n attributeChangedCallback(name: string, oldValue: string, newValue: string) {\r\n // do something when an attribute has changed\r\n this.onAttributeChange(name, newValue);\r\n }\r\n onAttributeChange(name: string, value: string) {\r\n switch (name) {\r\n case 'is-loading':\r\n if (value === 'true') {\r\n this.isLoading = true;\r\n } else {\r\n this.isLoading = false;\r\n }\r\n break;\r\n case 'is-list-empty':\r\n if (value === 'true') {\r\n this.isListEmpty = true;\r\n } else {\r\n this.isListEmpty = false;\r\n\r\n }\r\n break;\r\n case 'is-list-ended':\r\n if (value === 'true') {\r\n this.#isListEnded = true;\r\n } else {\r\n this.#isListEnded = false;\r\n\r\n }\r\n break;\r\n\r\n case 'disable-capture-scroll':\r\n if (value === 'true') {\r\n this.#disableCaptureScroll = true;\r\n } else {\r\n this.#disableCaptureScroll = false;\r\n\r\n }\r\n break;\r\n case 'state-change-waiting-behavior':\r\n this.#stateChangeWaitingBehavior = this.mapStateChangeWaitingBehavior(value);\r\n break;\r\n\r\n\r\n }\r\n\r\n }\r\n}\r\nconst myElementNotExists = !customElements.get('jb-infinite-scroll');\r\nif (myElementNotExists) {\r\n window.customElements.define('jb-infinite-scroll', JBInfiniteScrollWebComponent);\r\n}\r\n"],"names":["StateChangeWaitingBehavior","exports","JBInfiniteScrollWebComponent","HTMLElement","constructor","super","_JBInfiniteScrollWebComponent_isLoading","set","this","_JBInfiniteScrollWebComponent_endPageGap","_JBInfiniteScrollWebComponent_isLastPage","_JBInfiniteScrollWebComponent_isListEnded","_JBInfiniteScrollWebComponent_isWaitingForStateChange","_JBInfiniteScrollWebComponent_disableCaptureScroll","_JBInfiniteScrollWebComponent_isListEmpty","_JBInfiniteScrollWebComponent_stateChangeWaitingBehavior","forceWait","initWebComponent","mapStateChangeWaitingBehavior","state","noWait","stateChangeWaitingBehavior","value","__classPrivateFieldSet","__classPrivateFieldGet","disableCaptureScroll","setIsWaitingForStatChange","isListEnded","isLoading","elements","loading","classList","add","remove","checkEmptyListState","checkScrollHeight","isListEmpty","isLastPage","emptyListWrapper","contentWrapper","connectedCallback","callOnLoadEvent","initProp","callOnInitEvent","event","CustomEvent","bubbles","composed","dispatchEvent","shadowRoot","attachShadow","mode","element","document","createElement","innerHTML","appendChild","content","cloneNode","querySelector","componentWrapper","loadingWrapper","registerEventListener","addEventListener","onScroll","bind","passive","scrollHeight","clientHeight","canCaptureScroll","onScrollEnd","scrollTop","isWaitingStatus","observedAttributes","attributeChangedCallback","name","oldValue","newValue","onAttributeChange","customElements","get","window","define"],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export type Elements = {
2
+ loading: HTMLDivElement;
3
+ contentWrapper: HTMLDivElement;
4
+ componentWrapper: HTMLDivElement;
5
+ emptyListWrapper: HTMLDivElement;
6
+ loadingWrapper: HTMLDivElement;
7
+ };
8
+ export declare enum StateChangeWaitingBehavior {
9
+ forceWait = "FORCE_WAIT",
10
+ noWait = "NO_WAIT"
11
+ }
@@ -0,0 +1,36 @@
1
+ import { Elements, StateChangeWaitingBehavior } from './types.js';
2
+ import "jb-loading";
3
+ export * from "./types.js";
4
+ export declare class JBInfiniteScrollWebComponent extends HTMLElement {
5
+ #private;
6
+ elements: Elements;
7
+ constructor();
8
+ mapStateChangeWaitingBehavior(state: string): StateChangeWaitingBehavior;
9
+ set stateChangeWaitingBehavior(value: string);
10
+ get stateChangeWaitingBehavior(): string;
11
+ get disableCaptureScroll(): boolean;
12
+ set disableCaptureScroll(value: boolean);
13
+ get isListEnded(): boolean;
14
+ set isListEnded(value: boolean);
15
+ get isLoading(): boolean;
16
+ set isLoading(value: boolean);
17
+ get isListEmpty(): boolean;
18
+ set isListEmpty(value: boolean);
19
+ get isLastPage(): boolean;
20
+ set isLastPage(value: boolean);
21
+ checkEmptyListState(): void;
22
+ connectedCallback(): void;
23
+ callOnLoadEvent(): void;
24
+ callOnInitEvent(): void;
25
+ initWebComponent(): void;
26
+ registerEventListener(): void;
27
+ initProp(): void;
28
+ checkScrollHeight(): void;
29
+ onScrollEnd(): void;
30
+ onScroll(): void;
31
+ setIsWaitingForStatChange(isWaitingStatus: boolean): void;
32
+ get canCaptureScroll(): boolean;
33
+ static get observedAttributes(): string[];
34
+ attributeChangedCallback(name: string, oldValue: string, newValue: string): void;
35
+ onAttributeChange(name: string, value: string): void;
36
+ }
package/index.js ADDED
@@ -0,0 +1 @@
1
+ export * from './dist/jb-infinite-scroll.js';
@@ -0,0 +1,19 @@
1
+ <div class="infinite-scroll-component">
2
+ <div class="content-wrapper" part="content-wrapper">
3
+ <slot name="infinite-scroll-content"></slot>
4
+ </div>
5
+ <div class="empty-list-wrapper" part="empty-list-wrapper">
6
+ <slot name="empty-list-content">
7
+ <div class="default-empty-list">
8
+ <p>empty list</p>
9
+ </div>
10
+ </slot>
11
+ </div>
12
+ <div class="loading-wrapper" part="loading-wrapper">
13
+ <slot name="loading-content">
14
+ <div class="default-loading">
15
+ <jb-loading></jb-loading>
16
+ </div>
17
+ </slot>
18
+ </div>
19
+ </div>
@@ -0,0 +1,44 @@
1
+ .infinite-scroll-component {
2
+ height: 100%;
3
+ display: grid;
4
+ grid-template-rows: auto 1fr;
5
+
6
+ .content-wrapper {
7
+ width: 100%;
8
+ height: auto;
9
+ display: none;
10
+ overflow: auto;
11
+
12
+ &.--show {
13
+ display: inline-block;
14
+ }
15
+
16
+ }
17
+
18
+ .empty-list-wrapper {
19
+ width: 100%;
20
+ height: 100%;
21
+ display: none;
22
+
23
+ &.--show {
24
+ display: flex;
25
+ justify-content: center;
26
+ align-items: center;
27
+ }
28
+ }
29
+
30
+ .loading-wrapper {
31
+ display: none;
32
+ --jb-loading-color: var(--captcha-component-loading-color, #1565D8);
33
+
34
+ .default-loading {
35
+ width: 40px;
36
+ height: 40px;
37
+ margin: 0 auto;
38
+ }
39
+
40
+ &.--show {
41
+ display: inline-block;
42
+ }
43
+ }
44
+ }