fluent-styles 1.61.0 → 1.62.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.
@@ -0,0 +1,644 @@
1
+ "use strict";
2
+
3
+ import React, { useState, useCallback } from "react";
4
+ import { ScrollView, FlatList, useWindowDimensions } from "react-native";
5
+ import { Stack } from "../stack/index.js";
6
+ import { StyledText } from "../text/index.js";
7
+ import { StyledCheckBox } from "../checkBox/index.js";
8
+ import { StyledPressable } from "../pressable/index.js";
9
+ import { theme, palettes } from "../utiles/theme.js";
10
+
11
+ // ─── CompatNode ───────────────────────────────────────────────────────────────
12
+
13
+ // ─── Column definition ────────────────────────────────────────────────────────
14
+
15
+ // ─── Row data ─────────────────────────────────────────────────────────────────
16
+
17
+ // ─── Color tokens ─────────────────────────────────────────────────────────────
18
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
19
+ const DEFAULT_COLORS = {
20
+ background: palettes.white,
21
+ headerBg: theme.colors.gray[50],
22
+ headerText: theme.colors.gray[400],
23
+ rowBg: palettes.white,
24
+ rowAltBg: palettes.white,
25
+ rowHoverBg: theme.colors.gray[50],
26
+ selectedBg: palettes.indigo[50],
27
+ selectedBorder: palettes.indigo[200],
28
+ border: theme.colors.gray[100],
29
+ divider: theme.colors.gray[100],
30
+ text: theme.colors.gray[900],
31
+ subText: theme.colors.gray[400],
32
+ sortActive: theme.colors.gray[900],
33
+ sortInactive: theme.colors.gray[300],
34
+ checkboxChecked: theme.colors.gray[900],
35
+ emptyText: theme.colors.gray[400]
36
+ };
37
+
38
+ // ─── Props ────────────────────────────────────────────────────────────────────
39
+
40
+ // ─── Sort icon ────────────────────────────────────────────────────────────────
41
+
42
+ const SortIcon = ({
43
+ direction,
44
+ active,
45
+ color,
46
+ inactiveColor
47
+ }) => /*#__PURE__*/_jsxs(Stack, {
48
+ gap: 1,
49
+ marginLeft: 4,
50
+ children: [/*#__PURE__*/_jsx(StyledText, {
51
+ fontSize: 8,
52
+ lineHeight: 9,
53
+ color: active && direction === "asc" ? color : inactiveColor,
54
+ children: "\u25B2"
55
+ }), /*#__PURE__*/_jsx(StyledText, {
56
+ fontSize: 8,
57
+ lineHeight: 9,
58
+ color: active && direction === "desc" ? color : inactiveColor,
59
+ children: "\u25BC"
60
+ })]
61
+ });
62
+
63
+ // ─── Cell wrapper ─────────────────────────────────────────────────────────────
64
+
65
+ const Cell = ({
66
+ width,
67
+ align = "left",
68
+ children,
69
+ isFirst
70
+ }) => /*#__PURE__*/_jsx(Stack, {
71
+ flex: width ? undefined : 1,
72
+ width: width,
73
+ alignItems: align === "center" ? "center" : align === "right" ? "flex-end" : "flex-start",
74
+ paddingHorizontal: isFirst ? 16 : 12,
75
+ paddingVertical: 14,
76
+ justifyContent: "center",
77
+ children: children
78
+ });
79
+
80
+ // ─── StyledTable ──────────────────────────────────────────────────────────────
81
+
82
+ // ─── Card list (phone layout) ─────────────────────────────────────────────────
83
+
84
+ function CardList({
85
+ columns,
86
+ data,
87
+ selectable,
88
+ selectedIds,
89
+ onSelectionChange,
90
+ cardRender,
91
+ emptyText,
92
+ emptyNode,
93
+ pagination,
94
+ pageSize,
95
+ onRowPress,
96
+ colors: colorOverrides,
97
+ borderRadius
98
+ }) {
99
+ const c = {
100
+ ...DEFAULT_COLORS,
101
+ ...colorOverrides
102
+ };
103
+ const br = borderRadius ?? 16;
104
+
105
+ // internal selection
106
+ const [internalSelected, setInternalSelected] = React.useState([]);
107
+ const selectedIds_ = selectedIds ?? internalSelected;
108
+ const toggle = id => {
109
+ const next = selectedIds_.includes(id) ? selectedIds_.filter(s => s !== id) : [...selectedIds_, id];
110
+ setInternalSelected(next);
111
+ onSelectionChange?.(next);
112
+ };
113
+
114
+ // pagination
115
+ const [page, setPage] = React.useState(0);
116
+ const ps = pageSize ?? 10;
117
+ const totalPages = Math.ceil(data.length / ps);
118
+ const visible = pagination ? data.slice(page * ps, (page + 1) * ps) : data;
119
+ if (visible.length === 0) {
120
+ return /*#__PURE__*/_jsx(Stack, {
121
+ paddingVertical: 48,
122
+ alignItems: "center",
123
+ justifyContent: "center",
124
+ children: emptyNode ?? /*#__PURE__*/_jsx(StyledText, {
125
+ fontSize: 14,
126
+ color: c.emptyText,
127
+ children: emptyText ?? "No data"
128
+ })
129
+ });
130
+ }
131
+ return /*#__PURE__*/_jsxs(Stack, {
132
+ gap: 10,
133
+ children: [visible.map((row, idx) => {
134
+ const isSelected = selectedIds_.includes(row.id);
135
+ if (cardRender) {
136
+ return /*#__PURE__*/_jsx(React.Fragment, {
137
+ children: cardRender(row, idx, isSelected, selectable ? () => toggle(row.id) : undefined)
138
+ }, row.id);
139
+ }
140
+
141
+ // ── Default auto-card ─────────────────────────────────────────────
142
+ // Uses column definitions to render label: value pairs.
143
+ const [primary, ...rest] = columns;
144
+ return /*#__PURE__*/_jsxs(StyledPressable, {
145
+ onPress: () => onRowPress?.(row, idx),
146
+ disabled: !onRowPress && !selectable,
147
+ borderRadius: br,
148
+ borderWidth: 1,
149
+ borderColor: isSelected ? c.selectedBorder : c.border,
150
+ backgroundColor: isSelected ? c.selectedBg : c.rowBg,
151
+ borderLeftWidth: isSelected ? 3 : 1,
152
+ borderLeftColor: isSelected ? c.selectedBorder : c.border,
153
+ overflow: "hidden",
154
+ style: {
155
+ shadowColor: "#000",
156
+ shadowOffset: {
157
+ width: 0,
158
+ height: 1
159
+ },
160
+ shadowOpacity: 0.05,
161
+ shadowRadius: 4,
162
+ elevation: 1
163
+ },
164
+ children: [/*#__PURE__*/_jsxs(Stack, {
165
+ horizontal: true,
166
+ alignItems: "center",
167
+ justifyContent: "space-between",
168
+ paddingHorizontal: 14,
169
+ paddingVertical: 12,
170
+ borderBottomWidth: 1,
171
+ borderBottomColor: c.divider,
172
+ backgroundColor: c.headerBg,
173
+ children: [/*#__PURE__*/_jsx(Stack, {
174
+ flex: 1,
175
+ children: primary.render ? primary.render(row[primary.key], row, idx) : /*#__PURE__*/_jsx(StyledText, {
176
+ fontSize: 14,
177
+ fontWeight: "700",
178
+ color: c.text,
179
+ numberOfLines: 1,
180
+ children: row[primary.key]
181
+ })
182
+ }), selectable && /*#__PURE__*/_jsx(StyledCheckBox, {
183
+ checked: isSelected,
184
+ onCheck: () => toggle(row.id),
185
+ size: 18,
186
+ checkedColor: c.checkboxChecked
187
+ })]
188
+ }), /*#__PURE__*/_jsx(Stack, {
189
+ paddingHorizontal: 14,
190
+ paddingVertical: 10,
191
+ gap: 8,
192
+ children: rest.map(col => /*#__PURE__*/_jsxs(Stack, {
193
+ horizontal: true,
194
+ alignItems: "center",
195
+ justifyContent: "space-between",
196
+ gap: 8,
197
+ children: [/*#__PURE__*/_jsx(StyledText, {
198
+ fontSize: 12,
199
+ color: c.subText,
200
+ fontWeight: "500",
201
+ children: col.title
202
+ }), /*#__PURE__*/_jsx(Stack, {
203
+ alignItems: "flex-end",
204
+ children: col.render ? col.render(row[col.key], row, idx) : /*#__PURE__*/_jsx(StyledText, {
205
+ fontSize: 13,
206
+ color: c.text,
207
+ children: row[col.key] ?? "—"
208
+ })
209
+ })]
210
+ }, col.key))
211
+ })]
212
+ }, row.id);
213
+ }), pagination && totalPages > 1 && /*#__PURE__*/_jsxs(Stack, {
214
+ horizontal: true,
215
+ alignItems: "center",
216
+ justifyContent: "space-between",
217
+ paddingVertical: 4,
218
+ children: [/*#__PURE__*/_jsxs(StyledText, {
219
+ fontSize: 12,
220
+ color: c.subText,
221
+ children: [page * ps + 1, "\u2013", Math.min((page + 1) * ps, data.length), " of ", data.length]
222
+ }), /*#__PURE__*/_jsxs(Stack, {
223
+ horizontal: true,
224
+ gap: 6,
225
+ children: [/*#__PURE__*/_jsx(StyledPressable, {
226
+ onPress: () => setPage(p => Math.max(0, p - 1)),
227
+ disabled: page === 0,
228
+ paddingHorizontal: 12,
229
+ paddingVertical: 6,
230
+ borderRadius: 8,
231
+ borderWidth: 1,
232
+ borderColor: page === 0 ? c.border : c.sortActive,
233
+ opacity: page === 0 ? 0.4 : 1,
234
+ children: /*#__PURE__*/_jsx(StyledText, {
235
+ fontSize: 12,
236
+ fontWeight: "600",
237
+ color: c.text,
238
+ children: "\u2190 Prev"
239
+ })
240
+ }), /*#__PURE__*/_jsx(StyledPressable, {
241
+ onPress: () => setPage(p => Math.min(totalPages - 1, p + 1)),
242
+ disabled: page >= totalPages - 1,
243
+ paddingHorizontal: 12,
244
+ paddingVertical: 6,
245
+ borderRadius: 8,
246
+ borderWidth: 1,
247
+ borderColor: page >= totalPages - 1 ? c.border : c.sortActive,
248
+ opacity: page >= totalPages - 1 ? 0.4 : 1,
249
+ children: /*#__PURE__*/_jsx(StyledText, {
250
+ fontSize: 12,
251
+ fontWeight: "600",
252
+ color: c.text,
253
+ children: "Next \u2192"
254
+ })
255
+ })]
256
+ })]
257
+ })]
258
+ });
259
+ }
260
+ export function StyledTable({
261
+ columns,
262
+ data,
263
+ selectable = false,
264
+ selectedIds: controlledSelectedIds,
265
+ onSelectionChange,
266
+ sortKey: controlledSortKey,
267
+ sortDirection: controlledSortDir,
268
+ onSort,
269
+ pagination = false,
270
+ pageSize = 10,
271
+ striped = false,
272
+ showDivider = true,
273
+ scrollable = false,
274
+ emptyText = "No data",
275
+ emptyNode,
276
+ colors: colorOverrides,
277
+ borderRadius = 16,
278
+ bordered = true,
279
+ virtualized,
280
+ cardBreakpoint = 768,
281
+ forceTable,
282
+ forceCards,
283
+ cardRender,
284
+ externalPagination = false,
285
+ currentPage = 0,
286
+ totalPages: externalTotalPages,
287
+ totalCount,
288
+ onPageChange,
289
+ loading = false,
290
+ onRowPress
291
+ }) {
292
+ const {
293
+ width
294
+ } = useWindowDimensions();
295
+ const isCardMode = forceCards ? true : forceTable ? false : cardBreakpoint > 0 && width < cardBreakpoint;
296
+
297
+ // ── Card mode — render rows as stacked cards ─────────────────────────────
298
+ if (isCardMode) {
299
+ return /*#__PURE__*/_jsx(CardList, {
300
+ columns: columns,
301
+ data: data,
302
+ selectable: selectable,
303
+ selectedIds: controlledSelectedIds,
304
+ onSelectionChange: onSelectionChange,
305
+ cardRender: cardRender,
306
+ emptyText: emptyText,
307
+ emptyNode: emptyNode,
308
+ pagination: pagination,
309
+ pageSize: pageSize,
310
+ onRowPress: onRowPress,
311
+ colors: colorOverrides,
312
+ borderRadius: borderRadius
313
+ });
314
+ }
315
+ const c = {
316
+ ...DEFAULT_COLORS,
317
+ ...colorOverrides
318
+ };
319
+
320
+ // ── Internal selection state (uncontrolled fallback) ───────────────────
321
+ const [internalSelected, setInternalSelected] = useState([]);
322
+ const selectedIds = controlledSelectedIds ?? internalSelected;
323
+ const toggleRow = useCallback(id => {
324
+ const next = selectedIds.includes(id) ? selectedIds.filter(s => s !== id) : [...selectedIds, id];
325
+ setInternalSelected(next);
326
+ onSelectionChange?.(next);
327
+ }, [selectedIds, onSelectionChange]);
328
+ const toggleAll = useCallback(() => {
329
+ const allIds = data.map(r => r.id);
330
+ const allSelected = allIds.every(id => selectedIds.includes(id));
331
+ const next = allSelected ? [] : allIds;
332
+ setInternalSelected(next);
333
+ onSelectionChange?.(next);
334
+ }, [data, selectedIds, onSelectionChange]);
335
+ const allSelected = data.length > 0 && data.every(r => selectedIds.includes(r.id));
336
+
337
+ // ── Internal sort state (uncontrolled fallback) ────────────────────────
338
+ const [internalSortKey, setInternalSortKey] = useState(null);
339
+ const [internalSortDir, setInternalSortDir] = useState(null);
340
+ const activeSortKey = controlledSortKey ?? internalSortKey;
341
+ const activeSortDir = controlledSortDir ?? internalSortDir;
342
+ const handleSort = useCallback(key => {
343
+ const next = activeSortKey === key ? activeSortDir === "asc" ? "desc" : activeSortDir === "desc" ? null : "asc" : "asc";
344
+ setInternalSortKey(next === null ? null : key);
345
+ setInternalSortDir(next);
346
+ onSort?.(key, next);
347
+ }, [activeSortKey, activeSortDir, onSort]);
348
+
349
+ // ── Client-side sort (used when onSort not provided) ───────────────────
350
+ const sortedData = React.useMemo(() => {
351
+ if (!activeSortKey || !activeSortDir || onSort) return data;
352
+ return [...data].sort((a, b) => {
353
+ const av = a[activeSortKey];
354
+ const bv = b[activeSortKey];
355
+ const cmp = typeof av === "number" && typeof bv === "number" ? av - bv : String(av ?? "").localeCompare(String(bv ?? ""));
356
+ return activeSortDir === "asc" ? cmp : -cmp;
357
+ });
358
+ }, [data, activeSortKey, activeSortDir, onSort]);
359
+
360
+ // ── Pagination ────────────────────────────────────────────────────────
361
+ const [internalPage, setInternalPage] = useState(0);
362
+
363
+ // External mode: parent controls page + data
364
+ // Internal mode: we slice sortedData ourselves
365
+ const page = externalPagination ? currentPage : internalPage;
366
+ const totalPages = externalPagination ? externalTotalPages ?? 1 : Math.ceil(sortedData.length / pageSize);
367
+ const visibleData = externalPagination ? sortedData // parent already gave us just this page
368
+ : pagination ? sortedData.slice(page * pageSize, (page + 1) * pageSize) : sortedData;
369
+
370
+ // Auto-enable FlatList virtualisation for large unpaginated datasets
371
+ const useVirtualized = virtualized ?? (!pagination && !externalPagination && visibleData.length > 50);
372
+ const handlePageChange = p => {
373
+ if (externalPagination) {
374
+ onPageChange?.(p);
375
+ } else {
376
+ setInternalPage(p);
377
+ }
378
+ };
379
+
380
+ // Row count label
381
+ const rowStart = page * pageSize + 1;
382
+ const rowEnd = externalPagination ? totalCount != null ? Math.min(rowStart + visibleData.length - 1, totalCount) : rowStart + visibleData.length - 1 : Math.min((page + 1) * pageSize, sortedData.length);
383
+ const rowTotal = externalPagination ? totalCount ?? "?" : sortedData.length;
384
+
385
+ // ── Render ────────────────────────────────────────────────────────────
386
+ const tableContent = /*#__PURE__*/_jsxs(Stack, {
387
+ children: [/*#__PURE__*/_jsxs(Stack, {
388
+ horizontal: true,
389
+ backgroundColor: c.headerBg,
390
+ borderTopLeftRadius: borderRadius,
391
+ borderTopRightRadius: borderRadius,
392
+ borderBottomWidth: 1,
393
+ borderBottomColor: c.border,
394
+ children: [selectable && /*#__PURE__*/_jsx(Stack, {
395
+ width: 52,
396
+ paddingHorizontal: 16,
397
+ paddingVertical: 14,
398
+ alignItems: "center",
399
+ justifyContent: "center",
400
+ children: /*#__PURE__*/_jsx(StyledCheckBox, {
401
+ checked: allSelected,
402
+ onCheck: toggleAll,
403
+ size: 18,
404
+ checkedColor: c.checkboxChecked
405
+ })
406
+ }), columns.map((col, i) => /*#__PURE__*/_jsx(Cell, {
407
+ width: col.width,
408
+ align: col.align,
409
+ isFirst: i === 0 && !selectable,
410
+ children: /*#__PURE__*/_jsxs(StyledPressable, {
411
+ flexDirection: "row",
412
+ alignItems: "center",
413
+ onPress: col.sortable ? () => handleSort(col.key) : undefined,
414
+ disabled: !col.sortable,
415
+ children: [/*#__PURE__*/_jsx(StyledText, {
416
+ fontSize: 12,
417
+ fontWeight: "600",
418
+ color: c.headerText,
419
+ letterSpacing: 0.3,
420
+ children: col.title
421
+ }), col.sortable && /*#__PURE__*/_jsx(SortIcon, {
422
+ direction: activeSortDir,
423
+ active: activeSortKey === col.key,
424
+ color: c.sortActive,
425
+ inactiveColor: c.sortInactive
426
+ })]
427
+ })
428
+ }, col.key))]
429
+ }), visibleData.length === 0 ? /*#__PURE__*/_jsx(Stack, {
430
+ paddingVertical: 48,
431
+ alignItems: "center",
432
+ justifyContent: "center",
433
+ backgroundColor: c.rowBg,
434
+ borderBottomLeftRadius: borderRadius,
435
+ borderBottomRightRadius: borderRadius,
436
+ children: emptyNode ?? /*#__PURE__*/_jsx(StyledText, {
437
+ fontSize: 14,
438
+ color: c.emptyText,
439
+ children: emptyText
440
+ })
441
+ }) : useVirtualized ?
442
+ /*#__PURE__*/
443
+ // ── FlatList path — only mounts rows in the viewport ────────────
444
+ _jsx(FlatList, {
445
+ data: visibleData,
446
+ keyExtractor: row => String(row.id)
447
+ // Pass selectedIds + striped as extraData so FlatList knows to re-render
448
+ // when selection changes (FlatList only re-renders items whose key changes
449
+ // otherwise — extraData forces a full diff)
450
+ ,
451
+ extraData: [selectedIds, striped],
452
+ scrollEnabled: false // outer ScrollView handles scrolling
453
+ ,
454
+ renderItem: ({
455
+ item: row,
456
+ index: rowIndex
457
+ }) => {
458
+ const isSelected = selectedIds.includes(row.id);
459
+ const isLast = rowIndex === visibleData.length - 1;
460
+ const isAlt = striped && rowIndex % 2 !== 0;
461
+ const rowBg = isSelected ? c.selectedBg : isAlt ? c.rowAltBg : c.rowBg;
462
+ return /*#__PURE__*/_jsxs(StyledPressable, {
463
+ flexDirection: "row",
464
+ alignItems: "center",
465
+ backgroundColor: rowBg,
466
+ borderLeftWidth: isSelected ? 3 : 0,
467
+ borderLeftColor: isSelected ? c.selectedBorder : "transparent",
468
+ borderBottomWidth: showDivider && !isLast ? 1 : 0,
469
+ borderBottomColor: c.divider,
470
+ borderBottomLeftRadius: isLast ? borderRadius : 0,
471
+ borderBottomRightRadius: isLast ? borderRadius : 0,
472
+ onPress: () => onRowPress?.(row, rowIndex),
473
+ disabled: !onRowPress && !selectable,
474
+ children: [selectable && /*#__PURE__*/_jsx(Stack, {
475
+ width: 52,
476
+ paddingHorizontal: 16,
477
+ paddingVertical: 14,
478
+ alignItems: "center",
479
+ justifyContent: "center",
480
+ children: /*#__PURE__*/_jsx(StyledCheckBox, {
481
+ checked: isSelected,
482
+ onCheck: () => toggleRow(row.id),
483
+ size: 18,
484
+ checkedColor: c.checkboxChecked
485
+ })
486
+ }), columns.map((col, colIndex) => /*#__PURE__*/_jsx(Cell, {
487
+ width: col.width,
488
+ align: col.align,
489
+ isFirst: colIndex === 0 && !selectable,
490
+ children: col.render ? col.render(row[col.key], row, rowIndex) : /*#__PURE__*/_jsx(StyledText, {
491
+ fontSize: 14,
492
+ color: c.text,
493
+ numberOfLines: 1,
494
+ children: row[col.key] ?? "—"
495
+ })
496
+ }, col.key))]
497
+ });
498
+ }
499
+ }) :
500
+ // ── Stack.map path — simple, best for ≤ 50 rows ─────────────────
501
+ visibleData.map((row, rowIndex) => {
502
+ const isSelected = selectedIds.includes(row.id);
503
+ const isLast = rowIndex === visibleData.length - 1;
504
+ const isAlt = striped && rowIndex % 2 !== 0;
505
+ const rowBg = isSelected ? c.selectedBg : isAlt ? c.rowAltBg : c.rowBg;
506
+ return /*#__PURE__*/_jsxs(StyledPressable, {
507
+ flexDirection: "row",
508
+ alignItems: "center",
509
+ backgroundColor: rowBg,
510
+ borderLeftWidth: isSelected ? 3 : 0,
511
+ borderLeftColor: isSelected ? c.selectedBorder : "transparent",
512
+ borderBottomWidth: showDivider && !isLast ? 1 : 0,
513
+ borderBottomColor: c.divider,
514
+ borderBottomLeftRadius: isLast ? borderRadius : 0,
515
+ borderBottomRightRadius: isLast ? borderRadius : 0,
516
+ onPress: () => onRowPress?.(row, rowIndex),
517
+ disabled: !onRowPress && !selectable,
518
+ children: [selectable && /*#__PURE__*/_jsx(Stack, {
519
+ width: 52,
520
+ paddingHorizontal: 16,
521
+ paddingVertical: 14,
522
+ alignItems: "center",
523
+ justifyContent: "center",
524
+ children: /*#__PURE__*/_jsx(StyledCheckBox, {
525
+ checked: isSelected,
526
+ onCheck: () => toggleRow(row.id),
527
+ size: 18,
528
+ checkedColor: c.checkboxChecked
529
+ })
530
+ }), columns.map((col, colIndex) => /*#__PURE__*/_jsx(Cell, {
531
+ width: col.width,
532
+ align: col.align,
533
+ isFirst: colIndex === 0 && !selectable,
534
+ children: col.render ? col.render(row[col.key], row, rowIndex) : /*#__PURE__*/_jsx(StyledText, {
535
+ fontSize: 14,
536
+ color: c.text,
537
+ numberOfLines: 1,
538
+ children: row[col.key] ?? "—"
539
+ })
540
+ }, col.key))]
541
+ }, row.id);
542
+ }), (pagination || externalPagination) && totalPages > 1 && /*#__PURE__*/_jsxs(Stack, {
543
+ horizontal: true,
544
+ alignItems: "center",
545
+ justifyContent: "space-between",
546
+ paddingHorizontal: 16,
547
+ paddingVertical: 12,
548
+ borderTopWidth: 1,
549
+ borderTopColor: c.border,
550
+ backgroundColor: c.headerBg,
551
+ borderBottomLeftRadius: borderRadius,
552
+ borderBottomRightRadius: borderRadius,
553
+ children: [/*#__PURE__*/_jsxs(StyledText, {
554
+ fontSize: 12,
555
+ color: c.subText,
556
+ children: [rowStart, "\u2013", rowEnd, " of ", rowTotal]
557
+ }), /*#__PURE__*/_jsxs(Stack, {
558
+ horizontal: true,
559
+ gap: 6,
560
+ children: [Array.from({
561
+ length: totalPages
562
+ }, (_, i) => i).filter(i => i === 0 || i === totalPages - 1 || Math.abs(i - page) <= 1).reduce((acc, i, idx, arr) => {
563
+ if (idx > 0 && i - arr[idx - 1] > 1) acc.push("…");
564
+ acc.push(i);
565
+ return acc;
566
+ }, []).map((item, idx) => item === "…" ? /*#__PURE__*/_jsx(StyledText, {
567
+ fontSize: 12,
568
+ color: c.subText,
569
+ paddingHorizontal: 4,
570
+ children: "\u2026"
571
+ }, `ellipsis-${idx}`) : /*#__PURE__*/_jsx(StyledPressable, {
572
+ onPress: () => handlePageChange(item),
573
+ disabled: loading,
574
+ paddingHorizontal: 10,
575
+ paddingVertical: 6,
576
+ borderRadius: 8,
577
+ borderWidth: 1,
578
+ borderColor: page === item ? c.sortActive : c.border,
579
+ backgroundColor: page === item ? c.sortActive : "transparent",
580
+ children: /*#__PURE__*/_jsx(StyledText, {
581
+ fontSize: 12,
582
+ fontWeight: "600",
583
+ color: page === item ? c.background : c.text,
584
+ children: item + 1
585
+ })
586
+ }, item)), /*#__PURE__*/_jsx(StyledPressable, {
587
+ onPress: () => handlePageChange(Math.min(totalPages - 1, page + 1)),
588
+ disabled: page >= totalPages - 1 || loading,
589
+ paddingHorizontal: 12,
590
+ paddingVertical: 6,
591
+ borderRadius: 8,
592
+ borderWidth: 1,
593
+ borderColor: page >= totalPages - 1 ? c.border : c.sortActive,
594
+ opacity: page >= totalPages - 1 ? 0.4 : 1,
595
+ children: /*#__PURE__*/_jsx(StyledText, {
596
+ fontSize: 12,
597
+ fontWeight: "600",
598
+ color: c.text,
599
+ children: "\u2192"
600
+ })
601
+ })]
602
+ })]
603
+ }), loading && /*#__PURE__*/_jsx(Stack, {
604
+ position: "absolute",
605
+ top: 0,
606
+ left: 0,
607
+ right: 0,
608
+ bottom: 0,
609
+ backgroundColor: "rgba(255,255,255,0.7)",
610
+ alignItems: "center",
611
+ justifyContent: "center",
612
+ borderRadius: borderRadius,
613
+ children: /*#__PURE__*/_jsx(StyledText, {
614
+ fontSize: 13,
615
+ color: c.subText,
616
+ children: "Loading\u2026"
617
+ })
618
+ })]
619
+ });
620
+ return /*#__PURE__*/_jsx(Stack, {
621
+ borderRadius: borderRadius,
622
+ borderWidth: bordered ? 1 : 0,
623
+ borderColor: c.border,
624
+ overflow: "hidden",
625
+ backgroundColor: c.background,
626
+ style: bordered ? {
627
+ shadowColor: "#000",
628
+ shadowOffset: {
629
+ width: 0,
630
+ height: 1
631
+ },
632
+ shadowOpacity: 0.06,
633
+ shadowRadius: 8,
634
+ elevation: 2
635
+ } : undefined,
636
+ children: scrollable ? /*#__PURE__*/_jsx(ScrollView, {
637
+ horizontal: true,
638
+ showsHorizontalScrollIndicator: false,
639
+ children: tableContent
640
+ }) : tableContent
641
+ });
642
+ }
643
+ export default StyledTable;
644
+ //# sourceMappingURL=index.js.map