Skip to content

Commit

Permalink
Merge branch 'release/v0.23.16'
Browse files Browse the repository at this point in the history
  • Loading branch information
holtwick committed Oct 5, 2024
2 parents 59df7c5 + 01a5cbd commit 15f7207
Show file tree
Hide file tree
Showing 5 changed files with 181 additions and 27 deletions.
97 changes: 96 additions & 1 deletion lib/basic/lazy-data.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import type { LoggerInterface } from 'zeed'
import { describe, expect, it } from 'vitest'
import { createArray } from 'zeed'
import { createArray, Logger, sleep } from 'zeed'
import { useLazyData } from './lazy-data'

const log: LoggerInterface = Logger('lazy-data.spec')

describe('useLazyData', () => {
async function onFetch(offset: number, length: number) {
log('onFetch', offset, length)
return createArray(length).map((_, i) => offset + i)
}

Expand Down Expand Up @@ -49,4 +53,95 @@ describe('useLazyData', () => {
expect(data.length).toBe(3)
expect(data.every(item => item == null)).toBe(true)
})

it('should set visible data correctly', async () => {
const { setSize, setVisible, data } = useLazyData({
onFetch,
chunkSize: 2,
margin: 2,
})
setSize(20)
const r = setVisible(3, 2)
expect(r).toMatchInlineSnapshot(`
{
"allChunksToLoad": [
0,
1,
2,
3,
],
"fromChunk": 0,
"fromIndex": 1,
"toChunk": 3,
"toIndex": 7,
}
`)

await sleep(100)

expect(data).toMatchInlineSnapshot(`
[
0,
1,
2,
3,
4,
5,
6,
7,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
]
`)

const r2 = setVisible(4, 2)
expect(r2).toMatchInlineSnapshot(`
{
"allChunksToLoad": [
4,
],
"fromChunk": 1,
"fromIndex": 2,
"toChunk": 4,
"toIndex": 8,
}
`)

await sleep(100)

expect(data).toMatchInlineSnapshot(`
[
0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
]
`)
})
})
66 changes: 54 additions & 12 deletions lib/basic/lazy-data.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { Reactive } from 'vue'
import type { LoggerInterface } from 'zeed'
import { reactive } from 'vue'
import { arrayEmptyInPlace, createArray, Logger } from 'zeed'
Expand All @@ -9,6 +10,7 @@ interface Config<T> {
chunkSize?: number
margin?: number
size?: number
data?: Reactive<T[]>
}

