From 314e7d6592255c18c11473b0078ccb325041268d Mon Sep 17 00:00:00 2001 From: Damian Pieczynski Date: Mon, 16 Jan 2023 22:25:19 +0100 Subject: [PATCH] fix(virtual-core): scrollToIndex align end gets "stuck" --- examples/react/dynamic/src/main.tsx | 10 +- package-lock.json | 167 ++++++++++++++++++++-------- packages/react-virtual/package.json | 10 +- packages/virtual-core/src/index.ts | 38 ++++--- 4 files changed, 156 insertions(+), 69 deletions(-) diff --git a/examples/react/dynamic/src/main.tsx b/examples/react/dynamic/src/main.tsx index ee73d276e..1b765bc4c 100644 --- a/examples/react/dynamic/src/main.tsx +++ b/examples/react/dynamic/src/main.tsx @@ -27,6 +27,14 @@ function RowVirtualizerDynamic() { return (
+ +
=8" } }, - "node_modules/@testing-library/react": { - "version": "12.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.12.5", - "@testing-library/dom": "^8.0.0" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "react": "*", - "react-dom": "*" - } - }, "node_modules/@tootallnate/once": { "version": "1.1.2", "dev": true, @@ -5441,9 +5425,10 @@ } }, "node_modules/@types/react-dom": { - "version": "18.0.9", + "version": "18.0.10", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.10.tgz", + "integrity": "sha512-E42GW/JA4Qv15wQdqJq8DL4JhNpB3prJgjgapN3qJT9K2zO5IIAQh4VXvCEDupoqAwnz0cY4RlXeC/ajX5SFHg==", "dev": true, - "license": "MIT", "dependencies": { "@types/react": "*" } @@ -15792,11 +15777,11 @@ "@tanstack/virtual-core": "3.0.0-beta.36" }, "devDependencies": { - "@testing-library/react": "^12.1.2", - "@types/react": "17.0.45", - "@types/react-dom": "17.0.17", - "react": "^17.0.2", - "react-dom": "^17.0.2", + "@testing-library/react": "^13.4.0", + "@types/react": "18.0.26", + "@types/react-dom": "18.0.10", + "react": "^18.2.0", + "react-dom": "^18.2.0", "resize-observer-polyfill": "^1.5.1" }, "funding": { @@ -15807,12 +15792,67 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "packages/react-virtual/node_modules/@types/react-dom": { - "version": "17.0.17", + "packages/react-virtual/node_modules/@testing-library/react": { + "version": "13.4.0", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-13.4.0.tgz", + "integrity": "sha512-sXOGON+WNTh3MLE9rve97ftaZukN3oNf2KjDy7YTx6hcTO2uuLHuCGynMDhFwGw/jYf4OJ2Qk0i4i79qMNNkyw==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.12.5", + "@testing-library/dom": "^8.5.0", + "@types/react-dom": "^18.0.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "packages/react-virtual/node_modules/@types/react": { + "version": "18.0.26", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.26.tgz", + "integrity": "sha512-hCR3PJQsAIXyxhTNSiDFY//LhnMZWpNNr5etoCqx/iUfGc5gXWtQR2Phl908jVR6uPXacojQWTg4qRpkxTuGug==", + "dev": true, + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "packages/react-virtual/node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "dev": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/react-virtual/node_modules/react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "dev": true, + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, + "packages/react-virtual/node_modules/scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", "dev": true, - "license": "MIT", "dependencies": { - "@types/react": "^17" + "loose-envify": "^1.1.0" } }, "packages/solid-virtual": { @@ -15835,7 +15875,7 @@ }, "packages/svelte-virtual": { "name": "@tanstack/svelte-virtual", - "version": "3.0.0-beta.37", + "version": "3.0.0-beta.38", "license": "MIT", "dependencies": { "@tanstack/virtual-core": "3.0.0-beta.36" @@ -19047,19 +19087,62 @@ "version": "file:packages/react-virtual", "requires": { "@tanstack/virtual-core": "3.0.0-beta.36", - "@testing-library/react": "^12.1.2", - "@types/react": "17.0.45", - "@types/react-dom": "17.0.17", - "react": "^17.0.2", - "react-dom": "^17.0.2", + "@testing-library/react": "^13.4.0", + "@types/react": "18.0.26", + "@types/react-dom": "18.0.10", + "react": "^18.2.0", + "react-dom": "^18.2.0", "resize-observer-polyfill": "^1.5.1" }, "dependencies": { - "@types/react-dom": { - "version": "17.0.17", + "@testing-library/react": { + "version": "13.4.0", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-13.4.0.tgz", + "integrity": "sha512-sXOGON+WNTh3MLE9rve97ftaZukN3oNf2KjDy7YTx6hcTO2uuLHuCGynMDhFwGw/jYf4OJ2Qk0i4i79qMNNkyw==", "dev": true, "requires": { - "@types/react": "^17" + "@babel/runtime": "^7.12.5", + "@testing-library/dom": "^8.5.0", + "@types/react-dom": "^18.0.0" + } + }, + "@types/react": { + "version": "18.0.26", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.26.tgz", + "integrity": "sha512-hCR3PJQsAIXyxhTNSiDFY//LhnMZWpNNr5etoCqx/iUfGc5gXWtQR2Phl908jVR6uPXacojQWTg4qRpkxTuGug==", + "dev": true, + "requires": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "dev": true, + "requires": { + "loose-envify": "^1.1.0" + } + }, + "react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "dev": true, + "requires": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + } + }, + "scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "dev": true, + "requires": { + "loose-envify": "^1.1.0" } } } @@ -19195,14 +19278,6 @@ } } }, - "@testing-library/react": { - "version": "12.1.2", - "dev": true, - "requires": { - "@babel/runtime": "^7.12.5", - "@testing-library/dom": "^8.0.0" - } - }, "@tootallnate/once": { "version": "1.1.2", "dev": true @@ -19339,7 +19414,9 @@ } }, "@types/react-dom": { - "version": "18.0.9", + "version": "18.0.10", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.10.tgz", + "integrity": "sha512-E42GW/JA4Qv15wQdqJq8DL4JhNpB3prJgjgapN3qJT9K2zO5IIAQh4VXvCEDupoqAwnz0cY4RlXeC/ajX5SFHg==", "dev": true, "requires": { "@types/react": "*" diff --git a/packages/react-virtual/package.json b/packages/react-virtual/package.json index 333addddb..f4501c075 100644 --- a/packages/react-virtual/package.json +++ b/packages/react-virtual/package.json @@ -42,11 +42,11 @@ "src" ], "devDependencies": { - "@testing-library/react": "^12.1.2", - "@types/react": "17.0.45", - "@types/react-dom": "17.0.17", - "react": "^17.0.2", - "react-dom": "^17.0.2", + "@testing-library/react": "^13.4.0", + "@types/react": "18.0.26", + "@types/react-dom": "18.0.10", + "react": "^18.2.0", + "react-dom": "^18.2.0", "resize-observer-polyfill": "^1.5.1" }, "dependencies": { diff --git a/packages/virtual-core/src/index.ts b/packages/virtual-core/src/index.ts index 7bfbc79c2..c61d1cb80 100644 --- a/packages/virtual-core/src/index.ts +++ b/packages/virtual-core/src/index.ts @@ -519,7 +519,7 @@ export class Virtualizer< return rangeExtractor({ ...range, overscan, - count: count, + count, }) }, { @@ -626,13 +626,12 @@ export class Virtualizer< ) getOffsetForAlignment = (toOffset: number, align: ScrollAlignment) => { - const offset = this.scrollOffset const size = this.getSize() if (align === 'auto') { - if (toOffset <= offset) { + if (toOffset <= this.scrollOffset) { align = 'start' - } else if (toOffset >= offset + size) { + } else if (toOffset >= this.scrollOffset + size) { align = 'end' } else { align = 'start' @@ -640,13 +639,25 @@ export class Virtualizer< } if (align === 'start') { - return toOffset + toOffset = toOffset } else if (align === 'end') { - return toOffset - size + toOffset = toOffset - size } else if (align === 'center') { - return toOffset - size / 2 + toOffset = toOffset - size / 2 } - return toOffset + + const scrollSizeProp = this.options.horizontal + ? 'scrollWidth' + : 'scrollHeight' + const scrollSize = this.scrollElement + ? 'document' in this.scrollElement + ? this.scrollElement.document.documentElement[scrollSizeProp] + : this.scrollElement[scrollSizeProp] + : 0 + + const maxOffset = scrollSize - this.getSize() + + return Math.max(Math.min(maxOffset, toOffset), 0) } scrollToOffset = ( @@ -724,16 +735,7 @@ export class Virtualizer< ? measurement.end + this.options.scrollPaddingEnd : measurement.start - this.options.scrollPaddingStart - const sizeProp = this.options.horizontal ? 'scrollWidth' : 'scrollHeight' - const scrollSize = this.scrollElement - ? 'document' in this.scrollElement - ? this.scrollElement.document.documentElement[sizeProp] - : this.scrollElement[sizeProp] - : 0 - - const maxOffset = scrollSize - this.getSize() - - return Math.min(maxOffset, this.getOffsetForAlignment(toOffset, align)) + return this.getOffsetForAlignment(toOffset, align) } const toOffset = getOffsetForIndexAndAlignment(measurement)