-
Notifications
You must be signed in to change notification settings - Fork 32
/
index.ts
113 lines (96 loc) · 2.77 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
export type SectionListDataProp = Array<{
title: string
data: any[]
}>
interface SectionHeader {
type: 'SECTION_HEADER'
}
interface Row {
type: 'ROW'
index: number
}
interface SectionFooter {
type: 'SECTION_FOOTER'
}
type ListElement = SectionHeader | Row | SectionFooter
export interface Parameters {
getItemHeight: (
rowData: any,
sectionIndex: number,
rowIndex: number,
) => number
getSeparatorHeight?: (sectionIndex: number, rowIndex: number) => number
getSectionHeaderHeight?: (sectionIndex: number) => number
getSectionFooterHeight?: (sectionIndex: number) => number
listHeaderHeight?: number | (() => number)
}
export default ({
getItemHeight,
getSeparatorHeight = () => 0,
getSectionHeaderHeight = () => 0,
getSectionFooterHeight = () => 0,
listHeaderHeight = 0,
}: Parameters) => (data: SectionListDataProp, index: number) => {
let i = 0
let sectionIndex = 0
let elementPointer: ListElement = { type: 'SECTION_HEADER' }
let offset =
typeof listHeaderHeight === 'function'
? listHeaderHeight()
: listHeaderHeight
while (i < index) {
switch (elementPointer.type) {
case 'SECTION_HEADER': {
const sectionData = data[sectionIndex].data
offset += getSectionHeaderHeight(sectionIndex)
// If this section is empty, we go right to the footer...
if (sectionData.length === 0) {
elementPointer = { type: 'SECTION_FOOTER' }
// ...otherwise we make elementPointer point at the first row in this section
} else {
elementPointer = { type: 'ROW', index: 0 }
}
break
}
case 'ROW': {
const sectionData = data[sectionIndex].data
const rowIndex = elementPointer.index
offset += getItemHeight(sectionData[rowIndex], sectionIndex, rowIndex)
elementPointer.index += 1
if (rowIndex === sectionData.length - 1) {
elementPointer = { type: 'SECTION_FOOTER' }
} else {
offset += getSeparatorHeight(sectionIndex, rowIndex)
}
break
}
case 'SECTION_FOOTER': {
offset += getSectionFooterHeight(sectionIndex)
sectionIndex += 1
elementPointer = { type: 'SECTION_HEADER' }
break
}
}
i += 1
}
let length
switch (elementPointer.type) {
case 'SECTION_HEADER':
length = getSectionHeaderHeight(sectionIndex)
break
case 'ROW':
const rowIndex = elementPointer.index
length = getItemHeight(
data[sectionIndex].data[rowIndex],
sectionIndex,
rowIndex,
)
break
case 'SECTION_FOOTER':
length = getSectionFooterHeight(sectionIndex)
break
default:
throw new Error('Unknown elementPointer.type')
}
return { length, offset, index }
}