@adapttable/mantine 0.1.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/dist/index.js ADDED
@@ -0,0 +1,1951 @@
1
+ import { usePrefersReducedMotion, pageSizeOptions, useTableChrome, ACTIONS_COLUMN_KEY, useChromeBodyData, useFilterTriggerToggle, useChromeScrollReset, filterLabel, useTableData, resolveLabels, isDeclarativeFilters, resolveDisabledReason, rowClickProps, tableRenderModel, headerGroupRow, useHorizontalOverflow, PIN_Z, edgePinStyle, tableMinWidth, useSavedViews, useBulkActionRunner, RANGE_SUFFIXES, readRangeWidget, RANGE_OP_LABEL_KEYS, RANGE_OPS, useFilterOptions, runRowAction, pinnedCellStyle, columnResizeHandleProps, pinnedColumnWidth, useColumnDragState, columnMenuRows, GripIcon, columnReorderKeyProps, nextPinSide, pinActionLabel, EyeIcon, PinIcon, writeRangeWidget } from '@adapttable/core';
2
+ export { createHistoryAdapter, createMemoryAdapter, defaultConfirm, defaultLabels, deriveSortByOptions, getHistoryAdapter, useBackendData, useDataTable, useFrontendData, useSavedViews, useTableUrlState } from '@adapttable/core';
3
+ import { Group, Pill, Anchor, Stack, Text, Alert, Button, Select, Pagination, Menu, Box, ActionIcon, TextInput, Table, Skeleton, VisuallyHidden, Paper, Progress, Card, Checkbox, Tooltip, Badge, Drawer, Input, Loader, NativeSelect, Popover, NumberInput } from '@mantine/core';
4
+ import { useElementSize } from '@mantine/hooks';
5
+ import { useEffect, useState, useRef, useMemo, useCallback, memo } from 'react';
6
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
7
+
8
+ // src/DataTable.tsx
9
+ function useMountStagger(ref, deps, options) {
10
+ const reduced = usePrefersReducedMotion();
11
+ const { enabled, step = 40, duration = 320 } = options;
12
+ const depsKey = deps.map(String).join("|");
13
+ useEffect(() => {
14
+ if (!enabled || reduced) return;
15
+ const root = ref.current;
16
+ if (!root) return;
17
+ const items = root.querySelectorAll("[data-stagger]");
18
+ items.forEach((el, index) => {
19
+ if (typeof el.animate !== "function") return;
20
+ el.animate(
21
+ [
22
+ { opacity: 0, transform: "translateY(8px)" },
23
+ { opacity: 1, transform: "translateY(0)" }
24
+ ],
25
+ {
26
+ duration,
27
+ delay: index * step,
28
+ easing: "cubic-bezier(0.16, 1, 0.3, 1)",
29
+ fill: "both"
30
+ }
31
+ );
32
+ });
33
+ }, [enabled, reduced, step, duration, ref, depsKey]);
34
+ }
35
+ function ActiveFilterChips({
36
+ chips,
37
+ onClearAll,
38
+ label,
39
+ clearAllLabel
40
+ }) {
41
+ if (chips.length === 0) return null;
42
+ return /* @__PURE__ */ jsxs(
43
+ Group,
44
+ {
45
+ gap: 6,
46
+ "aria-label": label,
47
+ component: "ul",
48
+ style: { listStyle: "none", padding: 0, margin: 0 },
49
+ children: [
50
+ chips.map((chip) => /* @__PURE__ */ jsx(
51
+ Pill,
52
+ {
53
+ component: "li",
54
+ withRemoveButton: true,
55
+ onRemove: chip.onRemove,
56
+ removeButtonProps: {
57
+ "aria-label": `${clearAllLabel}: ${chip.label}`
58
+ },
59
+ children: chip.label
60
+ },
61
+ chip.key
62
+ )),
63
+ onClearAll && /* @__PURE__ */ jsx(
64
+ Anchor,
65
+ {
66
+ component: "button",
67
+ type: "button",
68
+ fz: "xs",
69
+ fw: 600,
70
+ onClick: onClearAll,
71
+ children: clearAllLabel
72
+ }
73
+ )
74
+ ]
75
+ }
76
+ );
77
+ }
78
+ var asText = (value) => value == null ? "" : String(value);
79
+ var asList = (value) => {
80
+ if (value == null || value === "") return [];
81
+ return Array.isArray(value) ? value : [String(value)];
82
+ };
83
+ var asOp = (value) => RANGE_OPS.find((op) => op === value);
84
+ var RANGE_FLAVOUR = { numberRange: "number", dateRange: "date" };
85
+ function RangeField({
86
+ def,
87
+ source,
88
+ kind,
89
+ labels
90
+ }) {
91
+ const label = filterLabel(def);
92
+ const lowKey = def.key + RANGE_SUFFIXES[kind].start;
93
+ const highKey = def.key + RANGE_SUFFIXES[kind].end;
94
+ const derived = readRangeWidget(source.extra, lowKey, highKey);
95
+ const [chosen, setChosen] = useState(null);
96
+ const op = chosen ?? derived.op ?? null;
97
+ const low = asText(source.extra[lowKey]);
98
+ const high = asText(source.extra[highKey]);
99
+ const single = op === "lte" ? high : low;
100
+ const write = (nextOp, a, b) => source.setExtras(writeRangeWidget(nextOp, a, b, lowKey, highKey));
101
+ const handleOp = (value) => {
102
+ const next = asOp(value);
103
+ setChosen(next ?? null);
104
+ write(next, single, "");
105
+ };
106
+ const flavour = RANGE_FLAVOUR[kind];
107
+ const opLabelKeys = RANGE_OP_LABEL_KEYS[flavour];
108
+ const data = RANGE_OPS.map((value) => ({
109
+ value,
110
+ label: labels[opLabelKeys[value]]
111
+ }));
112
+ const valueInput = (text, value, commit) => flavour === "number" ? /* @__PURE__ */ jsx(
113
+ NumberInput,
114
+ {
115
+ size: "sm",
116
+ hideControls: true,
117
+ style: { flex: "1 1 6rem", minWidth: "6rem" },
118
+ "aria-label": `${label} ${text}`,
119
+ placeholder: text,
120
+ value,
121
+ onChange: (next) => commit(String(next))
122
+ }
123
+ ) : /* @__PURE__ */ jsx(
124
+ TextInput,
125
+ {
126
+ type: "date",
127
+ size: "sm",
128
+ style: { flex: "1 1 8.5rem", minWidth: "8.5rem" },
129
+ "aria-label": `${label} ${text}`,
130
+ placeholder: text,
131
+ value,
132
+ onChange: (e) => commit(e.currentTarget.value)
133
+ }
134
+ );
135
+ let values = null;
136
+ if (op === "between") {
137
+ values = /* @__PURE__ */ jsxs(Fragment, { children: [
138
+ valueInput(labels.from, low, (next) => write("between", next, high)),
139
+ valueInput(labels.to, high, (next) => write("between", low, next))
140
+ ] });
141
+ } else if (op) {
142
+ values = valueInput(labels.value, single, (next) => write(op, next, ""));
143
+ }
144
+ return /* @__PURE__ */ jsxs(Stack, { gap: 4, children: [
145
+ /* @__PURE__ */ jsx(Input.Label, { size: "sm", children: label }),
146
+ /* @__PURE__ */ jsxs(Group, { gap: "xs", align: "flex-start", children: [
147
+ /* @__PURE__ */ jsx(
148
+ Select,
149
+ {
150
+ size: "sm",
151
+ clearable: true,
152
+ style: { flex: "0 0 8.5rem", width: "8.5rem" },
153
+ "aria-label": `${label} ${labels.operator}`,
154
+ placeholder: labels.operator,
155
+ data,
156
+ value: op,
157
+ onChange: handleOp,
158
+ comboboxProps: { withinPortal: false }
159
+ }
160
+ ),
161
+ values
162
+ ] })
163
+ ] });
164
+ }
165
+ function SelectControl({
166
+ def,
167
+ source
168
+ }) {
169
+ const label = filterLabel(def);
170
+ const { options, loading } = useFilterOptions(def);
171
+ const data = loading ? [{ value: "", label: "\u2026", disabled: true }] : [{ value: "", label: "All" }, ...options];
172
+ return /* @__PURE__ */ jsx(
173
+ NativeSelect,
174
+ {
175
+ size: "sm",
176
+ label,
177
+ data,
178
+ value: asText(source.extra[def.key]),
179
+ onChange: (e) => source.setExtra(def.key, e.currentTarget.value)
180
+ }
181
+ );
182
+ }
183
+ function MultiSelectControl({
184
+ def,
185
+ source
186
+ }) {
187
+ const label = filterLabel(def);
188
+ const { options, loading } = useFilterOptions(def);
189
+ return /* @__PURE__ */ jsx(
190
+ Checkbox.Group,
191
+ {
192
+ label,
193
+ value: asList(source.extra[def.key]),
194
+ onChange: (values) => source.setExtra(def.key, values),
195
+ children: /* @__PURE__ */ jsx(Group, { gap: "sm", mt: 4, children: loading ? /* @__PURE__ */ jsx(Loader, { size: "xs" }) : options.map((option) => /* @__PURE__ */ jsx(
196
+ Checkbox,
197
+ {
198
+ size: "sm",
199
+ value: option.value,
200
+ label: option.label
201
+ },
202
+ option.value
203
+ )) })
204
+ }
205
+ );
206
+ }
207
+ function FilterControl({
208
+ def,
209
+ source,
210
+ labels
211
+ }) {
212
+ switch (def.type) {
213
+ case "text":
214
+ return /* @__PURE__ */ jsx(
215
+ TextInput,
216
+ {
217
+ size: "sm",
218
+ label: filterLabel(def),
219
+ placeholder: def.placeholder,
220
+ value: asText(source.extra[def.key]),
221
+ onChange: (e) => source.setExtra(def.key, e.currentTarget.value)
222
+ }
223
+ );
224
+ case "select":
225
+ return /* @__PURE__ */ jsx(SelectControl, { def, source });
226
+ case "multiSelect":
227
+ return /* @__PURE__ */ jsx(MultiSelectControl, { def, source });
228
+ case "dateRange":
229
+ case "numberRange":
230
+ return /* @__PURE__ */ jsx(RangeField, { def, source, kind: def.type, labels });
231
+ }
232
+ }
233
+ function AutoFilterForm({
234
+ defs,
235
+ source,
236
+ labels
237
+ }) {
238
+ return /* @__PURE__ */ jsx(Stack, { gap: "sm", children: defs.map((def) => /* @__PURE__ */ jsx(
239
+ FilterControl,
240
+ {
241
+ def,
242
+ source,
243
+ labels
244
+ },
245
+ def.key
246
+ )) });
247
+ }
248
+ function BulkActionBar({
249
+ selection,
250
+ total,
251
+ bulkActions,
252
+ confirm,
253
+ labels
254
+ }) {
255
+ const { selectedIds, selectedCount, clear, allMatching } = selection;
256
+ const { pending, run } = useBulkActionRunner({
257
+ confirm,
258
+ cancelLabel: labels.cancel,
259
+ onComplete: clear
260
+ });
261
+ if (selectedCount === 0) return null;
262
+ const ids = [...selectedIds];
263
+ return /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
264
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", wrap: "wrap", gap: "sm", children: [
265
+ /* @__PURE__ */ jsx(Text, { fz: "sm", children: labels.selectedCount(selectedCount) }),
266
+ /* @__PURE__ */ jsxs(Group, { gap: "xs", wrap: "wrap", children: [
267
+ /* @__PURE__ */ jsx(
268
+ Button,
269
+ {
270
+ size: "xs",
271
+ variant: "subtle",
272
+ onClick: clear,
273
+ disabled: pending !== null,
274
+ children: labels.clearAll
275
+ }
276
+ ),
277
+ bulkActions.map((action) => /* @__PURE__ */ jsx(
278
+ BulkButton,
279
+ {
280
+ action,
281
+ ids,
282
+ pending,
283
+ onRun: (a) => {
284
+ if (allMatching) run(a, ids, { allMatching: true, total });
285
+ else run(a, ids);
286
+ }
287
+ },
288
+ action.key
289
+ ))
290
+ ] })
291
+ ] }),
292
+ /* @__PURE__ */ jsx(ScopeBanner, { selection, total, labels })
293
+ ] });
294
+ }
295
+ function ScopeBanner({
296
+ selection,
297
+ total,
298
+ labels
299
+ }) {
300
+ if (selection.headerState !== "all" || total <= selection.visibleIds.length) {
301
+ return null;
302
+ }
303
+ return /* @__PURE__ */ jsx(Group, { role: "status", gap: "xs", wrap: "wrap", children: selection.allMatching ? /* @__PURE__ */ jsxs(Fragment, { children: [
304
+ /* @__PURE__ */ jsx(Text, { fz: "sm", children: labels.allMatchingSelected(total) }),
305
+ /* @__PURE__ */ jsx(Button, { size: "xs", variant: "subtle", onClick: selection.clear, children: labels.clearAll })
306
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
307
+ /* @__PURE__ */ jsx(Text, { fz: "sm", children: labels.pageSelected(selection.selectedCount) }),
308
+ /* @__PURE__ */ jsx(
309
+ Button,
310
+ {
311
+ size: "xs",
312
+ variant: "light",
313
+ onClick: selection.selectAllMatching,
314
+ children: labels.selectAllMatching(total)
315
+ }
316
+ )
317
+ ] }) });
318
+ }
319
+ function BulkButton({
320
+ action,
321
+ ids,
322
+ pending,
323
+ onRun
324
+ }) {
325
+ const reason = resolveDisabledReason(action.disabledReason?.(ids));
326
+ const ineligible = reason !== void 0;
327
+ const button = /* @__PURE__ */ jsx(
328
+ Button,
329
+ {
330
+ size: "xs",
331
+ color: action.color,
332
+ leftSection: action.icon,
333
+ onClick: () => onRun(action),
334
+ loading: pending === action.key,
335
+ disabled: ineligible || pending !== null && pending !== action.key,
336
+ children: action.label
337
+ }
338
+ );
339
+ if (reason !== void 0) {
340
+ return /* @__PURE__ */ jsx(Tooltip, { label: reason, withArrow: true, openDelay: 150, children: /* @__PURE__ */ jsx("div", { children: button }) });
341
+ }
342
+ return button;
343
+ }
344
+ function RowVisibility({
345
+ hidden,
346
+ name,
347
+ labels,
348
+ onToggle
349
+ }) {
350
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
351
+ /* @__PURE__ */ jsx(
352
+ ActionIcon,
353
+ {
354
+ variant: hidden ? "subtle" : "light",
355
+ color: hidden ? "gray" : "blue",
356
+ size: "sm",
357
+ "aria-label": `${hidden ? labels.showColumn : labels.hideColumn}: ${name}`,
358
+ "aria-pressed": !hidden,
359
+ onClick: onToggle,
360
+ children: /* @__PURE__ */ jsx(EyeIcon, { off: hidden })
361
+ }
362
+ ),
363
+ /* @__PURE__ */ jsx(
364
+ Text,
365
+ {
366
+ size: "sm",
367
+ style: { flex: 1 },
368
+ c: hidden ? "dimmed" : void 0,
369
+ td: hidden ? "line-through" : void 0,
370
+ children: name
371
+ }
372
+ )
373
+ ] });
374
+ }
375
+ function PinToggle({
376
+ pinned,
377
+ label,
378
+ onClick
379
+ }) {
380
+ return /* @__PURE__ */ jsx(
381
+ ActionIcon,
382
+ {
383
+ variant: pinned ? "filled" : "subtle",
384
+ color: pinned ? "blue" : "gray",
385
+ size: "sm",
386
+ "aria-label": label,
387
+ onClick,
388
+ children: /* @__PURE__ */ jsx(PinIcon, {})
389
+ }
390
+ );
391
+ }
392
+ function ActionsRow({
393
+ layout,
394
+ labels
395
+ }) {
396
+ const hidden = layout.isHidden(ACTIONS_COLUMN_KEY);
397
+ const pinned = layout.state.pinned[ACTIONS_COLUMN_KEY] === "right";
398
+ return /* @__PURE__ */ jsxs(Group, { justify: "flex-start", wrap: "nowrap", gap: 6, px: 4, py: 2, children: [
399
+ /* @__PURE__ */ jsx(Box, { w: 22 }),
400
+ /* @__PURE__ */ jsx(
401
+ RowVisibility,
402
+ {
403
+ hidden,
404
+ name: labels.actions,
405
+ labels,
406
+ onToggle: () => layout.toggleVisible(ACTIONS_COLUMN_KEY)
407
+ }
408
+ ),
409
+ /* @__PURE__ */ jsx(
410
+ PinToggle,
411
+ {
412
+ pinned,
413
+ label: `${pinned ? labels.unpin : labels.pinRight}: ${labels.actions}`,
414
+ onClick: () => layout.setPinned(ACTIONS_COLUMN_KEY, pinned ? void 0 : "right")
415
+ }
416
+ )
417
+ ] });
418
+ }
419
+ function ColumnMenu({
420
+ allColumns,
421
+ layout,
422
+ labels,
423
+ hasRowActions = false
424
+ }) {
425
+ const drag = useColumnDragState();
426
+ return /* @__PURE__ */ jsxs(Menu, { closeOnItemClick: false, position: "bottom-end", withinPortal: true, children: [
427
+ /* @__PURE__ */ jsx(Menu.Target, { children: /* @__PURE__ */ jsx(Button, { variant: "default", size: "sm", children: labels.columns }) }),
428
+ /* @__PURE__ */ jsx(Menu.Dropdown, { children: /* @__PURE__ */ jsxs(Box, { p: 4, miw: 250, children: [
429
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", fw: 600, tt: "uppercase", px: 4, pb: 6, children: labels.columns }),
430
+ columnMenuRows(allColumns, layout).map((r) => {
431
+ const indicator = drag.rowAttrs(r.key, r.index);
432
+ const edge = indicator["data-drop"];
433
+ const edgeOffset = edge === "before" ? "2px" : "-2px";
434
+ return /* @__PURE__ */ jsxs(
435
+ Group,
436
+ {
437
+ justify: "flex-start",
438
+ wrap: "nowrap",
439
+ gap: 6,
440
+ px: 4,
441
+ py: 2,
442
+ style: {
443
+ cursor: "grab",
444
+ opacity: "data-dragging" in indicator ? 0.4 : void 0,
445
+ boxShadow: edge ? `inset 0 ${edgeOffset} 0 0 var(--mantine-primary-color-filled)` : void 0
446
+ },
447
+ ...drag.rowDragProps(r.key, r.index),
448
+ ...drag.dropProps(r.index, layout.move),
449
+ ...indicator,
450
+ children: [
451
+ /* @__PURE__ */ jsx(
452
+ ActionIcon,
453
+ {
454
+ variant: "subtle",
455
+ color: "gray",
456
+ size: "sm",
457
+ style: { cursor: "grab" },
458
+ ...columnReorderKeyProps(
459
+ r.key,
460
+ r.index,
461
+ layout.move,
462
+ `${labels.moveLeft} / ${labels.moveRight}: ${r.name}`
463
+ ),
464
+ children: /* @__PURE__ */ jsx(GripIcon, {})
465
+ }
466
+ ),
467
+ /* @__PURE__ */ jsx(
468
+ RowVisibility,
469
+ {
470
+ hidden: r.hidden,
471
+ name: r.name,
472
+ labels,
473
+ onToggle: () => layout.toggleVisible(r.key)
474
+ }
475
+ ),
476
+ /* @__PURE__ */ jsx(
477
+ PinToggle,
478
+ {
479
+ pinned: r.pinned !== void 0,
480
+ label: `${pinActionLabel(r.pinned, labels)}: ${r.name}`,
481
+ onClick: () => layout.setPinned(r.key, nextPinSide(r.pinned))
482
+ }
483
+ )
484
+ ]
485
+ },
486
+ r.key
487
+ );
488
+ }),
489
+ hasRowActions && /* @__PURE__ */ jsxs(Fragment, { children: [
490
+ /* @__PURE__ */ jsx(Menu.Divider, {}),
491
+ /* @__PURE__ */ jsx(ActionsRow, { layout, labels })
492
+ ] }),
493
+ /* @__PURE__ */ jsx(Menu.Divider, {}),
494
+ /* @__PURE__ */ jsx(
495
+ Button,
496
+ {
497
+ variant: "subtle",
498
+ size: "xs",
499
+ fullWidth: true,
500
+ justify: "flex-start",
501
+ onClick: () => layout.reset(),
502
+ children: labels.resetColumns
503
+ }
504
+ )
505
+ ] }) })
506
+ ] });
507
+ }
508
+
509
+ // src/density.ts
510
+ var DENSITY_SPACING = {
511
+ comfortable: { verticalSpacing: "sm", horizontalSpacing: "md" },
512
+ compact: { verticalSpacing: 4, horizontalSpacing: "sm" }
513
+ };
514
+ function Svg({
515
+ size = 16,
516
+ className,
517
+ style,
518
+ children
519
+ }) {
520
+ return /* @__PURE__ */ jsx(
521
+ "svg",
522
+ {
523
+ width: size,
524
+ height: size,
525
+ viewBox: "0 0 24 24",
526
+ fill: "none",
527
+ stroke: "currentColor",
528
+ strokeWidth: 2,
529
+ strokeLinecap: "round",
530
+ strokeLinejoin: "round",
531
+ className,
532
+ style,
533
+ "aria-hidden": "true",
534
+ focusable: "false",
535
+ children
536
+ }
537
+ );
538
+ }
539
+ var SearchIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
540
+ /* @__PURE__ */ jsx("circle", { cx: "11", cy: "11", r: "7" }),
541
+ /* @__PURE__ */ jsx("path", { d: "m21 21-4.3-4.3" })
542
+ ] });
543
+ var ChevronUpIcon = (p) => /* @__PURE__ */ jsx(Svg, { ...p, children: /* @__PURE__ */ jsx("path", { d: "m6 15 6-6 6 6" }) });
544
+ var ChevronDownIcon = (p) => /* @__PURE__ */ jsx(Svg, { ...p, children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" }) });
545
+ var ChevronRightIcon = (p) => /* @__PURE__ */ jsx(Svg, { ...p, children: /* @__PURE__ */ jsx("path", { d: "m9 6 6 6-6 6" }) });
546
+ var SelectorIcon = (p) => /* @__PURE__ */ jsx(Svg, { ...p, children: /* @__PURE__ */ jsx("path", { d: "m8 9 4-4 4 4M8 15l4 4 4-4" }) });
547
+ var CloseIcon = (p) => /* @__PURE__ */ jsx(Svg, { ...p, children: /* @__PURE__ */ jsx("path", { d: "M18 6 6 18M6 6l12 12" }) });
548
+ var FiltersIcon = (p) => /* @__PURE__ */ jsx(Svg, { ...p, children: /* @__PURE__ */ jsx("path", { d: "M4 6h16M7 12h10M10 18h4" }) });
549
+ var AlertIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
550
+ /* @__PURE__ */ jsx("path", { d: "M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z" }),
551
+ /* @__PURE__ */ jsx("path", { d: "M12 9v4M12 17h.01" })
552
+ ] });
553
+ var RefreshIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
554
+ /* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 1 1-3-6.7L21 8" }),
555
+ /* @__PURE__ */ jsx("path", { d: "M21 3v5h-5" })
556
+ ] });
557
+ var InboxIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
558
+ /* @__PURE__ */ jsx("path", { d: "M22 12h-6l-2 3h-4l-2-3H2" }),
559
+ /* @__PURE__ */ jsx("path", { d: "M5.5 5.1 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.5-6.9A2 2 0 0 0 16.8 4H7.2a2 2 0 0 0-1.7 1.1Z" })
560
+ ] });
561
+ function ExpandToggle({
562
+ expanded,
563
+ expandLabel,
564
+ collapseLabel,
565
+ onToggle
566
+ }) {
567
+ return /* @__PURE__ */ jsx(
568
+ ActionIcon,
569
+ {
570
+ variant: "subtle",
571
+ color: "gray",
572
+ size: "sm",
573
+ "aria-expanded": expanded,
574
+ "aria-label": expanded ? collapseLabel : expandLabel,
575
+ onClick: onToggle,
576
+ children: /* @__PURE__ */ jsx(
577
+ ChevronRightIcon,
578
+ {
579
+ size: 14,
580
+ style: {
581
+ transform: expanded ? "rotate(90deg)" : "rotate(0deg)",
582
+ transition: "transform 150ms ease"
583
+ }
584
+ }
585
+ )
586
+ }
587
+ );
588
+ }
589
+ var RESIZE_HANDLE_STYLE = {
590
+ position: "absolute",
591
+ insetInlineEnd: 0,
592
+ top: 0,
593
+ height: "100%",
594
+ width: 8,
595
+ cursor: "col-resize",
596
+ touchAction: "none",
597
+ userSelect: "none"
598
+ };
599
+ function SortIcon({
600
+ active,
601
+ dir
602
+ }) {
603
+ if (!active) return /* @__PURE__ */ jsx(SelectorIcon, { size: 12 });
604
+ return dir === "asc" ? /* @__PURE__ */ jsx(ChevronUpIcon, { size: 12 }) : /* @__PURE__ */ jsx(ChevronDownIcon, { size: 12 });
605
+ }
606
+ function HeaderCell({
607
+ table,
608
+ column,
609
+ stickyStyle,
610
+ resizeHandle
611
+ }) {
612
+ const cellProps = table.getHeaderCellProps(column);
613
+ const headerStyle = {
614
+ ...cellProps.style,
615
+ ...stickyStyle
616
+ };
617
+ if (!column.sortable) {
618
+ return /* @__PURE__ */ jsxs(Table.Th, { ...cellProps, style: headerStyle, children: [
619
+ column.header,
620
+ resizeHandle
621
+ ] });
622
+ }
623
+ const buttonProps = table.getSortButtonProps(column);
624
+ const sortIndex = buttonProps["data-sort-index"];
625
+ const level = table.source.sortLevels.find((l) => l.key === column.key);
626
+ const active = level !== void 0 || table.sortBy === column.key;
627
+ return /* @__PURE__ */ jsxs(Table.Th, { ...cellProps, style: headerStyle, children: [
628
+ /* @__PURE__ */ jsxs(
629
+ Group,
630
+ {
631
+ component: "button",
632
+ gap: 6,
633
+ wrap: "nowrap",
634
+ display: "inline-flex",
635
+ style: {
636
+ background: "none",
637
+ border: 0,
638
+ cursor: "pointer",
639
+ font: "inherit",
640
+ padding: 0,
641
+ color: active ? "var(--mantine-primary-color-filled)" : "inherit"
642
+ },
643
+ ...buttonProps,
644
+ children: [
645
+ /* @__PURE__ */ jsx("span", { children: column.header }),
646
+ /* @__PURE__ */ jsx(SortIcon, { active, dir: level?.dir ?? table.sortDir }),
647
+ typeof sortIndex === "number" && /* @__PURE__ */ jsx(Badge, { component: "span", size: "xs", variant: "light", children: sortIndex })
648
+ ]
649
+ }
650
+ ),
651
+ resizeHandle
652
+ ] });
653
+ }
654
+ function RowActions({
655
+ row,
656
+ actions,
657
+ confirm,
658
+ cancelLabel
659
+ }) {
660
+ return /* @__PURE__ */ jsx(Group, { gap: 4, justify: "flex-end", wrap: "nowrap", children: actions.map((action) => {
661
+ if (action.isHidden?.(row)) return null;
662
+ const reason = resolveDisabledReason(action.disabledReason?.(row));
663
+ const disabled = reason !== void 0 || (action.isDisabled?.(row) ?? false);
664
+ const handleClick = disabled ? void 0 : (e) => {
665
+ e.stopPropagation();
666
+ runRowAction(action, row, confirm, cancelLabel);
667
+ };
668
+ return action.icon ? /* @__PURE__ */ jsx(
669
+ Tooltip,
670
+ {
671
+ label: reason ?? action.label,
672
+ withArrow: true,
673
+ openDelay: 200,
674
+ children: /* @__PURE__ */ jsx(
675
+ ActionIcon,
676
+ {
677
+ variant: "subtle",
678
+ color: action.color,
679
+ size: "sm",
680
+ disabled,
681
+ "aria-label": action.label,
682
+ onClick: handleClick,
683
+ children: action.icon
684
+ }
685
+ )
686
+ },
687
+ action.key
688
+ ) : /* @__PURE__ */ jsx(
689
+ Button,
690
+ {
691
+ variant: "subtle",
692
+ color: action.color,
693
+ size: "compact-sm",
694
+ disabled,
695
+ onClick: handleClick,
696
+ children: action.label
697
+ },
698
+ action.key
699
+ );
700
+ }) });
701
+ }
702
+ var COMPARED_ROW_PROPS = [
703
+ "row",
704
+ "index",
705
+ "id",
706
+ "columns",
707
+ "getCellProps",
708
+ "selected",
709
+ "selectLabel",
710
+ "onToggleSelect",
711
+ "expanded",
712
+ "expandLabel",
713
+ "collapseLabel",
714
+ "onToggleExpand",
715
+ "renderRowDetail",
716
+ "columnSpan",
717
+ "rowActions",
718
+ "confirm",
719
+ "cancelLabel",
720
+ "onRowClick",
721
+ "prefetch",
722
+ "className",
723
+ "measureElement",
724
+ "pinSignature"
725
+ ];
726
+ function desktopRowPropsEqual(prev, next) {
727
+ return COMPARED_ROW_PROPS.every((key) => Object.is(prev[key], next[key]));
728
+ }
729
+ function leadingPinStyle(active, inset, zIndex, background) {
730
+ if (!active) return void 0;
731
+ const style = pinnedCellStyle({ side: "left", inset }, zIndex);
732
+ return background ? { ...style, background } : style;
733
+ }
734
+ function pinLayoutSignature(columns, pinOffset, hasLeftPin, actionsEdgePinned) {
735
+ const perColumn = columns.map((column) => {
736
+ const pin = pinOffset?.(column.key);
737
+ return pin ? `${column.key}:${pin.side}${pin.inset}` : column.key;
738
+ });
739
+ return `${perColumn.join("|")}|${String(hasLeftPin)}|${String(actionsEdgePinned)}`;
740
+ }
741
+ function DesktopRowBase({
742
+ row,
743
+ index,
744
+ id,
745
+ columns,
746
+ getCellProps,
747
+ selected,
748
+ selectLabel,
749
+ onToggleSelect,
750
+ expanded,
751
+ expandLabel,
752
+ collapseLabel,
753
+ onToggleExpand,
754
+ renderRowDetail,
755
+ columnSpan,
756
+ rowActions,
757
+ confirm,
758
+ cancelLabel,
759
+ onRowClick,
760
+ prefetch,
761
+ className,
762
+ measureElement,
763
+ pinStyleFor,
764
+ selectionCellStyle,
765
+ expansionCellStyle,
766
+ actionsCellStyle
767
+ }) {
768
+ const showActions = (rowActions?.length ?? 0) > 0;
769
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
770
+ /* @__PURE__ */ jsxs(
771
+ Table.Tr,
772
+ {
773
+ role: "row",
774
+ "data-index": index,
775
+ "aria-selected": selected,
776
+ ...rowClickProps(row, onRowClick),
777
+ className,
778
+ ref: measureElement,
779
+ "data-stagger": "",
780
+ onMouseEnter: prefetch ? () => prefetch(row) : void 0,
781
+ children: [
782
+ expanded !== void 0 && /* @__PURE__ */ jsx(Table.Td, { ta: "center", style: expansionCellStyle, children: /* @__PURE__ */ jsx(
783
+ ExpandToggle,
784
+ {
785
+ expanded,
786
+ expandLabel,
787
+ collapseLabel,
788
+ onToggle: () => onToggleExpand(id)
789
+ }
790
+ ) }),
791
+ selected !== void 0 && /* @__PURE__ */ jsx(Table.Td, { ta: "center", style: selectionCellStyle, children: /* @__PURE__ */ jsx(
792
+ Checkbox,
793
+ {
794
+ "aria-label": selectLabel,
795
+ checked: selected,
796
+ onChange: () => onToggleSelect(id)
797
+ }
798
+ ) }),
799
+ columns.map((column) => /* @__PURE__ */ jsx(
800
+ Table.Td,
801
+ {
802
+ ...getCellProps(column),
803
+ style: pinStyleFor(column.key),
804
+ children: column.Cell ? /* @__PURE__ */ jsx(column.Cell, { row, rowIndex: index }) : column.accessor?.(row)
805
+ },
806
+ column.key
807
+ )),
808
+ showActions && /* @__PURE__ */ jsx(Table.Td, { ta: "end", style: actionsCellStyle, children: /* @__PURE__ */ jsx(
809
+ RowActions,
810
+ {
811
+ row,
812
+ actions: rowActions,
813
+ confirm,
814
+ cancelLabel
815
+ }
816
+ ) })
817
+ ]
818
+ }
819
+ ),
820
+ expanded === true && /* @__PURE__ */ jsx(Table.Tr, { children: /* @__PURE__ */ jsx(Table.Td, { colSpan: columnSpan, children: renderRowDetail(row) }) })
821
+ ] });
822
+ }
823
+ function DesktopTable({
824
+ table,
825
+ rows,
826
+ rowActions,
827
+ confirm,
828
+ prefetch,
829
+ onRowClick,
830
+ rowClassName,
831
+ renderRowDetail,
832
+ summaryRow,
833
+ expansion,
834
+ getRowId,
835
+ bodyRef,
836
+ className,
837
+ rowEntries,
838
+ paddingTop = 0,
839
+ paddingBottom = 0,
840
+ measureElement,
841
+ stickyHeaderOffset = 0,
842
+ stickyHeader = false,
843
+ pinOffset,
844
+ maxHeight,
845
+ virtualScrollRef,
846
+ setWidth,
847
+ columnWidths,
848
+ resizeLabel = "Resize column",
849
+ actionsPinned = false,
850
+ density = "comfortable"
851
+ }) {
852
+ const { columns, selection, labels, showActions, entries, columnSpan } = tableRenderModel({
853
+ table,
854
+ rows,
855
+ rowActions,
856
+ getRowId,
857
+ rowEntries,
858
+ renderRowDetail,
859
+ expansion
860
+ });
861
+ const expandable = expansion !== void 0;
862
+ const groupCells = headerGroupRow(columns);
863
+ const summaryCells = summaryRow?.(rows);
864
+ const hasRightPin = table.columns.some(
865
+ (c) => pinOffset?.(c.key)?.side === "right"
866
+ );
867
+ const actionsEdgePinned = showActions && (hasRightPin || actionsPinned);
868
+ const hasPinned = table.columns.some((c) => pinOffset?.(c.key) != null) || actionsEdgePinned;
869
+ const { ref: wrapperRef, overflowing } = useHorizontalOverflow();
870
+ const inScrollBox = maxHeight != null || hasPinned || overflowing;
871
+ const headerCellStyle = stickyHeader ? {
872
+ position: "sticky",
873
+ top: inScrollBox ? 0 : stickyHeaderOffset,
874
+ zIndex: PIN_Z.header,
875
+ background: "var(--mantine-color-body)",
876
+ boxShadow: "0 1px 0 var(--mantine-color-default-border)"
877
+ } : { background: "var(--mantine-color-body)" };
878
+ const expansionWidth = 36;
879
+ const selectionWidth = 40;
880
+ const actionsWidth = 120;
881
+ const expansionLead = expandable ? expansionWidth : 0;
882
+ const leads = {
883
+ left: expansionLead + (selection ? selectionWidth : 0),
884
+ right: showActions ? actionsWidth : 0
885
+ };
886
+ const hasLeftPin = table.columns.some(
887
+ (c) => pinOffset?.(c.key)?.side === "left"
888
+ );
889
+ const pinBg = "var(--mantine-color-body)";
890
+ const headerStyleFor = (column) => {
891
+ const key = column.key;
892
+ const pin = pinnedCellStyle(pinOffset?.(key), PIN_Z.headerPinned, leads);
893
+ const merged = {
894
+ ...headerCellStyle,
895
+ ...pin,
896
+ // A pinned column renders at the same width its sticky inset assumed,
897
+ // so stacked pins stay flush even with no declared width.
898
+ width: pin ? pinnedColumnWidth(column, columnWidths) : columnWidths?.[key]
899
+ };
900
+ if (setWidth && !merged.position) merged.position = "relative";
901
+ return merged;
902
+ };
903
+ const expansionHeaderStyle = {
904
+ ...headerCellStyle,
905
+ ...leadingPinStyle(hasLeftPin, 0, PIN_Z.headerPinned)
906
+ };
907
+ const selectionHeaderStyle = {
908
+ ...headerCellStyle,
909
+ ...leadingPinStyle(hasLeftPin, expansionLead, PIN_Z.headerPinned)
910
+ };
911
+ const actionsHeaderStyle = {
912
+ ...headerCellStyle,
913
+ ...edgePinStyle("right", actionsEdgePinned, PIN_Z.headerPinned)
914
+ };
915
+ const edgeBodyStyle = (side, active) => {
916
+ const pin = edgePinStyle(side, active, PIN_Z.body);
917
+ return pin ? { ...pin, background: pinBg } : void 0;
918
+ };
919
+ const expansionCellStyle = leadingPinStyle(hasLeftPin, 0, PIN_Z.body, pinBg);
920
+ const selectionCellStyle = leadingPinStyle(
921
+ hasLeftPin,
922
+ expansionLead,
923
+ PIN_Z.body,
924
+ pinBg
925
+ );
926
+ const actionsCellStyle = edgeBodyStyle("right", actionsEdgePinned);
927
+ const columnName = (column) => typeof column.header === "string" ? column.header : column.key;
928
+ const resizeHandleFor = (column) => setWidth ? /* @__PURE__ */ jsx(
929
+ "span",
930
+ {
931
+ ...columnResizeHandleProps(
932
+ column.key,
933
+ setWidth,
934
+ `${resizeLabel}: ${columnName(column)}`
935
+ ),
936
+ style: RESIZE_HANDLE_STYLE
937
+ }
938
+ ) : void 0;
939
+ const bodyPinStyle = (key) => {
940
+ const pin = pinnedCellStyle(pinOffset?.(key), PIN_Z.body, leads);
941
+ return pin ? { ...pin, background: pinBg } : void 0;
942
+ };
943
+ const { verticalSpacing, horizontalSpacing } = DENSITY_SPACING[density];
944
+ const minWidth = tableMinWidth(columns, {
945
+ widths: columnWidths,
946
+ extra: expansionLead + (selection ? 40 : 0) + (showActions ? 120 : 0)
947
+ });
948
+ const selectionRef = useRef(selection);
949
+ selectionRef.current = selection;
950
+ const toggleSelect = useCallback(
951
+ (id) => selectionRef.current.toggle(id),
952
+ []
953
+ );
954
+ const Row = useMemo(
955
+ () => memo(DesktopRowBase, desktopRowPropsEqual),
956
+ []
957
+ );
958
+ const pinSignature = pinLayoutSignature(
959
+ columns,
960
+ pinOffset,
961
+ hasLeftPin,
962
+ actionsEdgePinned
963
+ );
964
+ const wrapperStyle = maxHeight == null ? {
965
+ width: "100%",
966
+ ...hasPinned || overflowing ? { overflowX: "auto" } : {}
967
+ } : { width: "100%", maxHeight, overflow: "auto" };
968
+ return /* @__PURE__ */ jsx(
969
+ "div",
970
+ {
971
+ ref: (node) => {
972
+ wrapperRef(node);
973
+ virtualScrollRef?.(node);
974
+ },
975
+ style: wrapperStyle,
976
+ children: /* @__PURE__ */ jsxs(
977
+ Table,
978
+ {
979
+ ...table.getTableProps(),
980
+ className,
981
+ highlightOnHover: true,
982
+ verticalSpacing,
983
+ horizontalSpacing,
984
+ miw: Math.max(480, minWidth),
985
+ children: [
986
+ /* @__PURE__ */ jsxs(Table.Thead, { style: { background: "var(--mantine-color-body)" }, children: [
987
+ groupCells && /* @__PURE__ */ jsxs(Table.Tr, { children: [
988
+ expandable && /* @__PURE__ */ jsx(Table.Th, {}),
989
+ selection && /* @__PURE__ */ jsx(Table.Th, {}),
990
+ groupCells.map((cell) => /* @__PURE__ */ jsx(
991
+ Table.Th,
992
+ {
993
+ colSpan: cell.span,
994
+ ta: "center",
995
+ fw: 600,
996
+ style: {
997
+ borderBottom: "1px solid var(--mantine-color-default-border)"
998
+ },
999
+ children: cell.label
1000
+ },
1001
+ cell.key
1002
+ )),
1003
+ showActions && /* @__PURE__ */ jsx(Table.Th, {})
1004
+ ] }),
1005
+ /* @__PURE__ */ jsxs(Table.Tr, { ...table.getHeaderRowProps(), children: [
1006
+ expandable && /* @__PURE__ */ jsx(
1007
+ Table.Th,
1008
+ {
1009
+ w: expansionWidth,
1010
+ ta: "center",
1011
+ style: expansionHeaderStyle,
1012
+ children: /* @__PURE__ */ jsx(VisuallyHidden, { children: labels.expandRow })
1013
+ }
1014
+ ),
1015
+ selection && /* @__PURE__ */ jsx(
1016
+ Table.Th,
1017
+ {
1018
+ w: selectionWidth,
1019
+ ta: "center",
1020
+ style: selectionHeaderStyle,
1021
+ children: /* @__PURE__ */ jsx(
1022
+ Checkbox,
1023
+ {
1024
+ "aria-label": labels.selectAll,
1025
+ checked: selection.headerState === "all",
1026
+ indeterminate: selection.headerState === "some",
1027
+ onChange: selection.toggleAll
1028
+ }
1029
+ )
1030
+ }
1031
+ ),
1032
+ columns.map((column) => /* @__PURE__ */ jsx(
1033
+ HeaderCell,
1034
+ {
1035
+ table,
1036
+ column,
1037
+ stickyStyle: headerStyleFor(column),
1038
+ resizeHandle: resizeHandleFor(column)
1039
+ },
1040
+ column.key
1041
+ )),
1042
+ showActions && /* @__PURE__ */ jsx(Table.Th, { ta: "end", w: actionsWidth, style: actionsHeaderStyle, children: labels.actions })
1043
+ ] })
1044
+ ] }),
1045
+ /* @__PURE__ */ jsxs(Table.Tbody, { ref: bodyRef, children: [
1046
+ paddingTop > 0 && /* @__PURE__ */ jsx(Table.Tr, { "aria-hidden": true, children: /* @__PURE__ */ jsx(
1047
+ Table.Td,
1048
+ {
1049
+ colSpan: columnSpan,
1050
+ style: { height: paddingTop, padding: 0 }
1051
+ }
1052
+ ) }),
1053
+ entries.map(({ row, index, key }) => {
1054
+ const id = getRowId(row);
1055
+ return /* @__PURE__ */ jsx(
1056
+ Row,
1057
+ {
1058
+ row,
1059
+ index,
1060
+ id,
1061
+ columns,
1062
+ getCellProps: table.getCellProps,
1063
+ selected: selection?.isSelected(id),
1064
+ selectLabel: labels.selectRow,
1065
+ onToggleSelect: toggleSelect,
1066
+ expanded: expansion?.isExpanded(id),
1067
+ expandLabel: labels.expandRow,
1068
+ collapseLabel: labels.collapseRow,
1069
+ onToggleExpand: expansion?.toggle,
1070
+ renderRowDetail,
1071
+ columnSpan,
1072
+ rowActions,
1073
+ confirm,
1074
+ cancelLabel: labels.cancel,
1075
+ onRowClick,
1076
+ prefetch,
1077
+ className: rowClassName?.(row, index),
1078
+ measureElement,
1079
+ pinStyleFor: bodyPinStyle,
1080
+ selectionCellStyle,
1081
+ expansionCellStyle,
1082
+ actionsCellStyle,
1083
+ pinSignature
1084
+ },
1085
+ key
1086
+ );
1087
+ }),
1088
+ paddingBottom > 0 && /* @__PURE__ */ jsx(Table.Tr, { "aria-hidden": true, children: /* @__PURE__ */ jsx(
1089
+ Table.Td,
1090
+ {
1091
+ colSpan: columnSpan,
1092
+ style: { height: paddingBottom, padding: 0 }
1093
+ }
1094
+ ) })
1095
+ ] }),
1096
+ summaryCells && /* @__PURE__ */ jsx(Table.Tfoot, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
1097
+ expandable && /* @__PURE__ */ jsx(Table.Td, {}),
1098
+ selection && /* @__PURE__ */ jsx(Table.Td, {}),
1099
+ columns.map((column) => /* @__PURE__ */ jsx(
1100
+ Table.Td,
1101
+ {
1102
+ ...table.getCellProps(column),
1103
+ fw: 600,
1104
+ c: "dimmed",
1105
+ children: summaryCells[column.key]
1106
+ },
1107
+ column.key
1108
+ )),
1109
+ showActions && /* @__PURE__ */ jsx(Table.Td, {})
1110
+ ] }) })
1111
+ ]
1112
+ }
1113
+ )
1114
+ }
1115
+ );
1116
+ }
1117
+ function EmptyState({
1118
+ title,
1119
+ description,
1120
+ icon,
1121
+ action
1122
+ }) {
1123
+ return /* @__PURE__ */ jsxs(
1124
+ Stack,
1125
+ {
1126
+ role: "status",
1127
+ align: "center",
1128
+ justify: "center",
1129
+ gap: 6,
1130
+ py: 48,
1131
+ px: 16,
1132
+ children: [
1133
+ /* @__PURE__ */ jsx(Text, { c: "dimmed", "aria-hidden": true, children: icon ?? /* @__PURE__ */ jsx(InboxIcon, { size: 40 }) }),
1134
+ /* @__PURE__ */ jsx(Text, { fw: 600, fz: "md", children: title }),
1135
+ description && /* @__PURE__ */ jsx(Text, { c: "dimmed", fz: "sm", ta: "center", maw: 360, children: description }),
1136
+ action
1137
+ ]
1138
+ }
1139
+ );
1140
+ }
1141
+ function ErrorState({
1142
+ error,
1143
+ title,
1144
+ message,
1145
+ retryLabel,
1146
+ onRetry,
1147
+ isRetrying
1148
+ }) {
1149
+ return /* @__PURE__ */ jsx(
1150
+ Alert,
1151
+ {
1152
+ icon: /* @__PURE__ */ jsx(AlertIcon, { size: 16 }),
1153
+ color: "red",
1154
+ variant: "light",
1155
+ title,
1156
+ children: /* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "center", wrap: "nowrap", gap: "md", children: [
1157
+ /* @__PURE__ */ jsxs("div", { children: [
1158
+ /* @__PURE__ */ jsx(Text, { fz: "sm", children: message }),
1159
+ /* @__PURE__ */ jsx(Text, { fz: "xs", c: "dimmed", mt: 2, children: error.message })
1160
+ ] }),
1161
+ onRetry && /* @__PURE__ */ jsx(
1162
+ Button,
1163
+ {
1164
+ size: "xs",
1165
+ variant: "light",
1166
+ color: "red",
1167
+ leftSection: /* @__PURE__ */ jsx(RefreshIcon, { size: 14 }),
1168
+ onClick: onRetry,
1169
+ loading: isRetrying,
1170
+ children: retryLabel
1171
+ }
1172
+ )
1173
+ ] })
1174
+ }
1175
+ );
1176
+ }
1177
+ function FilterDrawer({
1178
+ opened,
1179
+ onClose,
1180
+ filters,
1181
+ activeFilterCount,
1182
+ onClearFilters,
1183
+ labels,
1184
+ dir = "ltr"
1185
+ }) {
1186
+ return /* @__PURE__ */ jsx(
1187
+ Drawer,
1188
+ {
1189
+ opened,
1190
+ onClose,
1191
+ position: dir === "rtl" ? "left" : "right",
1192
+ size: 380,
1193
+ title: labels.filters,
1194
+ overlayProps: { opacity: 0.4, blur: 2 },
1195
+ closeButtonProps: { "aria-label": labels.cancel },
1196
+ children: /* @__PURE__ */ jsxs(Stack, { gap: "md", mih: "60vh", justify: "space-between", children: [
1197
+ /* @__PURE__ */ jsx(Stack, { gap: "md", children: filters }),
1198
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", pt: "md", children: [
1199
+ /* @__PURE__ */ jsx(
1200
+ Button,
1201
+ {
1202
+ variant: "subtle",
1203
+ onClick: onClearFilters,
1204
+ disabled: activeFilterCount === 0,
1205
+ children: labels.clearAll
1206
+ }
1207
+ ),
1208
+ /* @__PURE__ */ jsx(Button, { onClick: onClose, children: labels.applyFilters })
1209
+ ] })
1210
+ ] })
1211
+ }
1212
+ );
1213
+ }
1214
+ function mobileLabel(column) {
1215
+ return column.mobileLabel ?? (typeof column.header === "string" ? column.header : column.key);
1216
+ }
1217
+ function MobileCards({
1218
+ table,
1219
+ rows,
1220
+ rowActions,
1221
+ confirm,
1222
+ getRowId,
1223
+ bodyRef,
1224
+ className,
1225
+ rowEntries,
1226
+ paddingTop = 0,
1227
+ paddingBottom = 0,
1228
+ measureElement,
1229
+ density = "comfortable",
1230
+ onRowClick,
1231
+ rowClassName,
1232
+ renderRowDetail,
1233
+ summaryRow,
1234
+ expansion
1235
+ }) {
1236
+ const { columns, selection, labels } = table;
1237
+ const compact = density === "compact";
1238
+ const cardPadding = compact ? "sm" : "md";
1239
+ const cardGap = compact ? 4 : "xs";
1240
+ const entries = rowEntries ?? rows.map((row, index) => ({
1241
+ row,
1242
+ index,
1243
+ key: getRowId(row)
1244
+ }));
1245
+ const summaryCells = summaryRow?.(rows);
1246
+ return /* @__PURE__ */ jsxs(
1247
+ Stack,
1248
+ {
1249
+ gap: compact ? "xs" : "sm",
1250
+ ref: bodyRef,
1251
+ className,
1252
+ ...table.getTableProps({ role: "list" }),
1253
+ children: [
1254
+ paddingTop > 0 && /* @__PURE__ */ jsx("div", { "aria-hidden": true, style: { height: paddingTop } }),
1255
+ entries.map(({ row, index, key }) => {
1256
+ const id = getRowId(row);
1257
+ return /* @__PURE__ */ jsx(
1258
+ Card,
1259
+ {
1260
+ ...rowClickProps(row, onRowClick),
1261
+ className: rowClassName?.(row, index),
1262
+ ref: measureElement,
1263
+ "data-index": index,
1264
+ withBorder: true,
1265
+ radius: "md",
1266
+ padding: cardPadding,
1267
+ role: "listitem",
1268
+ "data-stagger": "",
1269
+ children: /* @__PURE__ */ jsxs(Stack, { gap: cardGap, children: [
1270
+ selection && /* @__PURE__ */ jsx(
1271
+ Checkbox,
1272
+ {
1273
+ "aria-label": labels.selectRow,
1274
+ checked: selection.isSelected(id),
1275
+ onChange: () => selection.toggle(id)
1276
+ }
1277
+ ),
1278
+ expansion && /* @__PURE__ */ jsx(Group, { justify: "flex-end", children: /* @__PURE__ */ jsx(
1279
+ ExpandToggle,
1280
+ {
1281
+ expanded: expansion.isExpanded(id),
1282
+ expandLabel: labels.expandRow,
1283
+ collapseLabel: labels.collapseRow,
1284
+ onToggle: () => expansion.toggle(id)
1285
+ }
1286
+ ) }),
1287
+ columns.map((column) => /* @__PURE__ */ jsxs("div", { children: [
1288
+ /* @__PURE__ */ jsx(Text, { fz: "xs", c: "dimmed", tt: "uppercase", fw: 500, children: mobileLabel(column) }),
1289
+ /* @__PURE__ */ jsx(Text, { component: "div", fz: "sm", children: column.Cell ? /* @__PURE__ */ jsx(column.Cell, { row, rowIndex: index }) : column.accessor?.(row) })
1290
+ ] }, column.key)),
1291
+ expansion?.isExpanded(id) === true && /* @__PURE__ */ jsx("div", { children: renderRowDetail(row) }),
1292
+ rowActions && rowActions.length > 0 && /* @__PURE__ */ jsx(Group, { gap: 4, justify: "flex-end", pt: 4, children: rowActions.map((action) => {
1293
+ if (action.isHidden?.(row)) return null;
1294
+ const reason = resolveDisabledReason(
1295
+ action.disabledReason?.(row)
1296
+ );
1297
+ const disabled = reason !== void 0 || (action.isDisabled?.(row) ?? false);
1298
+ const run = disabled ? void 0 : () => runRowAction(action, row, confirm, labels.cancel);
1299
+ return action.icon ? /* @__PURE__ */ jsx(
1300
+ Tooltip,
1301
+ {
1302
+ label: reason ?? action.label,
1303
+ withArrow: true,
1304
+ openDelay: 200,
1305
+ children: /* @__PURE__ */ jsx(
1306
+ ActionIcon,
1307
+ {
1308
+ variant: "subtle",
1309
+ color: action.color,
1310
+ size: "sm",
1311
+ disabled,
1312
+ "aria-label": action.label,
1313
+ onClick: run,
1314
+ children: action.icon
1315
+ }
1316
+ )
1317
+ },
1318
+ action.key
1319
+ ) : /* @__PURE__ */ jsx(
1320
+ Button,
1321
+ {
1322
+ variant: "subtle",
1323
+ color: action.color,
1324
+ size: "compact-sm",
1325
+ disabled,
1326
+ onClick: run,
1327
+ children: action.label
1328
+ },
1329
+ action.key
1330
+ );
1331
+ }) })
1332
+ ] })
1333
+ },
1334
+ key
1335
+ );
1336
+ }),
1337
+ paddingBottom > 0 && /* @__PURE__ */ jsx("div", { "aria-hidden": true, style: { height: paddingBottom } }),
1338
+ summaryCells && /* @__PURE__ */ jsx(Card, { withBorder: true, radius: "md", padding: cardPadding, role: "listitem", children: /* @__PURE__ */ jsx(Stack, { gap: cardGap, children: columns.filter((column) => summaryCells[column.key] !== void 0).map((column) => /* @__PURE__ */ jsxs("div", { children: [
1339
+ /* @__PURE__ */ jsx(Text, { fz: "xs", c: "dimmed", tt: "uppercase", fw: 500, children: mobileLabel(column) }),
1340
+ /* @__PURE__ */ jsx(Text, { component: "div", fz: "sm", fw: 600, children: summaryCells[column.key] })
1341
+ ] }, column.key)) }) })
1342
+ ]
1343
+ }
1344
+ );
1345
+ }
1346
+ function PaginationFooter({
1347
+ page,
1348
+ totalPages,
1349
+ limit,
1350
+ total,
1351
+ fromIndex,
1352
+ toIndex,
1353
+ onPageChange,
1354
+ onLimitChange,
1355
+ labels
1356
+ }) {
1357
+ const safeTotalPages = Math.max(totalPages, 1);
1358
+ const safePage = Math.min(Math.max(page, 1), safeTotalPages);
1359
+ const options = pageSizeOptions(limit).map((n) => ({
1360
+ value: String(n),
1361
+ label: String(n)
1362
+ }));
1363
+ return /* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "center", wrap: "wrap", gap: "md", pt: "xs", children: [
1364
+ /* @__PURE__ */ jsxs(Group, { gap: "xs", align: "center", wrap: "nowrap", children: [
1365
+ /* @__PURE__ */ jsx(Text, { fz: "xs", c: "dimmed", children: labels.rowsPerPage }),
1366
+ /* @__PURE__ */ jsx(
1367
+ Select,
1368
+ {
1369
+ "aria-label": labels.rowsPerPage,
1370
+ data: options,
1371
+ value: String(limit),
1372
+ onChange: (v) => onLimitChange(Number(v)),
1373
+ size: "xs",
1374
+ w: 76,
1375
+ allowDeselect: false,
1376
+ comboboxProps: { withinPortal: false }
1377
+ }
1378
+ ),
1379
+ total > 0 && /* @__PURE__ */ jsx(Text, { fz: "xs", c: "dimmed", children: labels.showing({ from: fromIndex, to: toIndex, total }) })
1380
+ ] }),
1381
+ /* @__PURE__ */ jsxs(Group, { gap: "sm", align: "center", wrap: "nowrap", children: [
1382
+ /* @__PURE__ */ jsx(Text, { fz: "xs", c: "dimmed", children: labels.pageOf({ page: safePage, total: safeTotalPages }) }),
1383
+ /* @__PURE__ */ jsx(
1384
+ Pagination,
1385
+ {
1386
+ total: safeTotalPages,
1387
+ value: safePage,
1388
+ onChange: onPageChange,
1389
+ size: "sm",
1390
+ siblings: 1,
1391
+ boundaries: 1,
1392
+ getControlProps: (control) => ({
1393
+ "aria-label": control === "previous" ? labels.previousPage : labels.nextPage
1394
+ })
1395
+ }
1396
+ )
1397
+ ] })
1398
+ ] });
1399
+ }
1400
+ function SavedViewsMenu({
1401
+ views,
1402
+ labels
1403
+ }) {
1404
+ const [name, setName] = useState("");
1405
+ const trimmed = name.trim();
1406
+ const handleSave = () => {
1407
+ views.save(trimmed);
1408
+ setName("");
1409
+ };
1410
+ return /* @__PURE__ */ jsxs(Menu, { closeOnItemClick: false, position: "bottom-end", withinPortal: true, children: [
1411
+ /* @__PURE__ */ jsx(Menu.Target, { children: /* @__PURE__ */ jsx(Button, { variant: "default", size: "sm", children: labels.savedViews }) }),
1412
+ /* @__PURE__ */ jsx(Menu.Dropdown, { children: /* @__PURE__ */ jsxs(Box, { p: 4, miw: 220, children: [
1413
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", fw: 600, tt: "uppercase", px: 4, pb: 6, children: labels.savedViews }),
1414
+ views.views.map((view) => /* @__PURE__ */ jsxs(Group, { gap: 6, px: 4, py: 2, wrap: "nowrap", children: [
1415
+ /* @__PURE__ */ jsx(
1416
+ Button,
1417
+ {
1418
+ variant: "subtle",
1419
+ size: "compact-sm",
1420
+ justify: "flex-start",
1421
+ style: { flex: 1 },
1422
+ onClick: () => views.apply(view.name),
1423
+ children: view.name
1424
+ }
1425
+ ),
1426
+ /* @__PURE__ */ jsx(
1427
+ ActionIcon,
1428
+ {
1429
+ variant: "subtle",
1430
+ color: "gray",
1431
+ size: "sm",
1432
+ "aria-label": `${labels.deleteView}: ${view.name}`,
1433
+ onClick: () => views.remove(view.name),
1434
+ children: /* @__PURE__ */ jsx(CloseIcon, { size: 12 })
1435
+ }
1436
+ )
1437
+ ] }, view.name)),
1438
+ /* @__PURE__ */ jsx(Menu.Divider, {}),
1439
+ /* @__PURE__ */ jsxs(Group, { gap: 6, p: 4, wrap: "nowrap", children: [
1440
+ /* @__PURE__ */ jsx(
1441
+ TextInput,
1442
+ {
1443
+ size: "xs",
1444
+ style: { flex: 1 },
1445
+ placeholder: labels.viewName,
1446
+ value: name,
1447
+ onChange: (e) => setName(e.currentTarget.value)
1448
+ }
1449
+ ),
1450
+ /* @__PURE__ */ jsx(Button, { size: "xs", disabled: trimmed === "", onClick: handleSave, children: labels.saveView })
1451
+ ] })
1452
+ ] }) })
1453
+ ] });
1454
+ }
1455
+ function TableSkeleton({
1456
+ columns,
1457
+ rows = 5,
1458
+ loadingLabel
1459
+ }) {
1460
+ const colKeys = Array.from({ length: Math.max(columns, 1) }, (_, i) => i);
1461
+ const rowKeys = Array.from({ length: rows }, (_, i) => i);
1462
+ return /* @__PURE__ */ jsxs("div", { role: "status", "aria-busy": "true", "aria-live": "polite", children: [
1463
+ /* @__PURE__ */ jsxs(Table, { children: [
1464
+ /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsx(Table.Tr, { children: colKeys.map((c) => /* @__PURE__ */ jsx(Table.Th, { children: /* @__PURE__ */ jsx(
1465
+ Skeleton,
1466
+ {
1467
+ height: 12,
1468
+ radius: "sm",
1469
+ width: c === 0 ? "55%" : "40%"
1470
+ }
1471
+ ) }, c)) }) }),
1472
+ /* @__PURE__ */ jsx(Table.Tbody, { children: rowKeys.map((r) => /* @__PURE__ */ jsx(Table.Tr, { children: colKeys.map((c) => /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(
1473
+ Skeleton,
1474
+ {
1475
+ height: 14,
1476
+ radius: "sm",
1477
+ width: c === 0 ? "70%" : "55%"
1478
+ }
1479
+ ) }, c)) }, r)) })
1480
+ ] }),
1481
+ loadingLabel ? /* @__PURE__ */ jsx(VisuallyHidden, { children: loadingLabel }) : null
1482
+ ] });
1483
+ }
1484
+ function FilterPopover({
1485
+ open,
1486
+ onClose,
1487
+ filters,
1488
+ activeFilterCount,
1489
+ onClearFilters,
1490
+ labels,
1491
+ dir = "ltr",
1492
+ children
1493
+ }) {
1494
+ return /* @__PURE__ */ jsxs(
1495
+ Popover,
1496
+ {
1497
+ opened: open,
1498
+ onDismiss: onClose,
1499
+ position: dir === "rtl" ? "bottom-start" : "bottom-end",
1500
+ withinPortal: true,
1501
+ shadow: "md",
1502
+ radius: "md",
1503
+ width: 340,
1504
+ children: [
1505
+ /* @__PURE__ */ jsx(Popover.Target, { children }),
1506
+ /* @__PURE__ */ jsxs(Popover.Dropdown, { children: [
1507
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "center", mb: "sm", children: [
1508
+ /* @__PURE__ */ jsx(Text, { fw: 600, fz: "sm", children: labels.filters }),
1509
+ /* @__PURE__ */ jsx(
1510
+ Button,
1511
+ {
1512
+ variant: "subtle",
1513
+ size: "compact-xs",
1514
+ onClick: onClearFilters,
1515
+ disabled: activeFilterCount === 0,
1516
+ children: labels.clearAll
1517
+ }
1518
+ )
1519
+ ] }),
1520
+ /* @__PURE__ */ jsx(Stack, { gap: "md", children: filters })
1521
+ ] })
1522
+ ]
1523
+ }
1524
+ );
1525
+ }
1526
+ function Toolbar({
1527
+ table,
1528
+ hideSearch,
1529
+ searchPlaceholder,
1530
+ sortByOptions,
1531
+ customToolbar,
1532
+ hasFilters,
1533
+ activeFilterCount,
1534
+ onToggleFilters,
1535
+ onFiltersTriggerPointerDown,
1536
+ onCloseFilters,
1537
+ filtersOpen,
1538
+ filtersMode,
1539
+ filters,
1540
+ onClearFilters,
1541
+ dir,
1542
+ columnMenu,
1543
+ showRowsPerPage,
1544
+ className
1545
+ }) {
1546
+ const { labels, source } = table;
1547
+ const searchProps = table.getSearchInputProps(
1548
+ searchPlaceholder ? { placeholder: searchPlaceholder } : void 0
1549
+ );
1550
+ const sortOptions = sortByOptions ?? (table.isMobile ? table.sortByOptions : void 0);
1551
+ const filtersButton = /* @__PURE__ */ jsx(
1552
+ Button,
1553
+ {
1554
+ variant: "default",
1555
+ size: "sm",
1556
+ "aria-expanded": filtersMode === "popover" ? filtersOpen : void 0,
1557
+ "data-active": filtersOpen || void 0,
1558
+ leftSection: /* @__PURE__ */ jsx(FiltersIcon, { size: 16 }),
1559
+ rightSection: activeFilterCount > 0 ? /* @__PURE__ */ jsx(Badge, { size: "sm", circle: true, children: activeFilterCount }) : void 0,
1560
+ onPointerDown: onFiltersTriggerPointerDown,
1561
+ onClick: onToggleFilters,
1562
+ children: labels.filters
1563
+ }
1564
+ );
1565
+ return /* @__PURE__ */ jsxs(
1566
+ Group,
1567
+ {
1568
+ gap: "sm",
1569
+ justify: "space-between",
1570
+ align: "center",
1571
+ className,
1572
+ children: [
1573
+ !hideSearch && /* @__PURE__ */ jsx(
1574
+ TextInput,
1575
+ {
1576
+ ...searchProps,
1577
+ leftSection: /* @__PURE__ */ jsx(SearchIcon, { size: 14 }),
1578
+ size: "sm",
1579
+ style: { flex: 1, minWidth: 160, maxWidth: 360 }
1580
+ }
1581
+ ),
1582
+ /* @__PURE__ */ jsxs(Group, { gap: "xs", align: "center", children: [
1583
+ sortOptions && sortOptions.length > 0 && /* @__PURE__ */ jsx(
1584
+ Select,
1585
+ {
1586
+ "aria-label": labels.sortBy,
1587
+ placeholder: labels.sortBy,
1588
+ data: sortOptions,
1589
+ value: source.sortBy ?? null,
1590
+ onChange: (v) => source.setSort(v ?? void 0, source.sortDir ?? "asc"),
1591
+ clearable: true,
1592
+ size: "sm",
1593
+ w: 160,
1594
+ comboboxProps: { withinPortal: false }
1595
+ }
1596
+ ),
1597
+ customToolbar,
1598
+ hasFilters && (filtersMode === "popover" ? /* @__PURE__ */ jsx(
1599
+ FilterPopover,
1600
+ {
1601
+ open: filtersOpen,
1602
+ onClose: onCloseFilters,
1603
+ filters,
1604
+ activeFilterCount,
1605
+ onClearFilters,
1606
+ labels,
1607
+ dir,
1608
+ children: filtersButton
1609
+ }
1610
+ ) : filtersButton),
1611
+ columnMenu,
1612
+ showRowsPerPage && /* @__PURE__ */ jsxs(Group, { gap: "xs", align: "center", children: [
1613
+ /* @__PURE__ */ jsx(Text, { fz: "xs", c: "dimmed", children: labels.rowsPerPage }),
1614
+ /* @__PURE__ */ jsx(
1615
+ Select,
1616
+ {
1617
+ "aria-label": labels.rowsPerPage,
1618
+ data: pageSizeOptions(source.limit).map((n) => ({
1619
+ value: String(n),
1620
+ label: String(n)
1621
+ })),
1622
+ value: String(source.limit),
1623
+ onChange: (v) => source.setLimit(Number(v)),
1624
+ size: "sm",
1625
+ w: 80,
1626
+ allowDeselect: false,
1627
+ comboboxProps: { withinPortal: false }
1628
+ }
1629
+ )
1630
+ ] })
1631
+ ] })
1632
+ ]
1633
+ }
1634
+ );
1635
+ }
1636
+ var stickyToolbarStyle = (top) => ({
1637
+ position: "sticky",
1638
+ top,
1639
+ zIndex: 3,
1640
+ background: "var(--mantine-color-body)",
1641
+ paddingBottom: "var(--mantine-spacing-xs)"
1642
+ });
1643
+ function ColumnMenuSlot({
1644
+ enabled,
1645
+ ...props
1646
+ }) {
1647
+ if (!enabled) return null;
1648
+ return /* @__PURE__ */ jsx(ColumnMenu, { ...props });
1649
+ }
1650
+ function SavedViewsSlot({
1651
+ options,
1652
+ labels
1653
+ }) {
1654
+ const views = useSavedViews(options);
1655
+ return /* @__PURE__ */ jsx(SavedViewsMenu, { views, labels });
1656
+ }
1657
+ function useResolvedTableProps(props) {
1658
+ const { source, runtime } = useTableData({
1659
+ locale: props.locale,
1660
+ source: props.source,
1661
+ data: props.data,
1662
+ total: props.total,
1663
+ loading: props.loading,
1664
+ onQueryChange: props.onQueryChange,
1665
+ columns: props.columns,
1666
+ filters: props.filters,
1667
+ urlKey: props.urlKey,
1668
+ adapter: props.urlSync === false ? void 0 : props.urlAdapter,
1669
+ enabled: props.urlSync
1670
+ });
1671
+ const labels = useMemo(() => resolveLabels(props.labels), [props.labels]);
1672
+ let filters;
1673
+ if (isDeclarativeFilters(props.filters) || props.filters === void 0) {
1674
+ filters = runtime.defs.length > 0 ? /* @__PURE__ */ jsx(AutoFilterForm, { defs: runtime.defs, source, labels }) : void 0;
1675
+ } else {
1676
+ filters = props.filters;
1677
+ }
1678
+ const filterLabels = useMemo(
1679
+ () => ({ ...runtime.filterLabels, ...props.filterLabels }),
1680
+ [runtime.filterLabels, props.filterLabels]
1681
+ );
1682
+ return { ...props, source, filters, filterLabels };
1683
+ }
1684
+ function DataTable(props) {
1685
+ const chromeProps = useResolvedTableProps(props);
1686
+ const {
1687
+ source,
1688
+ rowActions,
1689
+ searchPlaceholder,
1690
+ sortByOptions,
1691
+ dir,
1692
+ prefetch,
1693
+ hideSearch,
1694
+ filters,
1695
+ filtersMode = "popover",
1696
+ bulkActions,
1697
+ slots,
1698
+ classNames,
1699
+ toolbar: customToolbar,
1700
+ skeletonRows,
1701
+ stickyTop = 0,
1702
+ animate = false,
1703
+ stickyHeader = false,
1704
+ enableColumnMenu = false,
1705
+ savedViews
1706
+ } = chromeProps;
1707
+ const density = chromeProps.density ?? "comfortable";
1708
+ const chrome = useTableChrome(chromeProps);
1709
+ const { table, isMobile, confirm, getRowId } = chrome;
1710
+ const hasRowActions = (rowActions?.length ?? 0) > 0;
1711
+ const visibleRowActions = chrome.columnLayout.isHidden(ACTIONS_COLUMN_KEY) ? void 0 : rowActions;
1712
+ const actionsPinned = chrome.columnLayout.state.pinned[ACTIONS_COLUMN_KEY] === "right";
1713
+ const { virtualization, loadMoreRef, canLoadMore, virtualScrollRef } = useChromeBodyData(chrome, chromeProps);
1714
+ const [drawerOpened, setDrawerOpened] = useState(false);
1715
+ const filtersTrigger = useFilterTriggerToggle(drawerOpened, setDrawerOpened);
1716
+ const rootRef = useRef(null);
1717
+ const { ref: toolbarRef, height: toolbarHeight } = useElementSize();
1718
+ const desktopBodyRef = useRef(null);
1719
+ const mobileBodyRef = useRef(null);
1720
+ useChromeScrollReset(rootRef, chrome, chromeProps);
1721
+ useMountStagger(
1722
+ isMobile ? mobileBodyRef : desktopBodyRef,
1723
+ [virtualization.rows.length, isMobile],
1724
+ { enabled: animate }
1725
+ );
1726
+ let body;
1727
+ if (chrome.body === "skeleton") {
1728
+ body = slots?.skeleton ?? /* @__PURE__ */ jsx(
1729
+ TableSkeleton,
1730
+ {
1731
+ columns: table.columns.length || 1,
1732
+ rows: skeletonRows ?? source.limit,
1733
+ loadingLabel: table.labels.loading
1734
+ }
1735
+ );
1736
+ } else if (chrome.body === "empty") {
1737
+ body = slots?.empty ?? (chrome.emptyVariant === "noResults" ? /* @__PURE__ */ jsx(
1738
+ EmptyState,
1739
+ {
1740
+ title: table.labels.noResults,
1741
+ action: /* @__PURE__ */ jsx(Button, { variant: "light", size: "sm", onClick: chrome.clearFilters, children: table.labels.clearAll })
1742
+ }
1743
+ ) : /* @__PURE__ */ jsx(EmptyState, { title: table.labels.noData }));
1744
+ } else if (chrome.body === "mobile") {
1745
+ body = /* @__PURE__ */ jsx(
1746
+ MobileCards,
1747
+ {
1748
+ table,
1749
+ rows: source.rows,
1750
+ rowActions: visibleRowActions,
1751
+ confirm,
1752
+ getRowId,
1753
+ onRowClick: props.onRowClick,
1754
+ rowClassName: props.rowClassName,
1755
+ renderRowDetail: props.renderRowDetail,
1756
+ summaryRow: props.summaryRow,
1757
+ expansion: chrome.detail?.expansion,
1758
+ bodyRef: mobileBodyRef,
1759
+ className: classNames?.card,
1760
+ rowEntries: virtualization.enabled ? virtualization.rows : void 0,
1761
+ paddingTop: virtualization.paddingTop,
1762
+ paddingBottom: virtualization.paddingBottom,
1763
+ measureElement: virtualization.measureElement,
1764
+ density
1765
+ }
1766
+ );
1767
+ } else {
1768
+ body = /* @__PURE__ */ jsx(
1769
+ DesktopTable,
1770
+ {
1771
+ table,
1772
+ rows: source.rows,
1773
+ rowActions: visibleRowActions,
1774
+ confirm,
1775
+ prefetch,
1776
+ onRowClick: props.onRowClick,
1777
+ rowClassName: props.rowClassName,
1778
+ renderRowDetail: props.renderRowDetail,
1779
+ summaryRow: props.summaryRow,
1780
+ expansion: chrome.detail?.expansion,
1781
+ getRowId,
1782
+ bodyRef: desktopBodyRef,
1783
+ className: classNames?.table,
1784
+ rowEntries: virtualization.enabled ? virtualization.rows : void 0,
1785
+ paddingTop: virtualization.paddingTop,
1786
+ paddingBottom: virtualization.paddingBottom,
1787
+ measureElement: virtualization.measureElement,
1788
+ stickyHeaderOffset: stickyTop + toolbarHeight,
1789
+ stickyHeader,
1790
+ pinOffset: chrome.columnLayout.pinOffset,
1791
+ actionsPinned,
1792
+ maxHeight: props.maxHeight,
1793
+ virtualScrollRef,
1794
+ setWidth: props.resizableColumns ? chrome.columnLayout.setWidth : void 0,
1795
+ columnWidths: chrome.columnLayout.state.widths,
1796
+ resizeLabel: table.labels.resizeColumn,
1797
+ density
1798
+ }
1799
+ );
1800
+ }
1801
+ return /* @__PURE__ */ jsxs(
1802
+ Paper,
1803
+ {
1804
+ ref: rootRef,
1805
+ p: "xs",
1806
+ radius: "md",
1807
+ withBorder: true,
1808
+ dir,
1809
+ "aria-busy": chrome.isRefreshing || void 0,
1810
+ className: classNames?.root,
1811
+ children: [
1812
+ /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
1813
+ /* @__PURE__ */ jsx(
1814
+ Box,
1815
+ {
1816
+ ref: toolbarRef,
1817
+ style: stickyToolbarStyle(stickyTop),
1818
+ className: classNames?.toolbar,
1819
+ children: /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
1820
+ /* @__PURE__ */ jsx(
1821
+ Toolbar,
1822
+ {
1823
+ table,
1824
+ hideSearch,
1825
+ searchPlaceholder,
1826
+ sortByOptions,
1827
+ customToolbar,
1828
+ hasFilters: Boolean(filters),
1829
+ activeFilterCount: chrome.activeFilterCount,
1830
+ filtersMode,
1831
+ filters,
1832
+ filtersOpen: drawerOpened,
1833
+ onToggleFilters: filtersTrigger.onClick,
1834
+ onFiltersTriggerPointerDown: filtersTrigger.onPointerDown,
1835
+ onCloseFilters: () => setDrawerOpened(false),
1836
+ onClearFilters: chrome.clearFilters,
1837
+ dir,
1838
+ columnMenu: /* @__PURE__ */ jsxs(Fragment, { children: [
1839
+ savedViews && /* @__PURE__ */ jsx(
1840
+ SavedViewsSlot,
1841
+ {
1842
+ options: {
1843
+ adapter: chromeProps.urlAdapter,
1844
+ urlKey: chromeProps.urlKey,
1845
+ ...savedViews
1846
+ },
1847
+ labels: table.labels
1848
+ }
1849
+ ),
1850
+ /* @__PURE__ */ jsx(
1851
+ ColumnMenuSlot,
1852
+ {
1853
+ enabled: enableColumnMenu && !isMobile,
1854
+ allColumns: chrome.allColumns,
1855
+ layout: chrome.columnLayout,
1856
+ labels: table.labels,
1857
+ hasRowActions
1858
+ }
1859
+ )
1860
+ ] }),
1861
+ showRowsPerPage: canLoadMore
1862
+ }
1863
+ ),
1864
+ /* @__PURE__ */ jsx(
1865
+ ActiveFilterChips,
1866
+ {
1867
+ chips: chrome.mergedChips,
1868
+ onClearAll: chrome.clearFilters,
1869
+ label: table.labels.filters,
1870
+ clearAllLabel: table.labels.clearAll
1871
+ }
1872
+ ),
1873
+ table.selection && bulkActions && /* @__PURE__ */ jsx(
1874
+ BulkActionBar,
1875
+ {
1876
+ selection: table.selection,
1877
+ total: source.total,
1878
+ bulkActions,
1879
+ confirm,
1880
+ labels: table.labels
1881
+ }
1882
+ )
1883
+ ] })
1884
+ }
1885
+ ),
1886
+ chrome.isRefreshing && /* @__PURE__ */ jsx(
1887
+ Progress,
1888
+ {
1889
+ size: "xs",
1890
+ animated: true,
1891
+ value: 100,
1892
+ "aria-label": table.labels.loading
1893
+ }
1894
+ ),
1895
+ source.error && /* @__PURE__ */ jsx(
1896
+ ErrorState,
1897
+ {
1898
+ error: source.error,
1899
+ title: table.labels.errorTitle,
1900
+ message: table.labels.errorMessage,
1901
+ retryLabel: table.labels.retry,
1902
+ onRetry: source.refetch ? () => void source.refetch?.() : void 0,
1903
+ isRetrying: source.isFetching
1904
+ }
1905
+ ),
1906
+ !source.error && body,
1907
+ canLoadMore && source.hasNextPage && /* @__PURE__ */ jsx(Group, { ref: loadMoreRef, justify: "center", py: "xs", children: /* @__PURE__ */ jsx(
1908
+ Button,
1909
+ {
1910
+ variant: "default",
1911
+ size: "sm",
1912
+ loading: source.isFetchingNextPage,
1913
+ onClick: () => source.fetchNextPage(),
1914
+ children: table.labels.loadMore
1915
+ }
1916
+ ) }),
1917
+ chrome.showFooter && /* @__PURE__ */ jsx(Box, { className: classNames?.footer, children: /* @__PURE__ */ jsx(
1918
+ PaginationFooter,
1919
+ {
1920
+ page: table.pagination.safePage,
1921
+ totalPages: table.pagination.totalPages,
1922
+ limit: source.limit,
1923
+ total: source.total,
1924
+ fromIndex: table.pagination.fromIndex,
1925
+ toIndex: table.pagination.toIndex,
1926
+ onPageChange: source.setPage,
1927
+ onLimitChange: source.setLimit,
1928
+ labels: table.labels
1929
+ }
1930
+ ) })
1931
+ ] }),
1932
+ filters && filtersMode === "drawer" && /* @__PURE__ */ jsx(
1933
+ FilterDrawer,
1934
+ {
1935
+ opened: drawerOpened,
1936
+ onClose: () => setDrawerOpened(false),
1937
+ filters,
1938
+ activeFilterCount: chrome.activeFilterCount,
1939
+ onClearFilters: chrome.clearFilters,
1940
+ labels: table.labels,
1941
+ dir
1942
+ }
1943
+ )
1944
+ ]
1945
+ }
1946
+ );
1947
+ }
1948
+
1949
+ export { ActiveFilterChips, AutoFilterForm, DataTable, EmptyState, ErrorState, PaginationFooter, SavedViewsMenu, TableSkeleton, useMountStagger };
1950
+ //# sourceMappingURL=index.js.map
1951
+ //# sourceMappingURL=index.js.map