From 7145cec62fd4fc409d3f0e46f7aaaf0bea354abd Mon Sep 17 00:00:00 2001 From: kunish Date: Tue, 26 Sep 2023 22:22:24 +0800 Subject: [PATCH] feat(rule): implement virtual scroll on rules and rule providers, fixes #285 --- package.json | 3 +- pnpm-lock.yaml | 25 +++++--- src/pages/Rules.tsx | 144 ++++++++++++++++++++++++++++++-------------- 3 files changed, 117 insertions(+), 55 deletions(-) diff --git a/package.json b/package.json index d546079..eb02a76 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,8 @@ "@tabler/icons-solidjs": "^2.35.0", "@tanstack/match-sorter-utils": "^8.8.4", "@tanstack/solid-table": "^8.10.3", - "@tanstack/solid-virtual": "3.0.0-beta.6", + "@tanstack/solid-virtual": "3.0.0-beta.60", + "@tanstack/virtual-core": "3.0.0-beta.60", "@thisbeyond/solid-dnd": "^0.7.4", "@types/byte-size": "^8.1.0", "@types/lodash": "^4.14.199", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2425f96..e01e6a3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -60,8 +60,11 @@ dependencies: specifier: ^8.10.3 version: 8.10.3(solid-js@1.7.12) '@tanstack/solid-virtual': - specifier: 3.0.0-beta.6 - version: 3.0.0-beta.6 + specifier: 3.0.0-beta.60 + version: 3.0.0-beta.60(solid-js@1.7.12) + '@tanstack/virtual-core': + specifier: 3.0.0-beta.60 + version: 3.0.0-beta.60 '@thisbeyond/solid-dnd': specifier: ^0.7.4 version: 0.7.4(solid-js@1.7.12) @@ -1968,10 +1971,6 @@ packages: tslib: 2.6.2 dev: false - /@reach/observe-rect@1.2.0: - resolution: {integrity: sha512-Ba7HmkFgfQxZqqaeIWWkNK0rEhpxVQHIoVyW1YDSkGsGIXzcaW4deC8B0pZrNSSyLTdIk7y+5olKt5+g0GmFIQ==} - dev: false - /@rollup/plugin-babel@5.3.1(@babel/core@7.22.20)(rollup@2.79.1): resolution: {integrity: sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==} engines: {node: '>= 10.0.0'} @@ -2194,11 +2193,13 @@ packages: solid-js: 1.7.12 dev: false - /@tanstack/solid-virtual@3.0.0-beta.6: - resolution: {integrity: sha512-/HjeHZb4UZxxFSAkICUEWOozGwHQpKlvtnUoS5uSMSuLOz0XM5vFq6zR6ENwAczKWDtkh8ntddk+zXAhyXOlEw==} - engines: {node: '>=12'} + /@tanstack/solid-virtual@3.0.0-beta.60(solid-js@1.7.12): + resolution: {integrity: sha512-SN007vDq1AeRq5w2rK0E47CeI8rv+oPZ5IjtOgLynt1MKNUsSsJ7d+igK2jUPQ24QrZf5NLrN4FRQRdxvakvIg==} + peerDependencies: + solid-js: ^1.3.0 dependencies: - '@reach/observe-rect': 1.2.0 + '@tanstack/virtual-core': 3.0.0-beta.60 + solid-js: 1.7.12 dev: false /@tanstack/table-core@8.10.3: @@ -2206,6 +2207,10 @@ packages: engines: {node: '>=12'} dev: false + /@tanstack/virtual-core@3.0.0-beta.60: + resolution: {integrity: sha512-QlCdhsV1+JIf0c0U6ge6SQmpwsyAT0oQaOSZk50AtEeAyQl9tQrd6qCHAslxQpgphrfe945abvKG8uYvw3hIGA==} + dev: false + /@thisbeyond/solid-dnd@0.7.4(solid-js@1.7.12): resolution: {integrity: sha512-jgV9EtR3gAtVsILG8p1OAGrhHIgnK4W04YxpyLgJRCDKEFYQWuDrMdUe8F5Kc6pcVXlC4IMXr4cB8fS2Ut3/Ow==} peerDependencies: diff --git a/src/pages/Rules.tsx b/src/pages/Rules.tsx index ffc64a7..0cf50e2 100644 --- a/src/pages/Rules.tsx +++ b/src/pages/Rules.tsx @@ -1,4 +1,5 @@ import { IconReload } from '@tabler/icons-solidjs' +import { createVirtualizer } from '@tanstack/solid-virtual' import { For, Show, createSignal, onMount } from 'solid-js' import { twMerge } from 'tailwind-merge' import { Button } from '~/components' @@ -56,6 +57,30 @@ export default () => { }, ] + let parentRef: HTMLDivElement | undefined + + const ruleVirtualizer = createVirtualizer({ + get count() { + return rules().length + }, + getScrollElement: () => parentRef!, + estimateSize: () => 74, + overscan: 5, + }) + + const ruleVirtualizerItems = ruleVirtualizer.getVirtualItems() + + const ruleProviderVirtualizer = createVirtualizer({ + get count() { + return ruleProviders().length + }, + getScrollElement: () => parentRef!, + estimateSize: () => 74, + overscan: 5, + }) + + const ruleProviderVirtualizerItems = ruleProviderVirtualizer.getVirtualItems() + return (
@@ -92,60 +117,91 @@ export default () => {
-
+
(parentRef = ref)} class="flex-1 overflow-y-auto"> -
- - {(rule) => ( -
-
- {rule.payload} - -
{rule.size}
-
-
-
- {rule.type} :: {rule.proxy} +
+ {ruleVirtualizerItems.map((virtualizerItem) => { + const rule = rules()[virtualizerItem.index] + + return ( +
+ onMount(() => ruleVirtualizer.measureElement(el)) + } + data-index={virtualizerItem.index} + class="absolute inset-x-0 top-0 pb-2 last:pb-0" + style={{ + transform: `translateY(${virtualizerItem.start}px)`, + }} + > +
+
+ {rule.payload} + + +
{rule.size}
+
+
+ +
+ {rule.type} :: {rule.proxy} +
- )} - + ) + })}
-
- - {(ruleProvider) => ( -
-
- {ruleProvider.name} -
{ruleProvider.ruleCount}
-
+
+ {ruleProviderVirtualizerItems.map((virtualizerItem) => { + const ruleProvider = ruleProviders()[virtualizerItem.index] -
- {ruleProvider.vehicleType} / {ruleProvider.behavior} / - {t('updated')} {formatTimeFromNow(ruleProvider.updatedAt)} -
+ return ( +
+ onMount(() => ruleProviderVirtualizer.measureElement(el)) + } + data-index={virtualizerItem.index} + class="absolute inset-x-0 top-0 pb-2 last:pb-0" + style={{ + transform: `translateY(${virtualizerItem.start}px)`, + }} + > +
+
+ {ruleProvider.name} +
{ruleProvider.ruleCount}
+
-
- )} - + ) + })}