@swan-io/lake 8.17.0 → 8.18.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swan-io/lake",
3
- "version": "8.17.0",
3
+ "version": "8.18.0",
4
4
  "engines": {
5
5
  "node": ">=20.9.0",
6
6
  "yarn": "^1.22.0"
@@ -10,6 +10,7 @@ export type ScrollViewRef = {
10
10
  export type ScrollViewProps = ViewProps & {
11
11
  contentContainerStyle?: StyleProp<ViewStyle>;
12
12
  horizontal?: boolean;
13
+ both?: boolean;
13
14
  onScroll?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
14
15
  scrollEventThrottle?: number;
15
16
  showsScrollIndicators?: boolean;
@@ -17,6 +18,7 @@ export type ScrollViewProps = ViewProps & {
17
18
  export declare const ScrollView: import("react").ForwardRefExoticComponent<ViewProps & {
18
19
  contentContainerStyle?: StyleProp<ViewStyle>;
19
20
  horizontal?: boolean;
21
+ both?: boolean;
20
22
  onScroll?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
21
23
  scrollEventThrottle?: number;
22
24
  showsScrollIndicators?: boolean;
@@ -16,6 +16,11 @@ const styles = StyleSheet.create({
16
16
  overflowX: "auto",
17
17
  overflowY: "hidden",
18
18
  },
19
+ both: {
20
+ flexDirection: "column",
21
+ overflowX: "auto",
22
+ overflowY: "auto",
23
+ },
19
24
  contentHorizontal: {
20
25
  flexDirection: "row",
21
26
  },
@@ -55,7 +60,7 @@ const normalizeScrollEvent = (event) => {
55
60
  };
56
61
  };
57
62
  const shouldEmitScrollEvent = (state, eventThrottle) => !state.scrolling || (eventThrottle > 0 && Date.now() - state.lastTick >= eventThrottle);
58
- export const ScrollView = forwardRef(({ children, contentContainerStyle, horizontal = false, onScroll, scrollEventThrottle = 16, showsScrollIndicators = true, style, ...viewProps }, forwardedRef) => {
63
+ export const ScrollView = forwardRef(({ children, contentContainerStyle, horizontal = false, both = false, onScroll, scrollEventThrottle = 16, showsScrollIndicators = true, style, ...viewProps }, forwardedRef) => {
59
64
  const innerRef = useRef(null);
60
65
  const stateRef = useRef({ lastTick: 0, scrolling: false });
61
66
  const timeoutRef = useRef(null);
@@ -95,6 +100,7 @@ export const ScrollView = forwardRef(({ children, contentContainerStyle, horizon
95
100
  styles.base,
96
101
  style,
97
102
  horizontal && styles.horizontal,
103
+ both && styles.both,
98
104
  !showsScrollIndicators && styles.hideScrollbars,
99
105
  ], children: _jsx(View, { style: [horizontal && styles.contentHorizontal, contentContainerStyle], children: children }) }));
100
106
  });
@@ -0,0 +1,55 @@
1
+ import { ReactElement, ReactNode } from "react";
2
+ export type ColumnTitleConfig<ExtraInfo> = {
3
+ title: string;
4
+ extraInfo: ExtraInfo;
5
+ id: string;
6
+ };
7
+ export type ColumnCellConfig<T, ExtraInfo> = {
8
+ columnId: string;
9
+ item: T;
10
+ index: number;
11
+ extraInfo: ExtraInfo;
12
+ isHovered: boolean;
13
+ };
14
+ export type ColumnConfig<T, ExtraInfo> = {
15
+ id: string;
16
+ width: number;
17
+ title: string;
18
+ renderTitle: (props: ColumnTitleConfig<ExtraInfo>) => ReactNode;
19
+ renderCell: (props: ColumnCellConfig<T, ExtraInfo>) => ReactNode;
20
+ };
21
+ export type LinkConfig<T, ExtraInfo> = {
22
+ item: T;
23
+ index: number;
24
+ extraInfo: ExtraInfo;
25
+ };
26
+ export type VirtualizedListProps<T, ExtraInfo> = {
27
+ variant: "default" | "accented";
28
+ data: T[];
29
+ keyExtractor: (item: T, index: number) => string;
30
+ highlightedRowId?: string;
31
+ headerHeight: number;
32
+ rowHeight: number;
33
+ extraInfo: ExtraInfo;
34
+ stickedToStartColumns?: ColumnConfig<T, ExtraInfo>[];
35
+ columns: ColumnConfig<T, ExtraInfo>[];
36
+ stickedToEndColumns?: ColumnConfig<T, ExtraInfo>[];
37
+ renderThreshold?: number;
38
+ onEndReached?: () => void;
39
+ onEndReachedThreshold?: number;
40
+ getRowLink?: (config: LinkConfig<T, ExtraInfo>) => ReactElement | undefined;
41
+ renderEmptyList?: () => ReactNode;
42
+ loading?: {
43
+ isLoading: boolean;
44
+ count: number;
45
+ };
46
+ };
47
+ export declare const VirtualizedList: <T, ExtraInfo>({ variant, data, stickedToStartColumns, columns, stickedToEndColumns, headerHeight, rowHeight, renderThreshold, onEndReached, onEndReachedThreshold, loading, extraInfo, keyExtractor, }: VirtualizedListProps<T, ExtraInfo>) => import("react/jsx-runtime").JSX.Element;
48
+ type VirtualizedListPlaceholderProps = {
49
+ count: number;
50
+ rowHeight: number;
51
+ groupHeaderHeight?: number;
52
+ headerHeight?: number;
53
+ };
54
+ export declare const VirtualizedListPlaceholder: ({ count, rowHeight, groupHeaderHeight, headerHeight, }: VirtualizedListPlaceholderProps) => import("react/jsx-runtime").JSX.Element;
55
+ export {};
@@ -0,0 +1,426 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Option } from "@swan-io/boxed";
3
+ import { cloneElement, memo, useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, } from "react";
4
+ import { StyleSheet, View } from "react-native";
5
+ import { commonStyles } from "../constants/commonStyles";
6
+ import { backgroundColor as backgroundColorVariants, colors, spacings } from "../constants/design";
7
+ import { useHover } from "../hooks/useHover";
8
+ import { ScrollView } from "./ScrollView";
9
+ import { Space } from "./Space";
10
+ const styles = StyleSheet.create({
11
+ container: {
12
+ ...commonStyles.fill,
13
+ alignSelf: "stretch",
14
+ },
15
+ headerRow: {
16
+ position: "sticky",
17
+ top: 0,
18
+ flexDirection: "row",
19
+ alignItems: "stretch",
20
+ zIndex: 2,
21
+ },
22
+ cellsContainer: {
23
+ flexDirection: "row",
24
+ transform: "translateZ(0)",
25
+ },
26
+ stickedToStartColumnGroup: {
27
+ position: "sticky",
28
+ left: 0,
29
+ zIndex: 1,
30
+ },
31
+ stickedToEndColumnGroup: {
32
+ position: "sticky",
33
+ right: 0,
34
+ zIndex: 1,
35
+ },
36
+ rowsContainer: {
37
+ position: "relative",
38
+ },
39
+ row: {
40
+ position: "absolute",
41
+ left: 0,
42
+ right: 0,
43
+ flexDirection: "row",
44
+ alignItems: "stretch",
45
+ },
46
+ headerCell: {
47
+ display: "flex",
48
+ flexDirection: "row",
49
+ flexGrow: 1,
50
+ alignItems: "center",
51
+ },
52
+ cell: {
53
+ display: "flex",
54
+ flexDirection: "row",
55
+ flexGrow: 1,
56
+ alignItems: "stretch",
57
+ boxShadow: `inset 0 -1px ${colors.gray[100]}`,
58
+ },
59
+ shadowsLayerContainer: {
60
+ position: "absolute",
61
+ top: 0,
62
+ left: 0,
63
+ right: 0,
64
+ bottom: 0,
65
+ pointerEvents: "none",
66
+ zIndex: 4,
67
+ },
68
+ shadowsLayer: {
69
+ position: "sticky",
70
+ top: 12,
71
+ flexDirection: "row",
72
+ alignItems: "stretch",
73
+ },
74
+ startColumnsShadow: {
75
+ position: "sticky",
76
+ left: 0,
77
+ top: 0,
78
+ boxShadow: "15px 0 10px -12px rgba(0, 0, 0, 0.1)",
79
+ transition: "100ms ease-in-out opacity",
80
+ },
81
+ endColumnsShadow: {
82
+ position: "sticky",
83
+ right: 0,
84
+ top: 0,
85
+ boxShadow: "-15px 0 10px -12px rgba(0, 0, 0, 0.1)",
86
+ transition: "100ms ease-in-out opacity",
87
+ },
88
+ scrollTracker: {
89
+ pointerEvents: "none",
90
+ position: "absolute",
91
+ left: 0,
92
+ bottom: 0,
93
+ right: 0,
94
+ },
95
+ placeholderRowContainer: {
96
+ position: "absolute",
97
+ alignItems: "flex-start",
98
+ top: 0,
99
+ left: 0,
100
+ right: 0,
101
+ animationKeyframes: {
102
+ "50%": {
103
+ opacity: 0.6,
104
+ },
105
+ },
106
+ animationDuration: "2000ms",
107
+ animationTimingFunction: "linear",
108
+ animationIterationCount: "infinite",
109
+ boxShadow: `inset 0 -1px ${colors.gray[100]}`,
110
+ },
111
+ placeholderRowContents: {
112
+ position: "sticky",
113
+ width: "50%",
114
+ left: 0,
115
+ flexDirection: "row",
116
+ alignItems: "center",
117
+ justifyContent: "flex-start",
118
+ flexGrow: 1,
119
+ paddingHorizontal: spacings[20],
120
+ },
121
+ loadingPlaceholder: {
122
+ position: "absolute",
123
+ left: 0,
124
+ right: 0,
125
+ },
126
+ placeholderRow: {
127
+ height: 14,
128
+ width: "30%",
129
+ backgroundColor: colors.gray[100],
130
+ },
131
+ placeholderRowEnd: {
132
+ paddingHorizontal: spacings[20],
133
+ position: "sticky",
134
+ right: 0,
135
+ flexGrow: 1,
136
+ flexDirection: "row",
137
+ alignItems: "center",
138
+ justifyContent: "flex-end",
139
+ },
140
+ smallPlaceholderRow: {
141
+ width: "10%",
142
+ },
143
+ });
144
+ export const VirtualizedList = ({ variant, data, stickedToStartColumns, columns, stickedToEndColumns, headerHeight, rowHeight, renderThreshold = 1000, onEndReached, onEndReachedThreshold = 200, loading, extraInfo, keyExtractor, }) => {
145
+ // Used for unique IDs generation (usefull for header IDs and cells aria-describedBy pointing to them)
146
+ const viewId = useId();
147
+ const scrollViewRef = useRef(null);
148
+ const scrollTrackerRef = useRef(null);
149
+ // Theoretical height of all actual data if rendered
150
+ const fullDataHeight = rowHeight * data.length;
151
+ const loadingDataPlaceholderHeight = Option.fromNullable(loading)
152
+ .flatMap(({ isLoading, count }) => (isLoading ? Option.Some(rowHeight * count) : Option.None()))
153
+ .getOr(0);
154
+ const containerContainerHeight = headerHeight + fullDataHeight + loadingDataPlaceholderHeight;
155
+ const stickedToStartColumnsWidth = useMemo(() => Option.fromNullable(stickedToStartColumns)
156
+ .map(columns => columns.reduce((acc, column) => acc + column.width, 0))
157
+ .getOr(0), [stickedToStartColumns]);
158
+ const centerColumnsWidth = useMemo(() => columns.reduce((acc, column) => acc + column.width, 0), [columns]);
159
+ const stickedToEndColumnsWidth = useMemo(() => Option.fromNullable(stickedToEndColumns)
160
+ .map(columns => columns.reduce((acc, column) => acc + column.width, 0))
161
+ .getOr(0), [stickedToEndColumns]);
162
+ const contentContainerWidth = stickedToStartColumnsWidth + centerColumnsWidth + stickedToEndColumnsWidth;
163
+ const backgroundColor = backgroundColorVariants[variant];
164
+ // We store the `startIndex` and `endIndex` rather than the scroll position
165
+ // so that it triggers way less re-renders
166
+ const [rangeToRender, setRangeToRender] = useState(undefined);
167
+ const [clientHeight, setClientHeight] = useState(undefined);
168
+ const [horizontalScrollPosition, setHasHorizontalScrollPosition] = useState(undefined);
169
+ const rowsToRender = useMemo(() => {
170
+ return Option.fromNullable(rangeToRender).map(({ startIndex, endIndex }) => ({
171
+ startIndex,
172
+ endIndex,
173
+ data: data.slice(startIndex, endIndex),
174
+ }));
175
+ }, [data, rangeToRender]);
176
+ useLayoutEffect(() => {
177
+ const element = Option.fromNullable(scrollViewRef.current).flatMap(ref => Option.fromNullable(ref.element));
178
+ setRangeToRender(previousRangeToRender => element
179
+ .map(scrollView => {
180
+ const startIndex = Math.max(0, Math.floor((scrollView.scrollTop - renderThreshold) / rowHeight));
181
+ const endIndex = Math.min(data.length, startIndex + Math.ceil((scrollView.scrollHeight + renderThreshold * 2) / rowHeight));
182
+ if ((previousRangeToRender === null || previousRangeToRender === void 0 ? void 0 : previousRangeToRender.startIndex) === startIndex &&
183
+ previousRangeToRender.endIndex === endIndex) {
184
+ return previousRangeToRender;
185
+ }
186
+ return { startIndex, endIndex };
187
+ })
188
+ .toUndefined());
189
+ setClientHeight(element.map(scrollView => scrollView.clientHeight).toUndefined());
190
+ setHasHorizontalScrollPosition(element
191
+ .map(scrollView => scrollView.scrollWidth === scrollView.clientWidth
192
+ ? "NoScroll"
193
+ : scrollView.scrollLeft <= 0
194
+ ? "Start"
195
+ : scrollView.scrollLeft >= scrollView.scrollWidth - scrollView.clientWidth
196
+ ? "End"
197
+ : "Middle")
198
+ .toUndefined());
199
+ }, [data, renderThreshold, rowHeight]);
200
+ const scrollTimeoutRef = useRef(undefined);
201
+ const rowsContainerRef = useRef(null);
202
+ const onScroll = useCallback(() => {
203
+ const element = Option.fromNullable(scrollViewRef.current).flatMap(ref => Option.fromNullable(ref.element));
204
+ // Disable interactions in cells during scroll, avoids useless
205
+ // re-renders
206
+ if (scrollTimeoutRef.current != null) {
207
+ clearTimeout(scrollTimeoutRef.current);
208
+ }
209
+ if (rowsContainerRef.current instanceof HTMLElement) {
210
+ rowsContainerRef.current.style.pointerEvents = "none";
211
+ }
212
+ scrollTimeoutRef.current = window.setTimeout(() => {
213
+ if (rowsContainerRef.current instanceof HTMLElement) {
214
+ rowsContainerRef.current.style.pointerEvents = "auto";
215
+ }
216
+ }, 100);
217
+ setRangeToRender(previousRangeToRender => element
218
+ .map(scrollView => {
219
+ const startIndex = Math.max(0, Math.floor((scrollView.scrollTop - renderThreshold) / rowHeight));
220
+ const endIndex = Math.min(data.length, startIndex + Math.ceil((scrollView.scrollHeight + renderThreshold * 2) / rowHeight));
221
+ if ((previousRangeToRender === null || previousRangeToRender === void 0 ? void 0 : previousRangeToRender.startIndex) === startIndex &&
222
+ previousRangeToRender.endIndex === endIndex) {
223
+ return previousRangeToRender;
224
+ }
225
+ return { startIndex, endIndex };
226
+ })
227
+ .toUndefined());
228
+ setHasHorizontalScrollPosition(element
229
+ .map(scrollView => scrollView.scrollWidth === scrollView.clientWidth
230
+ ? "NoScroll"
231
+ : scrollView.scrollLeft <= 0
232
+ ? "Start"
233
+ : scrollView.scrollLeft >= scrollView.scrollWidth - scrollView.clientWidth
234
+ ? "End"
235
+ : "Middle")
236
+ .toUndefined());
237
+ }, [data, renderThreshold, rowHeight]);
238
+ // tracks if the threshold to initiate the next data load is reached
239
+ useEffect(() => {
240
+ const scrollTracker = scrollTrackerRef.current;
241
+ if (scrollTracker != null) {
242
+ const scrollTrackerElement = scrollTracker;
243
+ const intersectionObserver = new IntersectionObserver(entries => {
244
+ entries.forEach(entry => {
245
+ if (entry.isIntersecting) {
246
+ if (onEndReached != null) {
247
+ onEndReached();
248
+ }
249
+ }
250
+ });
251
+ });
252
+ intersectionObserver.observe(scrollTrackerElement);
253
+ return () => intersectionObserver.unobserve(scrollTrackerElement);
254
+ }
255
+ }, [onEndReached, data.length]);
256
+ const header = useMemo(() => {
257
+ return (_jsxs(View, { style: [styles.headerRow, { height: headerHeight }], children: [Option.fromNullable(stickedToStartColumns)
258
+ .map(columns => (_jsx(View, { style: [
259
+ styles.cellsContainer,
260
+ styles.stickedToStartColumnGroup,
261
+ { width: stickedToStartColumnsWidth, backgroundColor },
262
+ ], children: columns.map(({ id, width, title, renderTitle }) => {
263
+ const columnId = `${viewId}_${id}`;
264
+ return (_jsx(View, { style: [styles.headerCell, { width }], id: columnId, children: renderTitle({ title, extraInfo, id }) }, columnId));
265
+ }) })))
266
+ .toNull(), _jsx(View, { style: [styles.cellsContainer, { width: centerColumnsWidth, backgroundColor }], children: columns.map(({ id, width, title, renderTitle }) => {
267
+ const columnId = `${viewId}_${id}`;
268
+ return (_jsx(View, { style: [styles.headerCell, { width }], id: columnId, children: renderTitle({ title, extraInfo, id }) }, columnId));
269
+ }) }), Option.fromNullable(stickedToEndColumns)
270
+ .map(columns => (_jsx(View, { style: [
271
+ styles.cellsContainer,
272
+ styles.stickedToEndColumnGroup,
273
+ { width: stickedToEndColumnsWidth, backgroundColor },
274
+ ], children: columns.map(({ id, width, title, renderTitle }) => {
275
+ const columnId = `${viewId}_${id}`;
276
+ return (_jsx(View, { style: [styles.headerCell, { width }], id: columnId, children: renderTitle({ title, extraInfo, id }) }, columnId));
277
+ }) })))
278
+ .toNull()] }));
279
+ }, [
280
+ backgroundColor,
281
+ stickedToStartColumnsWidth,
282
+ centerColumnsWidth,
283
+ stickedToEndColumnsWidth,
284
+ headerHeight,
285
+ extraInfo,
286
+ stickedToStartColumns,
287
+ columns,
288
+ stickedToEndColumns,
289
+ viewId,
290
+ ]);
291
+ const startColumnShadow = useMemo(() => {
292
+ if (stickedToStartColumnsWidth === 0) {
293
+ return Option.None();
294
+ }
295
+ return Option.Some(_jsx(View, { style: [
296
+ styles.startColumnsShadow,
297
+ {
298
+ width: stickedToStartColumnsWidth,
299
+ opacity: Option.fromNullable(horizontalScrollPosition)
300
+ .map(value => (value === "Start" || value === "NoScroll" ? 0 : 1))
301
+ .getOr(0),
302
+ },
303
+ ] }));
304
+ }, [stickedToStartColumnsWidth, horizontalScrollPosition]);
305
+ const endColumnShadow = useMemo(() => {
306
+ if (stickedToEndColumnsWidth === 0) {
307
+ return Option.None();
308
+ }
309
+ return Option.Some(_jsx(View, { style: [
310
+ styles.endColumnsShadow,
311
+ {
312
+ width: stickedToEndColumnsWidth,
313
+ opacity: Option.fromNullable(horizontalScrollPosition)
314
+ .map(value => (value === "End" || value === "NoScroll" ? 0 : 1))
315
+ .getOr(0),
316
+ },
317
+ ] }));
318
+ }, [stickedToEndColumnsWidth, horizontalScrollPosition]);
319
+ return (_jsxs(ScrollView, { ref: scrollViewRef, both: true, style: styles.container, onScroll: onScroll, scrollEventThrottle: 32, contentContainerStyle: {
320
+ height: containerContainerHeight,
321
+ width: contentContainerWidth,
322
+ }, children: [header, rowsToRender
323
+ .map(({ startIndex, endIndex, data }) => (_jsxs(View, { style: styles.rowsContainer, ref: rowsContainerRef, children: [data.map((item, index) => (_jsx(VirtualizedRow, { viewId: viewId, item: item, rowHeight: rowHeight, absoluteIndex: startIndex + index, variant: variant, stickedToStartColumnsWidth: stickedToStartColumnsWidth, centerColumnsWidth: centerColumnsWidth, stickedToEndColumnsWidth: stickedToEndColumnsWidth, stickedToStartColumns: stickedToStartColumns, columns: columns, stickedToEndColumns: stickedToEndColumns, extraInfo: extraInfo }, keyExtractor(item, startIndex + index)))), Option.fromNullable(loading)
324
+ .flatMap(({ isLoading, count }) => (isLoading ? Option.Some(count) : Option.None()))
325
+ .map(count => (_jsx(View, { "aria-busy": true, style: [
326
+ styles.loadingPlaceholder,
327
+ {
328
+ top: endIndex * rowHeight,
329
+ },
330
+ ], children: _jsx(VirtualizedListPlaceholder, { count: count, headerHeight: 0, rowHeight: rowHeight }) })))
331
+ .toNull()] })))
332
+ .toNull(), Option.fromNullable(clientHeight)
333
+ .map(clientHeight => (_jsx(View, { style: styles.shadowsLayerContainer, children: _jsxs(View, { style: [styles.shadowsLayer, { height: clientHeight - 12 }], children: [startColumnShadow.toNull(), _jsx(View, { style: { width: centerColumnsWidth } }), endColumnShadow.toNull()] }) })))
334
+ .toNull(), _jsx(View, { style: [styles.scrollTracker, { height: onEndReachedThreshold }], ref: scrollTrackerRef })] }));
335
+ };
336
+ const RawVirtualizedRow = ({ viewId, rowHeight, absoluteIndex, variant, stickedToStartColumnsWidth, centerColumnsWidth, stickedToEndColumnsWidth, stickedToStartColumns, columns, stickedToEndColumns, extraInfo, item, getRowLink, }) => {
337
+ var _a;
338
+ const [isHovered, setIsHovered] = useState(false);
339
+ const elementRef = useRef(null);
340
+ useHover(elementRef, {
341
+ onHoverStart: () => setIsHovered(true),
342
+ onHoverEnd: () => setIsHovered(false),
343
+ });
344
+ const rootElement = getRowLink != null ? (((_a = getRowLink({ item, index: absoluteIndex, extraInfo })) !== null && _a !== void 0 ? _a : _jsx(View, {}))) : (_jsx(View, {}));
345
+ return cloneElement(rootElement, {
346
+ ref: elementRef,
347
+ style: [
348
+ styles.row,
349
+ isHovered && {
350
+ backgroundColor: variant === "accented"
351
+ ? backgroundColorVariants.default
352
+ : backgroundColorVariants.accented,
353
+ },
354
+ {
355
+ backgroundColor: backgroundColorVariants[variant],
356
+ top: absoluteIndex * rowHeight,
357
+ height: rowHeight,
358
+ },
359
+ ],
360
+ children: (_jsxs(_Fragment, { children: [Option.fromNullable(stickedToStartColumns)
361
+ .map(columns => (_jsx(View, { style: [
362
+ styles.cellsContainer,
363
+ styles.stickedToStartColumnGroup,
364
+ {
365
+ width: stickedToStartColumnsWidth,
366
+ backgroundColor: isHovered
367
+ ? backgroundColorVariants[variant === "accented" ? "default" : "accented"]
368
+ : backgroundColorVariants[variant],
369
+ },
370
+ ], children: columns.map(({ id, width, renderCell }) => {
371
+ const columnId = `${viewId}_${id}`;
372
+ return (_jsx(View, { style: [styles.cell, { width }], "aria-describedby": columnId, children: renderCell({
373
+ columnId,
374
+ item,
375
+ index: absoluteIndex,
376
+ extraInfo,
377
+ isHovered: false,
378
+ }) }, columnId));
379
+ }) })))
380
+ .toNull(), _jsx(View, { style: [
381
+ styles.cellsContainer,
382
+ {
383
+ width: centerColumnsWidth,
384
+ backgroundColor: isHovered
385
+ ? backgroundColorVariants[variant === "accented" ? "default" : "accented"]
386
+ : backgroundColorVariants[variant],
387
+ },
388
+ ], children: columns.map(({ id, width, renderCell }) => {
389
+ const columnId = `${viewId}_${id}`;
390
+ return (_jsx(View, { style: [styles.cell, { width }], "aria-describedby": columnId, children: renderCell({
391
+ columnId,
392
+ item,
393
+ index: absoluteIndex,
394
+ extraInfo,
395
+ isHovered: false,
396
+ }) }, columnId));
397
+ }) }), Option.fromNullable(stickedToEndColumns)
398
+ .map(columns => (_jsx(View, { style: [
399
+ styles.cellsContainer,
400
+ styles.stickedToEndColumnGroup,
401
+ {
402
+ width: stickedToEndColumnsWidth,
403
+ backgroundColor: isHovered
404
+ ? backgroundColorVariants[variant === "accented" ? "default" : "accented"]
405
+ : backgroundColorVariants[variant],
406
+ },
407
+ ], children: columns.map(({ id, width, renderCell }) => {
408
+ const columnId = `${viewId}_${id}`;
409
+ return (_jsx(View, { style: [styles.cell, { width }], "aria-describedby": columnId, children: renderCell({
410
+ columnId,
411
+ item,
412
+ index: absoluteIndex,
413
+ extraInfo,
414
+ isHovered: false,
415
+ }) }, columnId));
416
+ }) })))
417
+ .toNull()] })),
418
+ });
419
+ };
420
+ const VirtualizedRow = memo(RawVirtualizedRow);
421
+ export const VirtualizedListPlaceholder = ({ count, rowHeight, groupHeaderHeight, headerHeight, }) => {
422
+ return (_jsxs(View, { style: styles.container, children: [headerHeight != null ? _jsx(View, { style: { height: headerHeight } }) : null, groupHeaderHeight != groupHeaderHeight ? _jsx(View, { style: { height: headerHeight } }) : null, _jsx(View, { children: Array.from({ length: count }, (_, index) => {
423
+ const top = index * rowHeight;
424
+ return (_jsx(View, { style: [styles.placeholderRowContainer, { height: rowHeight, top }], children: _jsxs(View, { style: styles.placeholderRowContents, children: [_jsx(View, { style: styles.placeholderRow }), _jsx(Space, { width: 32 }), _jsx(View, { style: [styles.placeholderRow, styles.smallPlaceholderRow] }), _jsx(Space, { width: 32 }), _jsx(View, { style: styles.placeholderRowEnd, children: _jsx(View, { style: [styles.placeholderRow, styles.smallPlaceholderRow] }) })] }) }, String(index)));
425
+ }) })] }));
426
+ };