Repository: Akryum/vue-virtual-scroller Branch: master Commit: 5741944941d7 Files: 103 Total size: 227.9 KB Directory structure: gitextract_9c2q8070/ ├── .github/ │ ├── FUNDING.yml │ ├── ISSUE_TEMPLATE/ │ │ ├── bug-report.yml │ │ ├── config.yml │ │ └── feature-request.yml │ └── workflows/ │ ├── continuous-publish.yml │ ├── pr-title.yml │ ├── release-notes.yml │ └── test.yml ├── .gitignore ├── .node-version ├── CHANGELOG.md ├── README.md ├── SKILLS-GENERATION.md ├── docs/ │ ├── .vitepress/ │ │ ├── components/ │ │ │ └── demos/ │ │ │ ├── ChatStreamDocDemo.vue │ │ │ ├── DemoShell.vue │ │ │ ├── DynamicScrollerDocDemo.vue │ │ │ ├── GridDocDemo.vue │ │ │ ├── HorizontalDocDemo.vue │ │ │ ├── RecycleScrollerDocDemo.vue │ │ │ ├── SimpleListDocDemo.vue │ │ │ ├── TestChatDocDemo.vue │ │ │ └── demo-data.ts │ │ ├── config.mts │ │ └── theme/ │ │ ├── index.ts │ │ └── style.css │ ├── demos/ │ │ ├── chat.md │ │ ├── dynamic-scroller.md │ │ ├── grid.md │ │ ├── horizontal.md │ │ ├── index.md │ │ ├── recycle-scroller.md │ │ ├── simple-list.md │ │ └── test-chat.md │ ├── guide/ │ │ ├── ai-skills.md │ │ ├── dynamic-scroller-item.md │ │ ├── dynamic-scroller.md │ │ ├── id-state.md │ │ ├── index.md │ │ ├── recycle-scroller.md │ │ └── use-recycle-scroller.md │ └── index.md ├── eslint.config.mjs ├── netlify.toml ├── package.json ├── packages/ │ ├── demo/ │ │ ├── .gitignore │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── public/ │ │ │ └── index.html │ │ ├── src/ │ │ │ ├── App.vue │ │ │ ├── components/ │ │ │ │ ├── ChatDemo.vue │ │ │ │ ├── DynamicScrollerDemo.vue │ │ │ │ ├── GridDemo.vue │ │ │ │ ├── Home.vue │ │ │ │ ├── HorizontalDemo.vue │ │ │ │ ├── Person.vue │ │ │ │ ├── RecycleScrollerDemo.vue │ │ │ │ ├── SimpleList.vue │ │ │ │ └── TestChat.vue │ │ │ ├── data.js │ │ │ ├── main.js │ │ │ └── router.js │ │ └── vite.config.js │ └── vue-virtual-scroller/ │ ├── LICENSE │ ├── README.md │ ├── package.json │ ├── skills/ │ │ └── vue-virtual-scroller/ │ │ ├── SKILL.md │ │ └── references/ │ │ ├── dynamic-scroller-item.md │ │ ├── dynamic-scroller.md │ │ ├── index.md │ │ ├── installation-and-setup.md │ │ ├── recycle-scroller.md │ │ └── use-recycle-scroller.md │ ├── src/ │ │ ├── components/ │ │ │ ├── DynamicScroller.spec.ts │ │ │ ├── DynamicScroller.vue │ │ │ ├── DynamicScrollerItem.spec.ts │ │ │ ├── DynamicScrollerItem.vue │ │ │ ├── ItemView.spec.ts │ │ │ ├── ItemView.vue │ │ │ ├── RecycleScroller.spec.ts │ │ │ ├── RecycleScroller.vue │ │ │ └── ResizeObserver.vue │ │ ├── composables/ │ │ │ ├── useDynamicScroller.spec.ts │ │ │ ├── useDynamicScroller.ts │ │ │ ├── useDynamicScrollerItem.ts │ │ │ ├── useIdState.spec.ts │ │ │ ├── useIdState.ts │ │ │ ├── useRecycleScroller.spec.ts │ │ │ └── useRecycleScroller.ts │ │ ├── config.ts │ │ ├── directives/ │ │ │ └── observeVisibility.ts │ │ ├── index.spec.ts │ │ ├── index.ts │ │ ├── scrollparent.spec.ts │ │ ├── scrollparent.ts │ │ ├── shims-vue.d.ts │ │ ├── types.ts │ │ ├── utils.spec.ts │ │ └── utils.ts │ ├── tsconfig.build.json │ ├── tsconfig.json │ └── vite.config.ts └── pnpm-workspace.yaml ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/FUNDING.yml ================================================ # These are supported funding model platforms github: Akryum ================================================ FILE: .github/ISSUE_TEMPLATE/bug-report.yml ================================================ name: 🐞 Bug report description: Report an issue with vue-virtual-scroller labels: [to triage] body: - type: markdown attributes: value: | Thanks for taking the time to fill out this bug report! - type: textarea id: bug-description attributes: label: Describe the bug description: A clear and concise description of what the bug is. If you intend to submit a PR for this issue, tell us in the description. Thanks! placeholder: Bug description validations: required: true - type: textarea id: reproduction attributes: label: Reproduction description: Please provide a link to [StackBlitz](https://stackblitz.com/fork/vue). A [minimal reproduction](https://stackoverflow.com/help/minimal-reproducible-example) is required unless you are absolutely sure that the issue is obvious and the provided information is enough to understand the problem. If a report is vague (e.g. just a generic error message) and has no reproduction, it will receive a "need repro" label. If no reproduction is provided after 3 days, it will be closed. placeholder: Reproduction validations: required: true - type: textarea id: system-info attributes: label: System Info description: Output of `npx envinfo --system --npmPackages '{vue,vue-virtual-scroller,vite,@vitejs/*}' --binaries --browsers` render: shell placeholder: System, Binaries, Browsers validations: required: true - type: dropdown id: package-manager attributes: label: Used Package Manager description: Select the used package manager options: - npm - yarn - pnpm validations: required: true - type: checkboxes id: checkboxes attributes: label: Validations description: Before submitting the issue, please make sure you do the following options: # - label: Follow our [Code of Conduct](https://github.com/histoire-dev/histoire/blob/main/CODE_OF_CONDUCT.md) # required: true # - label: Read the [Contributing Guidelines](https://github.com/histoire-dev/histoire/blob/main/CONTRIBUTING.md). # required: true - label: Read the [docs](https://github.com/Akryum/vue-virtual-scroller/blob/master/packages/vue-virtual-scroller/README.md). required: true - label: Check that there isn't [already an issue](https://github.com/Akryum/vue-virtual-scroller/issues) that reports the same bug to avoid creating a duplicate. required: true - label: Check that this is a concrete bug. For Q&A open a [GitHub Discussion](https://github.com/Akryum/vue-virtual-scroller/discussions). required: true - label: The provided reproduction is a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) of the bug. required: true ================================================ FILE: .github/ISSUE_TEMPLATE/config.yml ================================================ blank_issues_enabled: false contact_links: - name: Questions & Discussions url: https://github.com/Akryum/vue-virtual-scroller/discussions about: Use GitHub discussions for message-board style questions and discussions. ================================================ FILE: .github/ISSUE_TEMPLATE/feature-request.yml ================================================ name: 🚀 New feature proposal description: Propose a new feature to be added to vue-virtual-scroller labels: ['enhancement: to triage'] body: - type: markdown attributes: value: | Thanks for your interest in the project and taking the time to fill out this feature report! - type: textarea id: feature-description attributes: label: Clear and concise description of the problem description: 'As a developer using vue-virtual-scroller I want [goal / wish] so that [benefit]. If you intend to submit a PR for this issue, tell us in the description. Thanks!' validations: required: true - type: textarea id: suggested-solution attributes: label: Suggested solution description: We could provide following implementation... validations: required: true - type: textarea id: alternative attributes: label: Alternative description: Clear and concise description of any alternative solutions or features you've considered. - type: textarea id: additional-context attributes: label: Additional context description: Any other context or screenshots about the feature request here. - type: checkboxes id: checkboxes attributes: label: Validations description: Before submitting the issue, please make sure you do the following options: # - label: Follow our [Code of Conduct](https://github.com/histoire-dev/histoire/blob/main/CODE_OF_CONDUCT.md) # required: true # - label: Read the [Contributing Guidelines](https://github.com/histoire-dev/histoire/blob/main/CONTRIBUTING.md). # required: true - label: Read the [docs](https://github.com/Akryum/vue-virtual-scroller/blob/master/packages/vue-virtual-scroller/README.md). required: true - label: Check that there isn't [already an issue](https://github.com/Akryum/vue-virtual-scroller/issues) that reports the same bug to avoid creating a duplicate. required: true ================================================ FILE: .github/workflows/continuous-publish.yml ================================================ name: Publish Any Commit on: [push, pull_request] jobs: auto-publish: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: corepack enable - uses: actions/setup-node@v4 with: node-version: latest cache: pnpm - name: Install dependencies run: pnpm install - name: Build run: pnpm build - run: pnpx pkg-pr-new publish './packages/*' ================================================ FILE: .github/workflows/pr-title.yml ================================================ name: Check PR title on: pull_request_target: types: - opened - edited - synchronize jobs: check-title: runs-on: ubuntu-latest steps: # Please look up the latest version from # https://github.com/amannn/action-semantic-pull-request/releases - uses: amannn/action-semantic-pull-request@v3.4.2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} ================================================ FILE: .github/workflows/release-notes.yml ================================================ name: Create release on: push: tags: - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10 jobs: build: name: Create Release runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@master with: fetch-depth: 0 # Fetch all tags - name: Create Release for Tag id: release_tag uses: Akryum/release-tag@conventional env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tag_name: ${{ github.ref }} preset: angular # Use conventional-changelog preset ================================================ FILE: .github/workflows/test.yml ================================================ name: Tests on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: corepack enable - uses: actions/setup-node@v4 with: node-version: latest cache: pnpm - name: Install dependencies run: pnpm install - name: Build run: pnpm build - name: ESLint run: pnpm lint ================================================ FILE: .gitignore ================================================ node_modules/ .temp/ .cache/ dist/ .eslintcache docs/.vitepress/cache docs/.vitepress/dist ================================================ FILE: .node-version ================================================ 25.8.0 ================================================ FILE: CHANGELOG.md ================================================ ## v2.0.0-beta.10 [compare changes](https://github.com/Akryum/vue-virtual-scroller/compare/v2.0.0-beta.9...v2.0.0-beta.10) ### 🩹 Fixes - Empty slot ([5791945](https://github.com/Akryum/vue-virtual-scroller/commit/5791945)) ### 🏡 Chore - Changelog ([2ae2195](https://github.com/Akryum/vue-virtual-scroller/commit/2ae2195)) ### ❤️ Contributors - Guillaume Chau ([@Akryum](http://github.com/Akryum)) ## v2.0.0-beta.9 [compare changes](https://github.com/Akryum/vue-virtual-scroller/compare/v2.0.0-beta.8...v2.0.0-beta.9) ### 🚀 Enhancements - Items ref ([#789](https://github.com/Akryum/vue-virtual-scroller/pull/789)) - New `disableTransform` prop to use top/left instead of translate ([#138](https://github.com/Akryum/vue-virtual-scroller/pull/138)) - Typescript / composition rewrite, new docs ([dff69e8](https://github.com/Akryum/vue-virtual-scroller/commit/dff69e8)) - AI skills ([8e58315](https://github.com/Akryum/vue-virtual-scroller/commit/8e58315)) ### 🩹 Fixes - Index lost, fix #783 ([#784](https://github.com/Akryum/vue-virtual-scroller/pull/784), [#783](https://github.com/Akryum/vue-virtual-scroller/issues/783)) - Avoid rendering when slot is unused ([#787](https://github.com/Akryum/vue-virtual-scroller/pull/787)) - Rewrite view (re-)assignment logic ([#743](https://github.com/Akryum/vue-virtual-scroller/pull/743)) - **RecycleScroller:** Introduce an item wrapper to reduce re-render ([#742](https://github.com/Akryum/vue-virtual-scroller/pull/742)) - Flicker issue in ios when scrolling up ([#864](https://github.com/Akryum/vue-virtual-scroller/pull/864)) - Hide view to avoid overlap when position is set to -9999px; ([#837](https://github.com/Akryum/vue-virtual-scroller/pull/837)) - Prevent empty gaps on fast scrolling, fix (#863, #882) ([#890](https://github.com/Akryum/vue-virtual-scroller/pull/890), [#863](https://github.com/Akryum/vue-virtual-scroller/issues/863), [#882](https://github.com/Akryum/vue-virtual-scroller/issues/882)) - Recycle scroller visible gaps computation ([5940707](https://github.com/Akryum/vue-virtual-scroller/commit/5940707)) - Small improvements ([013279c](https://github.com/Akryum/vue-virtual-scroller/commit/013279c)) - Build ([8efdef2](https://github.com/Akryum/vue-virtual-scroller/commit/8efdef2)) ### 💅 Refactors - Esm only ([4ffe378](https://github.com/Akryum/vue-virtual-scroller/commit/4ffe378)) ### 📖 Documentation - Fix dead link ([c6a3320](https://github.com/Akryum/vue-virtual-scroller/commit/c6a3320)) - Update readmes ([828c184](https://github.com/Akryum/vue-virtual-scroller/commit/828c184)) ### 🏡 Chore - Fix cherrypick of rewrite ([c9ccc34](https://github.com/Akryum/vue-virtual-scroller/commit/c9ccc34)) - Update lockfile ([0f2e362](https://github.com/Akryum/vue-virtual-scroller/commit/0f2e362)) - Update pnpm + pin pnpm in package.json ([#885](https://github.com/Akryum/vue-virtual-scroller/pull/885)) - Add pkg.pr.new ([#886](https://github.com/Akryum/vue-virtual-scroller/pull/886)) - Add test workflow ([#887](https://github.com/Akryum/vue-virtual-scroller/pull/887)) - Update pnpm and refresh lockfile ([47efc94](https://github.com/Akryum/vue-virtual-scroller/commit/47efc94)) ### ✅ Tests - **lint:** Update eslint and use antfu config ([61b9919](https://github.com/Akryum/vue-virtual-scroller/commit/61b9919)) - **lint:** Fix ([1e2e8e0](https://github.com/Akryum/vue-virtual-scroller/commit/1e2e8e0)) ### ❤️ Contributors - Guillaume Chau ([@Akryum](http://github.com/Akryum)) - Ferflores507 ([@ferflores507](http://github.com/ferflores507)) - KaygNas <597857074@QQ.COM> - Hobywhan ([@hobywhan](http://github.com/hobywhan)) - Wan Zulsarhan Wan Shaari - Tatsuyuki Ishi ([@ishitatsuyuki](http://github.com/ishitatsuyuki)) - AousAnwar ([@AousAnwar](http://github.com/AousAnwar)) - Alex Liu ([@Mini-ghost](http://github.com/Mini-ghost)) - Reynaldiaznan123 - Vito ([@liu-lihao](http://github.com/liu-lihao)) # [2.0.0-beta.8](https://github.com/Akryum/vue-virtual-scroller/compare/v2.0.0-beta.7...v2.0.0-beta.8) (2023-02-06) ### Bug Fixes * borderBoxSize not available in older browsers ([8f90971](https://github.com/Akryum/vue-virtual-scroller/commit/8f9097138d2f90ece8348141ac320c47ff7ab64a)) # [2.0.0-beta.7](https://github.com/Akryum/vue-virtual-scroller/compare/v2.0.0-beta.6...v2.0.0-beta.7) (2022-12-14) ### Bug Fixes * items not updating if new object reference, fix [#690](https://github.com/Akryum/vue-virtual-scroller/issues/690) ([5b5df8c](https://github.com/Akryum/vue-virtual-scroller/commit/5b5df8cdc231f989e7fc6d6677d02e9ef695d1b9)) # [2.0.0-beta.6](https://github.com/Akryum/vue-virtual-scroller/compare/v2.0.0-beta.5...v2.0.0-beta.6) (2022-12-14) ### Bug Fixes * keyField issue for class instances, fix [#770](https://github.com/Akryum/vue-virtual-scroller/issues/770) ([#771](https://github.com/Akryum/vue-virtual-scroller/issues/771)) ([1559ca8](https://github.com/Akryum/vue-virtual-scroller/commit/1559ca87e9195b6a1c5bada13de7f7b755a2fb6c)) * **RecycleScroller:** gridItems is undefined when scrollToItem, fix [#773](https://github.com/Akryum/vue-virtual-scroller/issues/773) ([#761](https://github.com/Akryum/vue-virtual-scroller/issues/761)) ([7c809ad](https://github.com/Akryum/vue-virtual-scroller/commit/7c809ad1d612824867490c7bd5ce2861110412eb)) * sorting views not working, [#772](https://github.com/Akryum/vue-virtual-scroller/issues/772) ([0b199d1](https://github.com/Akryum/vue-virtual-scroller/commit/0b199d14c846ecc00b93f989adbe29961dc68aad)) * view not unused if item no longer present, fix [#774](https://github.com/Akryum/vue-virtual-scroller/issues/774) ([bd51403](https://github.com/Akryum/vue-virtual-scroller/commit/bd514031f537978f0343317bb9cee550c5bfd7ad)) * views not reused correctly ([d5a8d75](https://github.com/Akryum/vue-virtual-scroller/commit/d5a8d759090f9af656865dd98648941fb2c71fa2)) ### Features * allow throttling update calls ([#764](https://github.com/Akryum/vue-virtual-scroller/issues/764)) ([9ba57d7](https://github.com/Akryum/vue-virtual-scroller/commit/9ba57d7d84c06d2ad265a266958292081704f218)) # [2.0.0-beta.5](https://github.com/Akryum/vue-virtual-scroller/compare/v2.0.0-beta.4...v2.0.0-beta.5) (2022-12-07) ### Bug Fixes * duplicate active views ([1ef796b](https://github.com/Akryum/vue-virtual-scroller/commit/1ef796b42143da6d4e74f83b8ac88176128e6d77)) * **DynamicScroller:** gaps caused by DOM reusing not triggering ResizeObserver ([a21e191](https://github.com/Akryum/vue-virtual-scroller/commit/a21e1915d76741a2806abd3a702d450f722879c8)) * inconsistent state on reused view ([a14747d](https://github.com/Akryum/vue-virtual-scroller/commit/a14747d33d75eaf7fe820370436d70e82562939b)) * views map corruption + view not removed from unusedPool ([cef8860](https://github.com/Akryum/vue-virtual-scroller/commit/cef886085c52f62736cf4c404a32f4f4fce6d229)) ### Performance Improvements * unnecessary loop ([86d0d07](https://github.com/Akryum/vue-virtual-scroller/commit/86d0d0776e26542d1b94484ec6ff5410733d3f18)) # [2.0.0-beta.4](https://github.com/Akryum/vue-virtual-scroller/compare/v2.0.0-beta.3...v2.0.0-beta.4) (2022-12-06) ### Bug Fixes * improved dynamic scroller resize observer logic ([40f58b3](https://github.com/Akryum/vue-virtual-scroller/commit/40f58b3e3a411df36c09d59cc3776719f60d93cf)) * item sizes getting 'disabled' resulting in gaps ([55b4ab1](https://github.com/Akryum/vue-virtual-scroller/commit/55b4ab1df1b4998178f2f03a53c112086a2633f2)) * unusing views after non-continuous scroll ([11488b7](https://github.com/Akryum/vue-virtual-scroller/commit/11488b7d8ffdfe1384fe808e4a49c1ba95ad1383)) * views incorrectly unused (proxy identity comparison) ([395bbfb](https://github.com/Akryum/vue-virtual-scroller/commit/395bbfb73588455795ecc5b144281ce5fda042ff)) # [2.0.0-beta.3](https://github.com/Akryum/vue-virtual-scroller/compare/v2.0.0-beta.2...v2.0.0-beta.3) (2022-10-18) ### Performance Improvements * small code changes to maximize performance ([3b4dbf3](https://github.com/Akryum/vue-virtual-scroller/commit/3b4dbf39f480745d53e4bb43217c2b35975e4ab6)) ### Reverts * pass key-field prop [#732](https://github.com/Akryum/vue-virtual-scroller/issues/732), fix [#758](https://github.com/Akryum/vue-virtual-scroller/issues/758) ([8d221e6](https://github.com/Akryum/vue-virtual-scroller/commit/8d221e6978e4924ab125337fc91f6b6de7a1f497)) # [2.0.0-beta.2](https://github.com/Akryum/vue-virtual-scroller/compare/v1.1.1...v2.0.0-beta.2) (2022-10-17) ### Bug Fixes * fix: height NaN, fix [#757](https://github.com/Akryum/vue-virtual-scroller/issues/757) # [2.0.0-beta.1](https://github.com/Akryum/vue-virtual-scroller/compare/v1.1.0...v2.0.0-beta.1) (2022-10-15) ### Bug Fixes * Account for the height of the leading and trailing slots when calculating visible items, fix [#685](https://github.com/Akryum/vue-virtual-scroller/issues/685) ([24ab3ba](https://github.com/Akryum/vue-virtual-scroller/commit/24ab3ba773d5819fcbe29f13eab663d48bce73ca)) * avoid jumping scroll position when upper item size is calculated ([#374](https://github.com/Akryum/vue-virtual-scroller/issues/374)) ([fd58a95](https://github.com/Akryum/vue-virtual-scroller/commit/fd58a95392c98b8e67da66235fcf4cac78ea2fd4)) * clamp endIndex if less items than prerender ([#473](https://github.com/Akryum/vue-virtual-scroller/issues/473)) ([f9124aa](https://github.com/Akryum/vue-virtual-scroller/commit/f9124aa81c36b46df339a5f18e0e832ab6e5a580)) * DynamicScroller should pass its own keyField prop to child RecycleScroller ([#732](https://github.com/Akryum/vue-virtual-scroller/issues/732)) ([9673679](https://github.com/Akryum/vue-virtual-scroller/commit/9673679fc174cd6236fae4e19a9b1a3b625e900e)) * **DynamicScrollerItem:** watch item prop ([#700](https://github.com/Akryum/vue-virtual-scroller/issues/700)) ([4d3b956](https://github.com/Akryum/vue-virtual-scroller/commit/4d3b95651610b8396c8dff66af9267407eab8e72)) * issue with beforeDestroy hook ([#748](https://github.com/Akryum/vue-virtual-scroller/issues/748)) ([59f3f1b](https://github.com/Akryum/vue-virtual-scroller/commit/59f3f1b0aee9ab8ea276fee60e204b6dcc0baceb)) * merge ([c8363b1](https://github.com/Akryum/vue-virtual-scroller/commit/c8363b114f691042dbced3b5b79d2ebd7812f481)) * restore scroll in keep-alive ([#724](https://github.com/Akryum/vue-virtual-scroller/issues/724)) ([5011e06](https://github.com/Akryum/vue-virtual-scroller/commit/5011e06f2aa6ef8afa6ecaad804413e56a542c8d)) * scrollToItem works with pageMode ([#396](https://github.com/Akryum/vue-virtual-scroller/issues/396)) ([c9772bf](https://github.com/Akryum/vue-virtual-scroller/commit/c9772bfb9e87672de1480072c4d5dc8024d1e5d1)) * wrap the callback in requestAnimationFrame, fix [#516](https://github.com/Akryum/vue-virtual-scroller/issues/516) ([#517](https://github.com/Akryum/vue-virtual-scroller/issues/517)) ([6f359ab](https://github.com/Akryum/vue-virtual-scroller/commit/6f359abed6cf5d81a05d3760d6b622153f331f01)) ### Features * add an empty slot ([#398](https://github.com/Akryum/vue-virtual-scroller/issues/398)) ([5c2715c](https://github.com/Akryum/vue-virtual-scroller/commit/5c2715c0a2c52b0c27436baabbf982fcb9861131)) * add skipHover prop to deactive the hover detection ([#752](https://github.com/Akryum/vue-virtual-scroller/issues/752)) ([b613318](https://github.com/Akryum/vue-virtual-scroller/commit/b613318a52d4d8f84bda69f0189f27dd51d0aaff)) * adds configurable list/item tags for semantic html ([#203](https://github.com/Akryum/vue-virtual-scroller/issues/203)) ([3d24dc3](https://github.com/Akryum/vue-virtual-scroller/commit/3d24dc31928ec9eabe74294e5d5b3466109e1bc2)) * custom classes for list wrapper and list items. ([#397](https://github.com/Akryum/vue-virtual-scroller/issues/397)) ([32b285d](https://github.com/Akryum/vue-virtual-scroller/commit/32b285d40667870b65c71dc59b02627f97c67ea4)) * Emit events for scroll to begin and end of list ([#364](https://github.com/Akryum/vue-virtual-scroller/issues/364)) ([2a7bfd4](https://github.com/Akryum/vue-virtual-scroller/commit/2a7bfd45e1ee56e82426a67d9f3f3ba5a7839185)) * gridItems prop ([#27](https://github.com/Akryum/vue-virtual-scroller/issues/27)) ([6339e72](https://github.com/Akryum/vue-virtual-scroller/commit/6339e72693c982805648ae3001b7c2957d8aa39e)) * itemSecondarySize ([43d311c](https://github.com/Akryum/vue-virtual-scroller/commit/43d311c2f336de74da4d0ec705b0a3546eeda153)) * throw error when key field does not exist in item ([#265](https://github.com/Akryum/vue-virtual-scroller/issues/265)) ([c63129f](https://github.com/Akryum/vue-virtual-scroller/commit/c63129fdc8264d25c737db1c2ce2891a9b804705)) * update event provide range of the visible items ([#115](https://github.com/Akryum/vue-virtual-scroller/issues/115)) ([f19af6c](https://github.com/Akryum/vue-virtual-scroller/commit/f19af6c15346ff33e5d3c4b9729b02a73d5fe4df)) ### Performance Improvements * skipHover: don't add event listeners ([6b623b5](https://github.com/Akryum/vue-virtual-scroller/commit/6b623b56e4ab481b1e0cde883682df2cc81edf19)) ================================================ FILE: README.md ================================================ # vue-virtual-scroller [![npm](https://img.shields.io/npm/v/vue-virtual-scroller.svg) ![npm](https://img.shields.io/npm/dm/vue-virtual-scroller.svg)](https://www.npmjs.com/package/vue-virtual-scroller) [![vue3](https://img.shields.io/badge/vue-3.x-brightgreen.svg)](https://vuejs.org/) [Documentation](https://vue-virtual-scroller.netlify.app/) Blazing fast scrolling of any amount of data | [Live demo](https://vue-virtual-scroller-demo.netlify.app/) | [Video demo](https://www.youtube.com/watch?v=Uzq1KQV8f4k) For Vue 2 support, see [here](https://github.com/Akryum/vue-virtual-scroller/tree/v1/packages/vue-virtual-scroller) This package ships ESM only in the current Vue 3 line. Use it with an ESM-aware toolchain such as Vite, Nuxt, Rollup, or webpack 5. [💚️ Become a Sponsor](https://github.com/sponsors/Akryum) ## Sponsors

