{"_id":"@dpsys/stimulus-bidirectional-infinite-scroll","_rev":"5-53094de1a26c18247063f17f907db4e8","name":"@dpsys/stimulus-bidirectional-infinite-scroll","dist-tags":{"latest":"1.0.4"},"versions":{"1.0.0":{"name":"@dpsys/stimulus-bidirectional-infinite-scroll","version":"1.0.0","keywords":["infinite-scroll","bidirectional"],"author":{"name":"David Petrásek"},"license":"ISC","_id":"@dpsys/stimulus-bidirectional-infinite-scroll@1.0.0","maintainers":[{"name":"davidpetrasek","email":"davidpetrasek@hotmail.cz"}],"homepage":"https://github.com/DavidPetrasek/stimulus-bidirectional-infinite-scroll#readme","bugs":{"url":"https://github.com/DavidPetrasek/stimulus-bidirectional-infinite-scroll/issues"},"dist":{"shasum":"7f74a5fb6483851ad7f8ae47df41bf6a1bbf6ec9","tarball":"https://registry.npmjs.org/@dpsys/stimulus-bidirectional-infinite-scroll/-/stimulus-bidirectional-infinite-scroll-1.0.0.tgz","fileCount":9,"integrity":"sha512-As1A4xmSHps3+yN6ArjCQwcwxUMrIMP6YL368RK7K+7ClqpWKVi6K9MHgMt+QjGywSSEjDXF77M36D8f+ttaFg==","signatures":[{"sig":"MEQCICJ5i43N4150WrRYO/cE8+zh3hl1EMfQfeVwo0okQO0kAiB/y+rvTXWNBqeEQ/i/wXf2Dge7wu3Wgp20vCLPvShLSw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":60010},"exports":{".":{"import":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.js"}}},"gitHead":"cdf1e64ec83a674d6dbb798df97e05edf419feff","scripts":{"test":"vitest --ui","build":"tsup"},"_npmUser":{"name":"davidpetrasek","email":"davidpetrasek@hotmail.cz"},"repository":{"url":"git+https://github.com/DavidPetrasek/stimulus-bidirectional-infinite-scroll.git","type":"git"},"_npmVersion":"11.15.0","description":"[![NPM Downloads](https://img.shields.io/npm/dm/%40dpsys%2Fstimulus-bidirectional-infinite-scroll)](https://www.npmjs.com/package/@dpsys/stimulus-bidirectional-infinite-scroll) [![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg","directories":{},"_nodeVersion":"24.14.1","dependencies":{"@dpsys/js-utils":"^2.1.3","@hotwired/stimulus":"^3.2.2"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","jsdom":"^29.1.1","vitest":"^4.1.8","@vitest/ui":"^4.1.8","typescript":"^6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/stimulus-bidirectional-infinite-scroll_1.0.0_1781463503499_0.19925203984344142","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@dpsys/stimulus-bidirectional-infinite-scroll","version":"1.0.1","keywords":["infinite-scroll","infinite-scrolling","bidirectional","stimulus-js","overlay-scrollbars","auto-fill"],"author":{"name":"David Petrásek"},"license":"ISC","_id":"@dpsys/stimulus-bidirectional-infinite-scroll@1.0.1","maintainers":[{"name":"davidpetrasek","email":"davidpetrasek@hotmail.cz"}],"homepage":"https://github.com/DavidPetrasek/stimulus-bidirectional-infinite-scroll#readme","bugs":{"url":"https://github.com/DavidPetrasek/stimulus-bidirectional-infinite-scroll/issues"},"dist":{"shasum":"f25f959ad154faba729b0ad3da4bbe910d681213","tarball":"https://registry.npmjs.org/@dpsys/stimulus-bidirectional-infinite-scroll/-/stimulus-bidirectional-infinite-scroll-1.0.1.tgz","fileCount":9,"integrity":"sha512-GVbdor6Yz93V+nsTOyXYuU8aQowpc+7Gy/STrN+jSF4JhdH14GRynapSB8zdFwmvzvATCmdHrw+QISGYOYilwQ==","signatures":[{"sig":"MEUCIQCYZRW1cwHnXaxoEC8K2tKSNLb4ON9Mf5yMr1r4qjFeOAIgY7+LGxC0QwED94n2PzXZS6nSuu2j/QZrSb5ubj8iI1g=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":60098},"exports":{".":{"import":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.js"}}},"gitHead":"bac4b6f4d0e3865cba03c4fc0a2d3cc3618982eb","scripts":{"test":"vitest --ui","build":"tsup"},"_npmUser":{"name":"davidpetrasek","email":"davidpetrasek@hotmail.cz"},"repository":{"url":"git+https://github.com/DavidPetrasek/stimulus-bidirectional-infinite-scroll.git","type":"git"},"_npmVersion":"11.15.0","description":"[![NPM Downloads](https://img.shields.io/npm/dm/%40dpsys%2Fstimulus-bidirectional-infinite-scroll)](https://www.npmjs.com/package/@dpsys/stimulus-bidirectional-infinite-scroll) [![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg","directories":{},"_nodeVersion":"24.14.1","dependencies":{"@dpsys/js-utils":"^2.1.3","@hotwired/stimulus":"^3.2.2"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","jsdom":"^29.1.1","vitest":"^4.1.8","@vitest/ui":"^4.1.8","typescript":"^6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/stimulus-bidirectional-infinite-scroll_1.0.1_1781464284136_0.1236150884286451","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@dpsys/stimulus-bidirectional-infinite-scroll","version":"1.0.2","keywords":["infinite-scroll","infinite-scrolling","bidirectional","stimulus-js","overlay-scrollbars","auto-fill"],"author":{"name":"David Petrásek"},"license":"ISC","_id":"@dpsys/stimulus-bidirectional-infinite-scroll@1.0.2","maintainers":[{"name":"davidpetrasek","email":"davidpetrasek@hotmail.cz"}],"homepage":"https://github.com/DavidPetrasek/stimulus-bidirectional-infinite-scroll#readme","bugs":{"url":"https://github.com/DavidPetrasek/stimulus-bidirectional-infinite-scroll/issues"},"dist":{"shasum":"6fca2767a2b173c10cd08352f6aeaa742f0bd851","tarball":"https://registry.npmjs.org/@dpsys/stimulus-bidirectional-infinite-scroll/-/stimulus-bidirectional-infinite-scroll-1.0.2.tgz","fileCount":9,"integrity":"sha512-YN48btnF9D47jAZ9tXwXzsFMBeKZY6EIquy+rCjSzhYh/dxWa5zFkrBgo5yKi5mZrbrSy79VpXMXsb4Q1R5tkQ==","signatures":[{"sig":"MEYCIQDv3+wtCql/tHKHxs3SGnZo2Dam9HvDFON3k5Jf7+3JRgIhAKZ1DXtUTb6JvwANTJ7eSNwkLwlq4m0gkQaZcEnq/WAa","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":60266},"exports":{".":{"import":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.js"}}},"gitHead":"170e25398ed209bb65e29a7a102b6dd422a94c36","scripts":{"test":"vitest --ui","build":"tsup"},"_npmUser":{"name":"davidpetrasek","email":"davidpetrasek@hotmail.cz"},"repository":{"url":"git+https://github.com/DavidPetrasek/stimulus-bidirectional-infinite-scroll.git","type":"git"},"_npmVersion":"11.15.0","description":"[![NPM Downloads](https://img.shields.io/npm/dm/%40dpsys%2Fstimulus-bidirectional-infinite-scroll)](https://www.npmjs.com/package/@dpsys/stimulus-bidirectional-infinite-scroll) [![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg","directories":{},"_nodeVersion":"24.14.1","dependencies":{"@dpsys/js-utils":"^2.1.3","@hotwired/stimulus":"^3.2.2"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","jsdom":"^29.1.1","vitest":"^4.1.8","@vitest/ui":"^4.1.8","typescript":"^6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/stimulus-bidirectional-infinite-scroll_1.0.2_1781506190636_0.7454956161218365","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"@dpsys/stimulus-bidirectional-infinite-scroll","version":"1.0.3","keywords":["infinite-scroll","infinite-scrolling","bidirectional","stimulus-js","overlay-scrollbars","auto-fill"],"author":{"name":"David Petrásek"},"license":"ISC","_id":"@dpsys/stimulus-bidirectional-infinite-scroll@1.0.3","maintainers":[{"name":"davidpetrasek","email":"davidpetrasek@hotmail.cz"}],"homepage":"https://github.com/DavidPetrasek/stimulus-bidirectional-infinite-scroll#readme","bugs":{"url":"https://github.com/DavidPetrasek/stimulus-bidirectional-infinite-scroll/issues"},"dist":{"shasum":"92d73693c6fe31bcf40ce548933b7db59816f393","tarball":"https://registry.npmjs.org/@dpsys/stimulus-bidirectional-infinite-scroll/-/stimulus-bidirectional-infinite-scroll-1.0.3.tgz","fileCount":9,"integrity":"sha512-4ZrFBvrAPLKSlaG+6s2pP7vDvcT7cjFPCHRL8qwPtEd7e5hmjN65dGplg0NNIECoZzMoC9txqm5h9ruY5LJEPw==","signatures":[{"sig":"MEUCIBy9Z81saISHW+yPvoQ7LFveTb2hb7PNXVjTcc+IYpSEAiEA2DXzrkX1tqshG4z9nHM+GuGyEZftzbkKeWuMFp02D5g=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":60325},"exports":{".":{"import":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.js"}}},"gitHead":"c2d069af4097cd79d9d78f29d9aac9125d1309ad","scripts":{"test":"vitest --ui","build":"tsup"},"_npmUser":{"name":"davidpetrasek","email":"davidpetrasek@hotmail.cz"},"repository":{"url":"git+https://github.com/DavidPetrasek/stimulus-bidirectional-infinite-scroll.git","type":"git"},"_npmVersion":"11.15.0","description":"A Stimulus controller for bidirectional infinite scrolling.","directories":{},"_nodeVersion":"24.17.0","dependencies":{"@dpsys/js-utils":"^2.1.3","@hotwired/stimulus":"^3.2.2"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","jsdom":"^29.1.1","vitest":"^4.1.8","@vitest/ui":"^4.1.8","typescript":"^6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/stimulus-bidirectional-infinite-scroll_1.0.3_1782807964450_0.38743883247823985","host":"s3://npm-registry-packages-npm-production"}},"1.0.4":{"name":"@dpsys/stimulus-bidirectional-infinite-scroll","version":"1.0.4","description":"A Stimulus controller for bidirectional infinite scrolling.","keywords":["infinite-scroll","infinite-scrolling","bidirectional","stimulus-js","overlay-scrollbars","auto-fill"],"author":{"name":"David Petrásek"},"license":"ISC","repository":{"type":"git","url":"git+https://github.com/DavidPetrasek/stimulus-bidirectional-infinite-scroll.git"},"bugs":{"url":"https://github.com/DavidPetrasek/stimulus-bidirectional-infinite-scroll/issues"},"exports":{".":{"import":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.js"}}},"scripts":{"test":"vitest --ui","build":"tsup"},"devDependencies":{"@vitest/ui":"^4.1.11","jsdom":"^30.0.1","tsup":"^8.5.1","typescript":"^6.0.3","vitest":"^4.1.11"},"dependencies":{"@dpsys/js-utils":"^2.2.1","@hotwired/stimulus":"^3.2.2"},"gitHead":"97b3a5d3d7b812ca5dae9799c4d55e6608c03879","_id":"@dpsys/stimulus-bidirectional-infinite-scroll@1.0.4","homepage":"https://github.com/DavidPetrasek/stimulus-bidirectional-infinite-scroll#readme","_nodeVersion":"24.18.1","_npmVersion":"11.15.0","dist":{"integrity":"sha512-4QRgBa3iNz5Ay+wLN+3QHq570cDlL+z8nnaoDvTkNv3ek81VuGCSosEMeTV2cSOMat/MDjAQeXY0woNDdnc76Q==","shasum":"eebcb2722bac898324231e84e9926faeccf7d4a4","tarball":"https://registry.npmjs.org/@dpsys/stimulus-bidirectional-infinite-scroll/-/stimulus-bidirectional-infinite-scroll-1.0.4.tgz","fileCount":9,"unpackedSize":60327,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIE6isq1SRf+KPqYv2Hp+xVxW08jgtgtCZnnabUrmDn51AiBmkrBjv6UVbMm39UwXg6ORAozSIkI9WEYDUmUGnKDnaw=="}]},"_npmUser":{"name":"davidpetrasek","email":"davidpetrasek@hotmail.cz"},"directories":{},"maintainers":[{"name":"davidpetrasek","email":"davidpetrasek@hotmail.cz"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/stimulus-bidirectional-infinite-scroll_1.0.4_1787415073997_0.020812199156577282"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-14T18:58:23.360Z","modified":"2026-08-22T16:11:14.305Z","1.0.0":"2026-06-14T18:58:23.642Z","1.0.1":"2026-06-14T19:11:24.284Z","1.0.2":"2026-06-15T06:49:50.782Z","1.0.3":"2026-06-30T08:26:04.639Z","1.0.4":"2026-08-22T16:11:14.132Z"},"bugs":{"url":"https://github.com/DavidPetrasek/stimulus-bidirectional-infinite-scroll/issues"},"author":{"name":"David Petrásek"},"license":"ISC","homepage":"https://github.com/DavidPetrasek/stimulus-bidirectional-infinite-scroll#readme","keywords":["infinite-scroll","infinite-scrolling","bidirectional","stimulus-js","overlay-scrollbars","auto-fill"],"repository":{"type":"git","url":"git+https://github.com/DavidPetrasek/stimulus-bidirectional-infinite-scroll.git"},"description":"A Stimulus controller for bidirectional infinite scrolling.","maintainers":[{"name":"davidpetrasek","email":"davidpetrasek@hotmail.cz"}],"readme":"[![NPM Downloads](https://img.shields.io/npm/dm/%40dpsys%2Fstimulus-bidirectional-infinite-scroll)](https://www.npmjs.com/package/@dpsys/stimulus-bidirectional-infinite-scroll)\n[![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg)](https://www.typescriptlang.org/)\n[![ISC License](https://img.shields.io/badge/License-ISC-blue.svg)](https://opensource.org/licenses/ISC)\n\n# Stimulus Bidirectional Infinite Scroll\n\nSupports CJS and ESM.\n\n## Features\n\n- **Up/Down/Left/Right**\n- **Triggerless**: No initial items or trigger element is required\n- **Auto fill**\n- **Custom Scroll Viewports**: Seamless integration with third-party wrappers like `OverlayScrollbars`\n\n\n## Installation\n1. Run: \n``` bash\nnpm i @dpsys/stimulus-bidirectional-infinite-scroll\n```\n2. Register this controller in your bootstrap file:\n``` js\nimport BidirectionalInfiniteScroll from \"@dpsys/stimulus-bidirectional-infinite-scroll\";\n...\nstimulusApp.register('bidirectional-infinite-scroll', BidirectionalInfiniteScroll);\n```\n\n## Example Usage\n**1. Basic**\n\nThis example uses Symfony UX StimulusBundle and the Fetch API. Use any other implementation of your choice.\n\n``` js\n// .../controllers/my-infinite-scroll-controller.js\nimport BidirectionalInfiniteController from '@dpsys/stimulus-bidirectional-infinite-scroll';\n\nexport default class extends BidirectionalInfiniteController \n{\n    async loadMoreCallback(formData)\n    {\n        const response = await fetch(\"https://example.org/load-more\", \n        {\n            method: \"POST\",\n            body: formData, // inherently contains the target 'page' parameter\n        });\n        return await response.text(); // Return raw HTML string containing elements\n    }\n}\n```\n\n``` twig\n<div {{ stimulus_controller('my-infinite-scroll', {'loadMoreDirection': 'down', 'nbPages': 10, 'autoFill': true}) }} >\n</div>\n```\n\n**2. Custom Containers (e.g., OverlayScrollbars)**\n\nIf your scroll layout runs inside a custom structural plugin wrapper rather than the controller element itself, flag `customScrollContainer` to handle initialization manually.\n\n``` js\n// .../controllers/my-infinite-scroll-controller.js\nimport BidirectionalInfiniteController from '@dpsys/stimulus-bidirectional-infinite-scroll';\nimport { OverlayScrollbars } from 'overlayscrollbars';\n\nexport default class extends BidirectionalInfiniteController \n{\n    connect() \n    {\n        super.connect();\n        \n        OverlayScrollbars(this.element, {},\n        {\n            initialized: (os) =>\n            {\n                // Point the controller to the actual overflowing layout viewport element\n                this.setScrollContainer(os.elements().viewport);\n                this.enable();\n            }\n        });\n    }\n\n    ...\n}\n```\n\n``` twig\n<div {{ stimulus_controller('my-infinite-scroll', {'loadMoreDirection': 'down', 'nbPages': 10, customScrollContainer': true}) }} >\n</div>\n```\n\n## Config\nConfigure the controller configuration using standard Stimulus Data Values:\n\n| Option | Type | Default | Description |\n| :--- | :--- | :--- | :--- |\n| `currPage` | Number | `1` | The starting page index which is incremented/decremented automatically when new content is loaded for insertion. |\n| `nbPages` | Number | *Required* | Number of available pages. Loding more content is halted when this limit is reached. |\n| `triggerDistanceEm` | Number | `10` | Lookahead threshold margin calculated in `em` units relative to the container boundaries before firing `loadMoreCallback`. |\n| `loadMoreDirection` | String | `'down'` | Permitted options: `'up'`, `'down'`, `'left'`, `'right'`. |\n| `customScrollContainer` | Boolean | `false` | If set to `true`, halts automatic initialization, allowing to set the scroll container later after `connect()` was fired. |\n| `autoFill` | Boolean | `false` | When true, automatically fills the container with new content until its scrollable. |\n| `insertTargetQuerySelector` | String | `null` | CSS query selector of child element relative to the default scroll container. If specified, the new content is inserted here instead of the default (parent) scroll container. |\n\n## Callbacks\n\n### `loadMoreCallback(formData: FormData): Promise<string>`\n\nThe primary abstract method executing async interactions. This **must** be implemented within your extending subclass.\n\n* **Arguments:** An instance of `FormData` replicating any previously bound application data and carrying the updated `page` value.\n* **Expected Return:** A `Promise` resolving to an HTML string slice containing the markup of your new elements.\n\n\n## Events\n\n### `elements-added`\n\nDispatched natively upon successful injection of new elements into the target scroll container.\n\n* **`event.target`**: The container in which new elements were inserted.\n* **`event.detail.newElems`**: An array containing the newly inserted elements.\n\n---\n**How to listen to events**\n\nThere are two ways to listen inside `my-infinite-scroll` or any other controller:\n\n#### First approach:\n```js\nthis.element.addEventListener('my-infinite-scroll:elements-added', (e) => \n{\n    console.log(\"Newly inserted elements:\", e.detail.newElems);\n});\n```\n\n#### Second approach:\n``` twig\n<div {{ stimulus_controller('some-other') }} \n{{ stimulus_action(\n    'some-other', \n    'elementsAddded', \n    'my-infinite-scroll:elements-added'\n) }}>\n</div>\n```\nThen inside `some-other` controller implement method:\n```js\nelementsAddded(e)\n{\n    console.log(\"Newly inserted elements:\", e.detail.newElems);\n}\n```\n\n\n## Methods\nThe following public methods are available directly on your extended controller instance:\n\n* **`enable(): Promise<void>`**: Enables all functionality\n* **`disable(): void`**: Disables all functionality\n* **`setBaseFormData(formData: FormData): void`**: This `FormData` is later available inside the `loadMoreCallback` with the updated `page` value\n* **`setScrollContainer(scrollContainer: HTMLElement): void`**\n* **`getScrollContainer(): HTMLElement | null`**\n* **`autoFill(): Promise<void>`**: Performs auto filling of the scroll container","readmeFilename":"README.md"}