enum ChunkStatus {
Expand All @@ -22,7 +24,7 @@ export function useLazyData<T>(opt: Config<T>) {

let iteration = 0
let dataSize = 0
const data = reactive<(T | null)[]>([])
const data = opt.data ?? reactive<(T | null)[]>([])
const chunks: Record<number, ChunkStatus | undefined> = {}

function reload() {
Expand All @@ -40,19 +42,59 @@ export function useLazyData<T>(opt: Config<T>) {
if (size > 0)
setSize(size)

function setVisible(fromPos: number, toPos: number) {
log.assert(fromPos <= toPos, 'fromPos must be less than or equal to toPos')
const fromChunk = Math.floor(Math.max(0, fromPos - margin) / chunkSize)
const toChunk = Math.floor((toPos + margin) / chunkSize) * chunkSize
const iterationNow = iteration
onFetch(fromChunk * chunkSize, ((toChunk - fromChunk) * chunkSize) + chunkSize).then((result) => {
if (iterationNow !== iteration)
function setVisible(fromPos: number, length: number) {
const toPos = fromPos + length
// log.assert(fromPos <= toPos, 'fromPos must be less than or equal to toPos')
const fromIndex = Math.max(0, fromPos - margin)
const toIndex = Math.min(dataSize, toPos + margin)
const fromChunk = Math.floor(fromIndex / chunkSize)
const toChunk = Math.floor(toIndex / chunkSize)

const allChunksToLoad: number[] = []

let chunksToLoad: number[] = []

function flush() {
if (chunksToLoad.length === 0)
return
for (let i = fromChunk; i <= toChunk; i++)
chunks[i] = ChunkStatus.Loaded
const loading = [...chunksToLoad]
allChunksToLoad.push(...loading)
chunksToLoad = []

const fromIndex = loading[0] * chunkSize
const itemCount = (loading[loading.length - 1] - loading[0] + 1) * chunkSize

onFetch(fromIndex, itemCount).then((values) => {
log('Loaded', fromIndex, itemCount, values)
loading.forEach(i => chunks[i] = ChunkStatus.Loaded)
for (let i = 0; i < itemCount; i++) {
data[fromIndex + i] = values[i] as any
}
}).catch((e) => {
log.error('Failed to load chunks', loading, e)
})
}

for (let i = fromChunk; i <= toChunk; i++) {
const chunk = chunks[i]
if (chunk == null) {
chunks[i] = ChunkStatus.Loading
chunksToLoad.push(i)
}
else {
flush()
}
}

flush()

// arraySetArrayInPlace(data, result, fromChunk * chunkSize)
})
return {
fromIndex,
toIndex,
fromChunk,
toChunk,
allChunksToLoad,
}
}

return {
Expand Down
25 changes: 20 additions & 5 deletions lib/basic/oui-virtual-list.demo.vue
Original file line number Diff line number Diff line change
@@ -1,19 +1,34 @@
<script lang="ts" setup>
import { OuiVirtualList } from '@/lib'
import { reactive } from 'vue'
import { createArray, uuid } from 'zeed'
import { createArray } from 'zeed'
import { useLazyData } from './lazy-data'
const items = createArray(1000, i => ({ id: uuid() }))
const visibleItems = reactive(items)
// const items = createArray(1000, i => ({ id: uuid() }))
// const visibleItems = reactive(items)
async function onFetch(offset: number, length: number) {
return createArray(length).map((_, i) => {
const id = String(offset + i)
return { id }
})
}
const { data, setVisible } = useLazyData({
size: 1000,
chunkSize: 10,
margin: 5,
onFetch,
})
</script>

<template>
<h2>Virtual List</h2>
<div>
<OuiVirtualList
:data="visibleItems"
:data="data as any"
:height="20"
style="height: 400px"
@visible="setVisible"
>
<template #default="{ item, index }">
{{ index }}.
Expand Down
10 changes: 6 additions & 4 deletions lib/basic/oui-virtual-list.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// Which is under MIT License https://github.com/waningflow/vue3-virtual-list/blob/master/package.json#L11
import { onMounted, ref, toRefs, watch } from 'vue'
import { debounce, throttle } from 'zeed'
import { debounce } from 'zeed'
import { px } from './lib'
import './oui-virtual-list.styl'
Expand Down Expand Up @@ -136,9 +136,11 @@ onMounted(() => {
<div :style="`height: ${px(scrollHeight)}; padding-top: ${px(paddingTop)}`">
<template v-for="(item, index) in data.slice(indexFirst, indexLast)" :key="indexFirst + index">
<div :style="{ height: `${px(rowHeight)}` }">
<slot :item="item" :index="indexFirst + index">
Placeholder {{ index }}
</slot>
<template v-if="item">
<slot :item="item" :index="indexFirst + index">
Placeholder {{ index }}
</slot>
</template>
</div>
</template>
</div>
Expand Down
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "oui-kit",
"type": "module",
"version": "0.23.15",
"version": "0.23.16",
"author": {
"email": "[email protected]",
"name": "Dirk Holtwick",
Expand Down Expand Up @@ -62,7 +62,7 @@
"build": "vite build",
"build:demo": "BUILD_DEMO=1 vite build",
"check": "vue-tsc --noEmit",
"dev": "vite --host",
"dev": "vite --host --open",
"generate-pwa-assets": "npx pwa-assets-generator",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
Expand All @@ -75,15 +75,15 @@
"dependencies": {
"@floating-ui/vue": "^1.1.5",
"@vueuse/core": "^11.1.0",
"vue": "^3.5.10",
"vue": "^3.5.11",
"zeed": "^0.24.22"
},
"devDependencies": {
"@antfu/eslint-config": "^3.7",
"@antfu/ni": "^0.23.0",
"@shikijs/markdown-it": "^1.21.0",
"@vitejs/plugin-vue": "^5.1.4",
"@vitest/browser": "^2.1.1",
"@vitest/browser": "^2.1.2",
"eslint": "^9",
"stylus": "^0.63.0",
"tsup": "^8.3.0",
Expand All @@ -92,6 +92,6 @@
"vite": "^5.4.8",
"vite-plugin-dts": "^4.2.3",
"vite-plugin-qrcode": "^0.2.3",
"vitest": "^2.1.1"
"vitest": "^2.1.2"
}
}

0 comments on commit 15f7207

Please sign in to comment.