sponsors

================================================ FILE: SKILLS-GENERATION.md ================================================ # Skills Generation (vue-virtual-scroller) This file is the canonical process for generating and updating package skills in this repository. ## Scope This process currently covers one package skill: - `packages/vue-virtual-scroller/skills/vue-virtual-scroller` This process does not cover: - `packages/demo` as a standalone skill target - internal implementation-only helpers that are not documented as public APIs ## Sources of truth Always generate skill content from public documentation first, not from memory. If implementation behavior appears to differ from docs, fix docs first, then regenerate the skill from the updated docs. ### Primary docs - `docs/index.md` - `docs/guide/index.md` - `docs/guide/recycle-scroller.md` - `docs/guide/dynamic-scroller.md` - `docs/guide/dynamic-scroller-item.md` - `docs/guide/id-state.md` - `docs/guide/use-recycle-scroller.md` ### Supporting examples Use these to sharpen examples and workflow guidance, not to invent undocumented API behavior: - `docs/demos/index.md` - `docs/demos/recycle-scroller.md` - `docs/demos/dynamic-scroller.md` - `docs/demos/chat.md` - `docs/demos/simple-list.md` - `docs/demos/horizontal.md` - `docs/demos/grid.md` - `docs/demos/test-chat.md` - `packages/demo/src/**` ### Public-export verification Use these only to verify package exports, option names, and known docs gaps: - `packages/vue-virtual-scroller/src/index.ts` - `packages/vue-virtual-scroller/src/types.ts` - `packages/vue-virtual-scroller/README.md` If an exported surface is not documented enough to support skill content, update docs first or explicitly leave that surface out of the generated skill. Current areas that require extra care: - `docs/guide/id-state.md` describes `IdState`, while the current package exports `useIdState` - `useDynamicScroller` and `useDynamicScrollerItem` are exported but do not currently have guide pages - plugin install options such as `installComponents` and `componentsPrefix` are exported but not fully documented in the guide Do not silently fill those gaps from source code into the skill. Either document them first or keep them out of the generated skill. ## Output files Generate one skill folder for the published package: 1. `packages/vue-virtual-scroller/skills/vue-virtual-scroller/SKILL.md` 2. `packages/vue-virtual-scroller/skills/vue-virtual-scroller/references/index.md` 3. One reference file per documented public surface or recurring workflow Expected initial reference set for this repo: - `packages/vue-virtual-scroller/skills/vue-virtual-scroller/references/installation-and-setup.md` - `packages/vue-virtual-scroller/skills/vue-virtual-scroller/references/recycle-scroller.md` - `packages/vue-virtual-scroller/skills/vue-virtual-scroller/references/dynamic-scroller.md` - `packages/vue-virtual-scroller/skills/vue-virtual-scroller/references/dynamic-scroller-item.md` - `packages/vue-virtual-scroller/skills/vue-virtual-scroller/references/use-recycle-scroller.md` Optional reference files: - `packages/vue-virtual-scroller/skills/vue-virtual-scroller/references/id-state.md` only after docs and exports are reconciled - `packages/vue-virtual-scroller/skills/vue-virtual-scroller/references/patterns-and-guardrails.md` if the core skill becomes too dense Do not force an `api-*.md` naming pattern here. This repo is better represented by one file per component, composable, or usage decision. ## Required `SKILL.md` structure Each generated `SKILL.md` should include: 1. YAML frontmatter: - `name` - `description` as a single line that clearly mentions Vue virtual scrolling, `RecycleScroller`, `DynamicScroller`, and headless usage so the skill triggers correctly 2. Title and one-line summary 3. A quick decision table for when to use: - `RecycleScroller` - `DynamicScroller` - `DynamicScrollerItem` - `useRecycleScroller` 4. Setup snippet that includes: - package install - ESM-only note - CSS import (`vue-virtual-scroller/index.css`) - plugin install or direct component import 5. Practical guidance sections for: - choosing fixed-size vs variable-size rendering - when to switch from `RecycleScroller` to `DynamicScroller` - required sizing/CSS constraints - performance guardrails and reuse pitfalls - common layouts such as chat feeds, grids, and horizontal scrollers 6. References section containing a table with `Topic`, `Description`, and `Reference` 7. Further reading section linking only to shipped reference files and, if needed, stable package-level external URLs ## Required references structure Each skill should include a `references/` folder with surface-focused reference files. Keep references one level deep from `SKILL.md`. Mandatory layout: - `references/index.md`: maps each documented surface and workflow topic to exactly one reference file - `references/.md`: one file per documented public surface or focused workflow Each reference file should: - start with a short title and one-line scope - include a short provenance section without referencing repository-local file paths outside the published package - include sections in this order when possible: - `When to use` - `Required inputs` - `Core props/options` - `Events/returns` - `Pitfalls` - `Example patterns` - stay grounded in current docs - focus on user-facing behavior, not internal implementation detail - avoid chaining into nested references - avoid bundling unrelated surfaces into one file ## Writing constraints - Keep guidance practical and tied to current public behavior. - Prefer decisions and guardrails over generic marketing language. - Always mention that the package is Vue 3 and ESM-only when setup is discussed. - Always mention the required CSS import when installation/setup is discussed. - Do not invent APIs, props, events, or helper functions that are not documented. - Do not describe Vue 2 usage in the generated skill for this repo. - Use demo pages to illustrate patterns such as chat streams, grids, horizontal scrolling, and stress-tested append flows. - Never reference repository-local files outside the published package from `SKILL.md` or `references/*.md`. - In shipped skill files, only link to other shipped skill files or stable external package URLs. - If the repo documents AI-agent consumption with `skills-npm`, keep that guidance in the VitePress docs, not in the shipped skill files. - Do not generate or update `agents/openai.yaml` for this workflow. ## Generation workflow ### 1. Gather context ```bash rg --files docs packages/vue-virtual-scroller rg -n "RecycleScroller|DynamicScroller|DynamicScrollerItem|useRecycleScroller|useDynamicScroller|useDynamicScrollerItem|useIdState|installComponents|componentsPrefix|ESM" \ docs \ packages/vue-virtual-scroller/src/index.ts \ packages/vue-virtual-scroller/src/types.ts \ packages/vue-virtual-scroller/README.md ``` Read the primary docs files first. Use demos and package exports to check scope and examples. If docs are missing, outdated, or contradictory, update docs first and use the updated docs as the generation input. ### 2. Decide skill coverage Start from documented public surfaces only. For the current repo baseline, the minimum covered surfaces should be: - installation/setup - `RecycleScroller` - `DynamicScroller` - `DynamicScrollerItem` - `useRecycleScroller` Only add `id-state`, `useDynamicScroller`, `useDynamicScrollerItem`, or plugin option references after the docs clearly support them. ### 3. Generate or update the skill - Regenerate `SKILL.md` using the required structure above. - Regenerate `references/index.md`. - Regenerate one reference file per documented surface or workflow topic. - Ensure `SKILL.md` links to `references/index.md`. - Keep the top-level skill concise and move detail into `references/*.md`. ### 4. Validate generated skill files ```bash sed -n '1,260p' packages/vue-virtual-scroller/skills/vue-virtual-scroller/SKILL.md sed -n '1,260p' packages/vue-virtual-scroller/skills/vue-virtual-scroller/references/index.md rg --files packages/vue-virtual-scroller/skills/vue-virtual-scroller/references ``` Checklist: - [ ] Frontmatter is valid and the description is specific enough to trigger on virtual scrolling tasks. - [ ] Setup guidance includes the ESM-only note and the CSS import. - [ ] The choose-the-right-surface guidance distinguishes `RecycleScroller`, `DynamicScroller`, and headless usage correctly. - [ ] Fixed-size, variable-size, page mode, and common performance pitfalls are grounded in current docs. - [ ] `references/index.md` exists and links to every reference file. - [ ] Each reference file covers one surface or one focused workflow only. - [ ] No shipped skill file links to repository-local paths outside the package. - [ ] Any API not fully documented in the guide has been omitted or documented first. ### 5. Record generation metadata After regeneration, update this document with: - generation date - docs/package baseline commit SHA - version notes if the public package surface changed - generated artifacts ## Incremental update process When docs or public exports change, update only impacted skill sections. ```bash git diff ..HEAD -- docs packages/vue-virtual-scroller/src/index.ts packages/vue-virtual-scroller/src/types.ts packages/vue-virtual-scroller/README.md git diff --name-only ..HEAD -- docs packages/vue-virtual-scroller/src/index.ts packages/vue-virtual-scroller/src/types.ts packages/vue-virtual-scroller/README.md ``` Then: 1. Map changed docs or export files to affected skill sections. 2. If exports changed without docs updates, fix docs first unless the skill already omits that surface. 3. Update only the affected `SKILL.md` sections and reference files. 4. Re-run the validation checklist. 5. Refresh metadata below. ## Current generation metadata - Last generation date: `2026-03-10T14:40:32+01:00` - Baseline commit SHA: `4ffe378192353c24e474d7541c649613458cf1eb` - Baseline short SHA: `4ffe378` - Baseline commit date: `2026-03-10T14:25:42+01:00` - Baseline commit message: `refactor: esm only` - Generated artifacts: - `packages/vue-virtual-scroller/skills/vue-virtual-scroller/SKILL.md` - `packages/vue-virtual-scroller/skills/vue-virtual-scroller/references/index.md` - `packages/vue-virtual-scroller/skills/vue-virtual-scroller/references/installation-and-setup.md` - `packages/vue-virtual-scroller/skills/vue-virtual-scroller/references/recycle-scroller.md` - `packages/vue-virtual-scroller/skills/vue-virtual-scroller/references/dynamic-scroller.md` - `packages/vue-virtual-scroller/skills/vue-virtual-scroller/references/dynamic-scroller-item.md` - `packages/vue-virtual-scroller/skills/vue-virtual-scroller/references/use-recycle-scroller.md` ## Notes - There is no dedicated generation script in this repository yet. - Generation is currently a documented manual process with reproducible inspection commands. - `packages/demo` exists as an example application and validation aid, not as a primary skill output target. - To make shipped skills consumable through `skills-npm`, the published `vue-virtual-scroller` package must include the `skills/` directory in its packaged files. ================================================ FILE: docs/.vitepress/components/demos/ChatStreamDocDemo.vue ================================================ ================================================ FILE: docs/.vitepress/components/demos/DemoShell.vue ================================================ ================================================ FILE: docs/.vitepress/components/demos/DynamicScrollerDocDemo.vue ================================================ ================================================ FILE: docs/.vitepress/components/demos/GridDocDemo.vue ================================================ ================================================ FILE: docs/.vitepress/components/demos/HorizontalDocDemo.vue ================================================ ================================================ FILE: docs/.vitepress/components/demos/RecycleScrollerDocDemo.vue ================================================ ================================================ FILE: docs/.vitepress/components/demos/SimpleListDocDemo.vue ================================================ ================================================ FILE: docs/.vitepress/components/demos/TestChatDocDemo.vue ================================================ ================================================ FILE: docs/.vitepress/components/demos/demo-data.ts ================================================ export interface PersonRow { id: number index: number type: 'person' | 'letter' value: string | Person height: number } export interface Person { name: string initials: string hue: number } export interface MessageRow { id: number user: string initials: string hue: number message: string timestamp: string } const FIRST_NAMES = [ 'Avery', 'Riley', 'Jordan', 'Quinn', 'Morgan', 'Rowan', 'Sage', 'Parker', 'Casey', 'Reese', 'Dakota', 'Alex', 'Jamie', 'Taylor', 'Harper', 'Mika', 'Noa', 'Arden', 'River', 'Kai', ] const LAST_NAMES = [ 'Anderson', 'Bennett', 'Carter', 'Diaz', 'Edwards', 'Fletcher', 'Garcia', 'Hughes', 'Ingram', 'Johnson', 'Khan', 'Lopez', 'Miller', 'Nguyen', 'Ortiz', 'Patel', 'Quincy', 'Rivera', 'Sato', 'Turner', ] const WORDS = [ 'virtual', 'scrolling', 'profile', 'buffer', 'dynamic', 'render', 'smooth', 'window', 'active', 'message', 'compute', 'layout', 'viewport', 'recycle', 'velocity', 'index', 'height', 'width', 'visibility', 'performant', 'batch', 'stream', 'queue', 'resize', 'observe', 'compose', 'discover', 'cluster', 'card', 'slot', ] function createRng(seed = 1) { let value = seed >>> 0 return () => { value = (Math.imul(1664525, value) + 1013904223) >>> 0 return value / 4294967296 } } function pick(rng: () => number, values: T[]) { return values[Math.floor(rng() * values.length)] } function capitalize(text: string) { return text.charAt(0).toUpperCase() + text.slice(1) } function sentence(rng: () => number, minWords = 8, maxWords = 20) { const length = minWords + Math.floor(rng() * (maxWords - minWords + 1)) const parts: string[] = [] for (let i = 0; i < length; i++) { parts.push(pick(rng, WORDS)) } return `${capitalize(parts.join(' '))}.` } function initialsFromName(name: string) { const parts = name.split(' ') return `${parts[0]?.charAt(0) ?? ''}${parts[1]?.charAt(0) ?? ''}`.toUpperCase() } function hueFromText(text: string, salt = 0) { let hash = salt for (let i = 0; i < text.length; i++) { hash = (hash * 31 + text.charCodeAt(i)) % 360 } return (hash + 360) % 360 } export function avatarStyle(hue: number) { return { background: `linear-gradient(145deg, hsl(${hue} 68% 44%), hsl(${(hue + 32) % 360} 70% 36%))`, } } export function createPeopleRows(count: number, withLetters = true, seed = 42) { const rng = createRng(seed) const byLetter = new Map() for (let i = 0; i < count; i++) { const name = `${pick(rng, FIRST_NAMES)} ${pick(rng, LAST_NAMES)}` const letter = name.charAt(0).toLowerCase() const person: Person = { name, initials: initialsFromName(name), hue: hueFromText(name), } const bucket = byLetter.get(letter) ?? [] bucket.push(person) byLetter.set(letter, bucket) } const rows: PersonRow[] = [] const letters = 'abcdefghijklmnopqrstuvwxyz'.split('') let index = 0 let id = 1 for (const letter of letters) { const bucket = (byLetter.get(letter) ?? []).sort((a, b) => a.name.localeCompare(b.name)) if (!bucket.length) continue if (withLetters) { rows.push({ id: id++, index: index++, type: 'letter', value: letter, height: 96, }) } for (const person of bucket) { rows.push({ id: id++, index: index++, type: 'person', value: person, height: 74, }) } } return rows } export function createMessages(count: number, seed = 99) { const rng = createRng(seed) const list: MessageRow[] = [] for (let i = 0; i < count; i++) { const user = `${pick(rng, FIRST_NAMES)} ${pick(rng, LAST_NAMES)}` const timestamp = `${String(8 + Math.floor((i % 720) / 60)).padStart(2, '0')}:${String(i % 60).padStart(2, '0')}` list.push({ id: i + 1, user, initials: initialsFromName(user), hue: hueFromText(user, i), message: `${sentence(rng)} ${rng() > 0.5 ? sentence(rng, 4, 11) : ''}`.trim(), timestamp, }) } return list } export function mutateMessage(row: MessageRow, seed = 1234) { const rng = createRng(seed + row.id) row.message = `${sentence(rng, 5, 14)} ${sentence(rng, 8, 18)}` } export function createSimpleStrings(count: number, seed = 7) { const rng = createRng(seed) const list: string[] = [] for (let i = 0; i < count; i++) { list.push(`${sentence(rng, 5, 14)} ${rng() > 0.6 ? sentence(rng, 4, 10) : ''}`.trim()) } return list } const GRADIENTS = [ 'linear-gradient(145deg, #57cc99, #2d6a4f)', 'linear-gradient(145deg, #ff8fa3, #7b2cbf)', 'linear-gradient(145deg, #56cfe1, #4361ee)', 'linear-gradient(145deg, #ffd166, #f77f00)', 'linear-gradient(145deg, #52b788, #1b4332)', 'linear-gradient(145deg, #f8961e, #f94144)', ] export function gradientAt(index: number) { return GRADIENTS[index % GRADIENTS.length] } ================================================ FILE: docs/.vitepress/config.mts ================================================ import { defineConfig } from 'vitepress' export default defineConfig({ title: 'Vue Virtual Scroller', description: 'Blazing fast scrolling of any amount of data', themeConfig: { nav: [ { text: 'Guide', link: '/guide/' }, { text: 'Demos', link: '/demos/' }, { text: 'Links', items: [ { text: 'Live Demo', link: 'https://vue-virtual-scroller-demo.netlify.app/' }, { text: 'GitHub', link: 'https://github.com/Akryum/vue-virtual-scroller' }, { text: 'Changelog', link: 'https://github.com/Akryum/vue-virtual-scroller/blob/master/CHANGELOG.md' }, ], }, ], sidebar: { '/guide/': [ { text: 'Introduction', items: [ { text: 'Getting Started', link: '/guide/' }, ], }, { text: 'Components', items: [ { text: 'RecycleScroller', link: '/guide/recycle-scroller' }, { text: 'DynamicScroller', link: '/guide/dynamic-scroller' }, { text: 'DynamicScrollerItem', link: '/guide/dynamic-scroller-item' }, ], }, { text: 'Utilities', items: [ { text: 'IdState', link: '/guide/id-state' }, { text: 'Headless (useRecycleScroller)', link: '/guide/use-recycle-scroller' }, ], }, { text: 'AI & Skills', link: '/guide/ai-skills' }, ], '/demos/': [ { text: 'Demos', items: [ { text: 'Overview', link: '/demos/' }, { text: 'RecycleScroller', link: '/demos/recycle-scroller' }, { text: 'DynamicScroller', link: '/demos/dynamic-scroller' }, { text: 'Chat Stream', link: '/demos/chat' }, { text: 'Simple List', link: '/demos/simple-list' }, { text: 'Horizontal', link: '/demos/horizontal' }, { text: 'Grid', link: '/demos/grid' }, { text: 'Test Chat', link: '/demos/test-chat' }, ], }, ], }, socialLinks: [ { icon: 'github', link: 'https://github.com/Akryum/vue-virtual-scroller' }, ], footer: { message: 'Released under the MIT License.', copyright: 'Copyright Akryum', }, search: { provider: 'local', }, }, }) ================================================ FILE: docs/.vitepress/theme/index.ts ================================================ import DefaultTheme from 'vitepress/theme' import './style.css' export default { extends: DefaultTheme, } ================================================ FILE: docs/.vitepress/theme/style.css ================================================ :root { --demo-bg: linear-gradient(145deg, #f4f8f2 0%, #edf7f6 48%, #f8f2e9 100%); --demo-surface: rgba(255, 255, 255, 0.86); --demo-border: rgba(47, 73, 59, 0.16); --demo-accent: #2f7a52; --demo-accent-soft: rgba(47, 122, 82, 0.12); --demo-text: #173224; --demo-muted: #4c6a5c; --demo-shadow: 0 12px 35px rgba(13, 42, 29, 0.12); } .demo-shell { border: 1px solid var(--demo-border); border-radius: 18px; background: var(--demo-bg); box-shadow: var(--demo-shadow); overflow: hidden; margin: 18px 0 26px; } .demo-shell__header { padding: 18px 20px; border-bottom: 1px solid var(--demo-border); background: linear-gradient(180deg, rgba(255, 255, 255, 0.75), rgba(255, 255, 255, 0.55)); } .demo-shell__title { margin: 0; color: var(--demo-text); font-family: 'Avenir Next', 'Helvetica Neue', 'Segoe UI', sans-serif; font-size: 1.05rem; letter-spacing: 0.01em; } .demo-shell__description { margin: 6px 0 0; color: var(--demo-muted); font-size: 0.92rem; line-height: 1.45; } .demo-shell__toolbar { display: flex; flex-wrap: wrap; gap: 10px; padding: 12px 18px; border-bottom: 1px solid var(--demo-border); background: rgba(255, 255, 255, 0.52); } .demo-shell__viewport { padding: 16px; } .demo-chip { display: inline-flex; align-items: center; height: 34px; gap: 8px; border-radius: 999px; padding: 0 12px; color: var(--demo-text); background: var(--demo-surface); border: 1px solid var(--demo-border); box-shadow: 0 3px 10px rgba(13, 42, 29, 0.06); font-size: 0.84rem; } .demo-chip input, .demo-chip button, .demo-chip select { border: 0; outline: 0; background: transparent; color: inherit; font: inherit; } .demo-chip input[type="number"], .demo-chip input[type="text"] { width: 78px; } .demo-chip input[type="range"] { width: 110px; } .demo-button { border: 1px solid color-mix(in srgb, var(--demo-accent) 70%, #fff 30%); background: linear-gradient(180deg, #4ba774, #2f7a52); color: #fff; border-radius: 999px; padding: 4px 12px; cursor: pointer; font-size: 0.82rem; font-weight: 600; } .demo-button.secondary { background: #fff; color: var(--demo-accent); border-color: rgba(47, 122, 82, 0.35); } .demo-viewport { height: 560px; border-radius: 14px; background: rgba(255, 255, 255, 0.6); border: 1px solid var(--demo-border); overflow: hidden; } .demo-person-row { min-height: 74px; display: grid; grid-template-columns: 52px 1fr auto; gap: 12px; align-items: center; padding: 10px 16px; border-bottom: 1px solid rgba(0, 0, 0, 0.06); } .demo-avatar { width: 44px; height: 44px; border-radius: 50%; display: grid; place-items: center; color: #fff; font-size: 0.92rem; font-weight: 700; } .demo-letter-row { display: flex; align-items: center; justify-content: space-between; padding: 0 16px; background: linear-gradient(90deg, rgba(47, 122, 82, 0.16), rgba(47, 122, 82, 0.04)); border-bottom: 1px solid rgba(47, 122, 82, 0.14); cursor: pointer; } .demo-letter-row strong { font-size: 1.35rem; text-transform: uppercase; color: #214935; } .demo-message-row { display: grid; grid-template-columns: 42px 1fr auto; gap: 10px; align-items: flex-start; padding: 10px 14px; border-bottom: 1px solid rgba(0, 0, 0, 0.06); cursor: pointer; } .demo-message-body { color: #1f352a; line-height: 1.4; } .demo-message-meta { color: #6a7f74; font-size: 0.78rem; white-space: nowrap; } .demo-notice { margin: 10px; padding: 10px 12px; border-radius: 10px; border: 1px dashed rgba(47, 122, 82, 0.35); color: #2e5c43; background: var(--demo-accent-soft); } .demo-grid-card { height: 100%; border-radius: 14px; border: 1px solid rgba(0, 0, 0, 0.08); color: #fff; padding: 12px; display: flex; flex-direction: column; justify-content: space-between; box-shadow: 0 6px 16px rgba(0, 0, 0, 0.15); } .demo-horizontal-track { height: 320px; } .demo-horizontal-card { height: 100%; border-right: 1px solid rgba(0, 0, 0, 0.08); padding: 12px; display: flex; flex-direction: column; gap: 8px; background: linear-gradient(180deg, rgba(255, 255, 255, 0.7), rgba(255, 255, 255, 0.5)); } .demo-chat-bubble { border-radius: 14px; padding: 10px 12px; background: rgba(255, 255, 255, 0.92); border: 1px solid rgba(0, 0, 0, 0.06); } @media (max-width: 760px) { .demo-shell__toolbar { gap: 8px; padding: 10px; } .demo-chip { width: 100%; justify-content: space-between; } .demo-viewport { height: 470px; } } ================================================ FILE: docs/demos/chat.md ================================================ # Chat Stream Demo Use this demo for chat, logs, and live feeds that continuously append data. What to try: - Start/stop the stream and observe scroll stability. - Append large batches (`+20 messages`) to validate throughput. - Apply filters while data is growing. - Confirm the list stays pinned near the latest items. ## Relevant source code ```vue ``` ================================================ FILE: docs/demos/dynamic-scroller.md ================================================ # DynamicScroller Demo Use this demo when item height is not known ahead of time. What to try: - Filter the list to verify virtualization still behaves correctly. - Click messages to mutate content and trigger automatic re-measurement. - Adjust `Min row size` to see first-render tradeoffs. - Watch the visible range to understand viewport updates. ## Relevant source code ```vue ``` ================================================ FILE: docs/demos/grid.md ================================================ # Grid Demo Use this demo for card galleries and catalog layouts. What to try: - Change `Items / row` to test responsiveness. - Jump to deep indexes with `Scroll to`. - Validate performance with thousands of cards. ## Relevant source code ```vue ``` ================================================ FILE: docs/demos/horizontal.md ================================================ # Horizontal Demo Use this demo for horizontally scrolling lists with dynamic item width. What to try: - Scroll horizontally with trackpad or Shift + mouse wheel. - Filter cards and verify smooth reflow. - Inspect how variable-width content stays virtualized. ## Relevant source code ```vue ``` ================================================ FILE: docs/demos/index.md ================================================ # Demos Interactive demos for common real-world use cases. ## Pick a demo - [RecycleScroller demo](./recycle-scroller) — fixed or variable-size rows with large datasets. - [DynamicScroller demo](./dynamic-scroller) — unknown row heights with live size recalculation. - [Chat stream demo](./chat) — append-only feeds with auto-scroll to bottom. - [Simple list demo](./simple-list) — compare `DynamicScroller` and `RecycleScroller` quickly. - [Horizontal demo](./horizontal) — dynamic-size cards in horizontal direction. - [Grid demo](./grid) — multi-column virtualized layouts. - [Test chat demo](./test-chat) — stress-test frequent insertions and bottom pinning. ================================================ FILE: docs/demos/recycle-scroller.md ================================================ # RecycleScroller Demo Use this demo when your list items have known sizes, or when sizes can be provided by data. What to try: - Change `Items` to simulate very large datasets. - Toggle `Variable height` and click letter rows to see size updates. - Tune `Buffer` to understand render-ahead behavior. - Use `Jump` to test `scrollToItem`. ## Relevant source code ```vue ``` ================================================ FILE: docs/demos/simple-list.md ================================================ # Simple List Demo Use this demo to compare dynamic and fixed-size strategies on the same dataset. What to try: - Toggle `Dynamic mode` on/off to compare behavior. - Filter the list and compare how both modes respond. - Use this as a reference when deciding between `DynamicScroller` and `RecycleScroller`. ## Relevant source code ```vue ``` ================================================ FILE: docs/demos/test-chat.md ================================================ # Test Chat Demo Use this demo to test append-heavy timelines and quick burst updates. What to try: - Add rows in different batch sizes (`+1`, `+5`, `+20`, `+80`). - Confirm auto-scroll behavior under repeated inserts. - Use it as a sanity check for real-time message UIs. ## Relevant source code ```vue ``` ================================================ FILE: docs/guide/ai-skills.md ================================================ # AI & Skills If you use AI coding agents, `vue-virtual-scroller` ships a package skill that can be discovered from the installed npm package. ## One-off usage with `npx skills-npm` After installing `vue-virtual-scroller` in your project: ```bash pnpm add vue-virtual-scroller@next npx skills-npm ``` This lets supported coding agents discover the skill that ships inside the package. ## Repeatable setup If you want skill links to refresh automatically after installs: ```bash npm i -D skills-npm ``` Add a `prepare` script in your project: ```json { "scripts": { "prepare": "skills-npm" } } ``` ## Useful options - `--source ` chooses `package.json` or `node_modules` - `--cwd ` targets a specific workspace root - `--recursive` scans monorepos - `--dry-run` previews the generated links - `--yes` skips prompts For more control, create a `skills-npm.config.ts` file in your consumer project. Learn more about `skills-npm` [here](https://github.com/antfu/skills-npm#skills-npm). ## Notes - Run `skills-npm` from the consumer project root, not from this package repository. - Generated links are typically local setup artifacts. Add `skills/npm-*` to `.gitignore` if you do not want them committed. - The published `vue-virtual-scroller` package includes its `skills/` directory so discovery tools can find the shipped skill. ================================================ FILE: docs/guide/dynamic-scroller-item.md ================================================ # DynamicScrollerItem The component that should wrap all the items in a [DynamicScroller](./dynamic-scroller) to handle size computations. ## Props | Prop | Default | Description | |------|---------|-------------| | `item` (required) | — | The item rendered in the scroller. | | `active` (required) | — | Is the holding view active in RecycleScroller. Will prevent unnecessary size recomputation. | | `sizeDependencies` | — | Values that can affect the size of the item. This prop will be watched and if one value changes, the size will be recomputed. Recommended instead of `watchData`. | | `watchData` | `false` | Deeply watch `item` for changes to re-calculate the size (not recommended, can impact performance). | | `tag` | `'div'` | Element used to render the component. | | `emitResize` | `false` | Emit the `resize` event each time the size is recomputed (can impact performance). | ## Events | Event | Description | |-------|-------------| | `resize` | Emitted each time the size is recomputed, only if `emitResize` prop is `true`. | ================================================ FILE: docs/guide/dynamic-scroller.md ================================================ # DynamicScroller This works just like the [RecycleScroller](./recycle-scroller), but it can render items with unknown sizes! ## Basic usage ```vue ``` ## Important notes - `minItemSize` is required for the initial render of items. - `DynamicScroller` won't detect size changes on its own, but you can put values that can affect the item size with `size-dependencies` on [DynamicScrollerItem](./dynamic-scroller-item). - You don't need to have a `size` field on the items. ## Props Extends all the [RecycleScroller props](./recycle-scroller#props). ::: tip It's not recommended to change the `sizeField` prop since all the size management is done internally. ::: ## Events Extends all the [RecycleScroller events](./recycle-scroller#events). ## Default scoped slot props Extends all the [RecycleScroller scoped slot props](./recycle-scroller#default-scoped-slot-props). ## Other slots Extends all the [RecycleScroller other slots](./recycle-scroller#other-slots). ================================================ FILE: docs/guide/id-state.md ================================================ # IdState This is a convenience mixin that can replace `data` in components being rendered in a [RecycleScroller](./recycle-scroller). ## Why is this useful? Since the components in RecycleScroller are reused, you can't directly use the Vue standard `data` properties: otherwise they will be shared with different items in the list! IdState will instead provide an `idState` object which is equivalent to `$data`, but it's linked to a single item with its identifier (you can change which field with `idProp` param). ## Example In this example, we use the `id` of the `item` to have a "scoped" state to the item: ```vue