@legendapp/list 3.0.0-beta.20 → 3.0.0-beta.21

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.
@@ -0,0 +1,271 @@
1
+ import * as React from 'react';
2
+ import { Platform } from 'react-native';
3
+ import { typedMemo, typedForwardRef, LegendList } from '@legendapp/list';
4
+
5
+ // src/section-list/SectionList.tsx
6
+
7
+ // src/section-list/flattenSections.ts
8
+ var defaultKeyExtractor = (item, index) => {
9
+ var _a;
10
+ const key = (_a = item == null ? void 0 : item.key) != null ? _a : item == null ? void 0 : item.id;
11
+ return key != null ? String(key) : String(index);
12
+ };
13
+ var getSectionKey = (section, sectionIndex) => {
14
+ var _a;
15
+ return (_a = section.key) != null ? _a : `section-${sectionIndex}`;
16
+ };
17
+ function buildSectionListData({
18
+ sections,
19
+ renderSectionHeader,
20
+ renderSectionFooter,
21
+ ItemSeparatorComponent,
22
+ SectionSeparatorComponent,
23
+ stickySectionHeadersEnabled,
24
+ keyExtractor = defaultKeyExtractor
25
+ }) {
26
+ var _a, _b;
27
+ const data = [];
28
+ const sectionMeta = [];
29
+ const stickyHeaderIndices = [];
30
+ let absoluteItemIndex = 0;
31
+ for (let sectionIndex = 0; sectionIndex < sections.length; sectionIndex++) {
32
+ const section = sections[sectionIndex];
33
+ const items = (_a = section.data) != null ? _a : [];
34
+ const meta = { items: [] };
35
+ const sectionKey = getSectionKey(section, sectionIndex);
36
+ const hasHeader = typeof renderSectionHeader === "function";
37
+ const hasFooter = typeof renderSectionFooter === "function";
38
+ const hasItemSeparator = Boolean(ItemSeparatorComponent || section.ItemSeparatorComponent);
39
+ const hasSectionSeparator = Boolean(SectionSeparatorComponent);
40
+ if (hasHeader) {
41
+ const headerIndex = data.length;
42
+ data.push({
43
+ key: `${sectionKey}:header`,
44
+ kind: "header",
45
+ section,
46
+ sectionIndex
47
+ });
48
+ meta.header = headerIndex;
49
+ if (stickySectionHeadersEnabled) {
50
+ stickyHeaderIndices.push(headerIndex);
51
+ }
52
+ }
53
+ for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
54
+ const item = items[itemIndex];
55
+ const itemKeyExtractor = (_b = section.keyExtractor) != null ? _b : keyExtractor;
56
+ const itemKey = itemKeyExtractor(item, itemIndex);
57
+ data.push({
58
+ absoluteItemIndex: absoluteItemIndex++,
59
+ item,
60
+ itemIndex,
61
+ key: `${sectionKey}:item:${itemKey}`,
62
+ kind: "item",
63
+ section,
64
+ sectionIndex
65
+ });
66
+ meta.items.push(data.length - 1);
67
+ if (hasItemSeparator && itemIndex < items.length - 1) {
68
+ data.push({
69
+ key: `${sectionKey}:separator:${itemIndex}`,
70
+ kind: "item-separator",
71
+ leadingItem: item,
72
+ leadingItemIndex: itemIndex,
73
+ section,
74
+ sectionIndex,
75
+ trailingItem: items[itemIndex + 1]
76
+ });
77
+ }
78
+ }
79
+ if (hasFooter) {
80
+ data.push({
81
+ key: `${sectionKey}:footer`,
82
+ kind: "footer",
83
+ section,
84
+ sectionIndex
85
+ });
86
+ meta.footer = data.length - 1;
87
+ }
88
+ const isLastSection = sectionIndex === sections.length - 1;
89
+ if (hasSectionSeparator && !isLastSection) {
90
+ data.push({
91
+ key: `${sectionKey}:section-separator`,
92
+ kind: "section-separator",
93
+ leadingSection: section,
94
+ leadingSectionIndex: sectionIndex,
95
+ trailingSection: sections[sectionIndex + 1]
96
+ });
97
+ }
98
+ sectionMeta.push(meta);
99
+ }
100
+ return { data, sectionMeta, stickyHeaderIndices };
101
+ }
102
+
103
+ // src/section-list/SectionList.tsx
104
+ var defaultSeparators = {
105
+ highlight: () => {
106
+ },
107
+ unhighlight: () => {
108
+ },
109
+ updateProps: () => {
110
+ }
111
+ };
112
+ function resolveSeparatorComponent(component, props) {
113
+ if (!component) return null;
114
+ if (React.isValidElement(component)) {
115
+ return component;
116
+ }
117
+ const Component = component;
118
+ return /* @__PURE__ */ React.createElement(Component, { ...props });
119
+ }
120
+ var SectionList = typedMemo(
121
+ typedForwardRef(function SectionListInner(props, ref) {
122
+ const {
123
+ sections,
124
+ renderItem: renderItemProp,
125
+ renderSectionHeader,
126
+ renderSectionFooter,
127
+ ItemSeparatorComponent,
128
+ SectionSeparatorComponent,
129
+ stickySectionHeadersEnabled = Platform.OS === "ios",
130
+ keyExtractor,
131
+ extraData,
132
+ onViewableItemsChanged,
133
+ horizontal,
134
+ ...restProps
135
+ } = props;
136
+ const legendListRef = React.useRef(null);
137
+ const flattened = React.useMemo(
138
+ () => buildSectionListData({
139
+ ItemSeparatorComponent,
140
+ keyExtractor,
141
+ renderSectionFooter,
142
+ renderSectionHeader,
143
+ SectionSeparatorComponent,
144
+ sections,
145
+ stickySectionHeadersEnabled: !horizontal && stickySectionHeadersEnabled
146
+ }),
147
+ [
148
+ sections,
149
+ extraData,
150
+ renderSectionHeader,
151
+ renderSectionFooter,
152
+ ItemSeparatorComponent,
153
+ SectionSeparatorComponent,
154
+ stickySectionHeadersEnabled,
155
+ keyExtractor,
156
+ horizontal
157
+ ]
158
+ );
159
+ const { data, sectionMeta, stickyHeaderIndices } = flattened;
160
+ const handleViewableItemsChanged = React.useMemo(() => {
161
+ if (!onViewableItemsChanged) return void 0;
162
+ return ({
163
+ viewableItems,
164
+ changed
165
+ }) => {
166
+ const mapToken = (token) => {
167
+ if (token.item.kind !== "item") return null;
168
+ return {
169
+ index: token.item.itemIndex,
170
+ isViewable: token.isViewable,
171
+ item: token.item.item,
172
+ key: token.key,
173
+ section: token.item.section
174
+ };
175
+ };
176
+ const mappedViewable = viewableItems.map(mapToken).filter(Boolean);
177
+ const mappedChanged = changed.map(mapToken).filter(Boolean);
178
+ onViewableItemsChanged({ changed: mappedChanged, viewableItems: mappedViewable });
179
+ };
180
+ }, [onViewableItemsChanged]);
181
+ const renderItem = React.useCallback(
182
+ ({ item }) => {
183
+ var _a, _b;
184
+ switch (item.kind) {
185
+ case "header":
186
+ return renderSectionHeader ? renderSectionHeader({ section: item.section }) : null;
187
+ case "footer":
188
+ return renderSectionFooter ? renderSectionFooter({ section: item.section }) : null;
189
+ case "item": {
190
+ const render = (_a = item.section.renderItem) != null ? _a : renderItemProp;
191
+ if (!render) return null;
192
+ return render({
193
+ index: item.itemIndex,
194
+ item: item.item,
195
+ section: item.section,
196
+ separators: defaultSeparators
197
+ });
198
+ }
199
+ case "item-separator": {
200
+ const SeparatorComponent = (_b = item.section.ItemSeparatorComponent) != null ? _b : ItemSeparatorComponent;
201
+ return resolveSeparatorComponent(SeparatorComponent, {
202
+ leadingItem: item.leadingItem,
203
+ leadingSection: item.section,
204
+ section: item.section,
205
+ trailingItem: item.trailingItem,
206
+ trailingSection: item.section
207
+ });
208
+ }
209
+ case "section-separator":
210
+ return resolveSeparatorComponent(SectionSeparatorComponent, {
211
+ leadingItem: void 0,
212
+ leadingSection: item.leadingSection,
213
+ section: item.leadingSection,
214
+ trailingItem: void 0,
215
+ trailingSection: item.trailingSection
216
+ });
217
+ default:
218
+ return null;
219
+ }
220
+ },
221
+ [
222
+ ItemSeparatorComponent,
223
+ SectionSeparatorComponent,
224
+ renderItemProp,
225
+ renderSectionFooter,
226
+ renderSectionHeader
227
+ ]
228
+ );
229
+ const scrollToLocation = React.useCallback(
230
+ ({ sectionIndex, itemIndex, viewOffset, viewPosition, animated }) => {
231
+ var _a, _b, _c;
232
+ const meta = sectionMeta[sectionIndex];
233
+ if (!meta) return;
234
+ const target = itemIndex === -1 ? (_b = (_a = meta.header) != null ? _a : meta.items[0]) != null ? _b : meta.footer : meta.items[itemIndex];
235
+ if (target === void 0) return;
236
+ (_c = legendListRef.current) == null ? void 0 : _c.scrollToIndex({
237
+ animated,
238
+ index: target,
239
+ viewOffset,
240
+ viewPosition
241
+ });
242
+ },
243
+ [sectionMeta]
244
+ );
245
+ React.useImperativeHandle(
246
+ ref,
247
+ () => ({
248
+ ...legendListRef.current,
249
+ scrollToLocation
250
+ }),
251
+ [scrollToLocation]
252
+ );
253
+ return /* @__PURE__ */ React.createElement(
254
+ LegendList,
255
+ {
256
+ ...restProps,
257
+ columnWrapperStyle: void 0,
258
+ data,
259
+ getItemType: (item) => item.kind,
260
+ keyExtractor: (item) => item.key,
261
+ numColumns: 1,
262
+ onViewableItemsChanged: handleViewableItemsChanged,
263
+ ref: legendListRef,
264
+ renderItem,
265
+ stickyHeaderIndices: !horizontal ? stickyHeaderIndices : void 0
266
+ }
267
+ );
268
+ })
269
+ );
270
+
271
+ export { SectionList };