nexa-ui-kit 0.6.4 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/NCard.js +5 -1
- package/dist/components/NDataTable.js +50 -38
- package/dist/components/NDataTable.nexa +19 -2
- package/dist/components/NImage.js +108 -0
- package/dist/components/NImage.nexa +117 -0
- package/dist/components/NModal.js +3 -1
- package/dist/components/NScrollView.js +128 -0
- package/dist/components/NScrollView.nexa +136 -0
- package/dist/components/NTabs.js +1 -1
- package/dist/components/NVirtualList.js +91 -0
- package/dist/components/NVirtualList.nexa +94 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/package.json +4 -4
- package/src/components/NDataTable.nexa +19 -2
- package/src/components/NImage.nexa +117 -0
- package/src/components/NScrollView.nexa +136 -0
- package/src/components/NVirtualList.nexa +94 -0
- package/src/index.ts +3 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { signal, computed, onMounted, onUnmounted, effect } from 'nexa-framework'
|
|
3
|
+
|
|
4
|
+
const props = defineProps({
|
|
5
|
+
items: { type: Array, default: () => [] },
|
|
6
|
+
itemHeight: { type: Number, default: 48 },
|
|
7
|
+
overscan: { type: Number, default: 3 },
|
|
8
|
+
renderItem: { type: Function, required: true },
|
|
9
|
+
keyFn: { type: Function, default: null }
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
const containerRef = signal(null)
|
|
13
|
+
const scrollTop = signal(0)
|
|
14
|
+
const containerHeight = signal(400)
|
|
15
|
+
|
|
16
|
+
const totalHeight = computed(() => props.items.length * props.itemHeight)
|
|
17
|
+
|
|
18
|
+
const visibleRange = computed(() => {
|
|
19
|
+
const start = Math.max(0, Math.floor(scrollTop.value / props.itemHeight) - props.overscan)
|
|
20
|
+
const visibleCount = Math.ceil(containerHeight.value / props.itemHeight) + props.overscan * 2
|
|
21
|
+
const end = Math.min(props.items.length, start + visibleCount)
|
|
22
|
+
return { start, end }
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
const visibleItems = computed(() => {
|
|
26
|
+
const { start, end } = visibleRange.value
|
|
27
|
+
return props.items.slice(start, end).map((item, i) => ({
|
|
28
|
+
item,
|
|
29
|
+
index: start + i,
|
|
30
|
+
top: (start + i) * props.itemHeight
|
|
31
|
+
}))
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
let resizeObserver = null
|
|
35
|
+
|
|
36
|
+
onMounted(() => {
|
|
37
|
+
const el = containerRef.value
|
|
38
|
+
if (!el) return
|
|
39
|
+
containerHeight.value = el.clientHeight
|
|
40
|
+
|
|
41
|
+
resizeObserver = new ResizeObserver(entries => {
|
|
42
|
+
containerHeight.value = entries[0].contentRect.height
|
|
43
|
+
})
|
|
44
|
+
resizeObserver.observe(el)
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
onUnmounted(() => {
|
|
48
|
+
resizeObserver?.disconnect()
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
const onScroll = (e) => {
|
|
52
|
+
scrollTop.value = e.target.scrollTop
|
|
53
|
+
}
|
|
54
|
+
</script>
|
|
55
|
+
|
|
56
|
+
<template>
|
|
57
|
+
<div
|
|
58
|
+
class="n-virtual-list"
|
|
59
|
+
@scroll="onScroll"
|
|
60
|
+
:ref="el => containerRef.value = el"
|
|
61
|
+
>
|
|
62
|
+
<div
|
|
63
|
+
class="n-virtual-list-spacer"
|
|
64
|
+
:style="{ height: totalHeight.value + 'px', position: 'relative' }"
|
|
65
|
+
>
|
|
66
|
+
<div
|
|
67
|
+
v-for="row in visibleItems.value"
|
|
68
|
+
:key="keyFn ? keyFn(row.item, row.index) : row.index"
|
|
69
|
+
class="n-virtual-list-row"
|
|
70
|
+
:style="{ position: 'absolute', top: row.top + 'px', width: '100%', height: itemHeight + 'px' }"
|
|
71
|
+
>
|
|
72
|
+
{{ renderItem(row.item, row.index) }}
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
</template>
|
|
77
|
+
|
|
78
|
+
<style scoped>
|
|
79
|
+
.n-virtual-list {
|
|
80
|
+
overflow-y: auto;
|
|
81
|
+
width: 100%;
|
|
82
|
+
height: 100%;
|
|
83
|
+
-webkit-overflow-scrolling: touch;
|
|
84
|
+
overscroll-behavior: contain;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.n-virtual-list-spacer {
|
|
88
|
+
position: relative;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.n-virtual-list-row {
|
|
92
|
+
box-sizing: border-box;
|
|
93
|
+
}
|
|
94
|
+
</style>
|
package/src/index.ts
CHANGED
|
@@ -30,6 +30,9 @@ export { default as NInputNumber } from './components/NInputNumber.nexa'
|
|
|
30
30
|
export { default as NMultiSelect } from './components/NMultiSelect.nexa'
|
|
31
31
|
export { default as NDataTable } from './components/NDataTable.nexa'
|
|
32
32
|
export { default as NPaginator } from './components/NPaginator.nexa'
|
|
33
|
+
export { default as NVirtualList } from './components/NVirtualList.nexa'
|
|
34
|
+
export { default as NScrollView } from './components/NScrollView.nexa'
|
|
35
|
+
export { default as NImage } from './components/NImage.nexa'
|
|
33
36
|
export * from './services/ToastService.js'
|
|
34
37
|
export * from './services/FormValidation.js'
|
|
35
38
|
export { installTheme } from './styles/theme.js'
|