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

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