@fayz-ai/ui 0.37.0 → 0.38.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.
@@ -1,6 +1,6 @@
1
1
  import { PageViewBar } from './chunk-7SEWMFO3.js';
2
2
  import { cn, Button } from './chunk-FKYFYGAS.js';
3
- import * as React2 from 'react';
3
+ import * as React4 from 'react';
4
4
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
5
  import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
6
6
  import { ChevronRight, Check, Circle, Minus, ChevronDown, ArrowDown, ArrowUp, ArrowUpDown, ListFilter, X, Calendar, RefreshCw } from 'lucide-react';
@@ -8,7 +8,7 @@ import { useReactTable, getSortedRowModel, getCoreRowModel, flexRender } from '@
8
8
  import { useTranslation } from '@fayz-ai/core';
9
9
  import * as PopoverPrimitive from '@radix-ui/react-popover';
10
10
 
11
- var Card = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
11
+ var Card = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
12
12
  "div",
13
13
  {
14
14
  ref,
@@ -20,7 +20,7 @@ var Card = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ j
20
20
  }
21
21
  ));
22
22
  Card.displayName = "Card";
23
- var CardHeader = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
23
+ var CardHeader = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
24
24
  "div",
25
25
  {
26
26
  ref,
@@ -29,7 +29,7 @@ var CardHeader = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE_
29
29
  }
30
30
  ));
31
31
  CardHeader.displayName = "CardHeader";
32
- var CardTitle = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
32
+ var CardTitle = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
33
33
  "h3",
34
34
  {
35
35
  ref,
@@ -41,7 +41,7 @@ var CardTitle = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__
41
41
  }
42
42
  ));
43
43
  CardTitle.displayName = "CardTitle";
44
- var CardDescription = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
44
+ var CardDescription = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
45
45
  "p",
46
46
  {
47
47
  ref,
@@ -50,9 +50,9 @@ var CardDescription = React2.forwardRef(({ className, ...props }, ref) => /* @__
50
50
  }
51
51
  ));
52
52
  CardDescription.displayName = "CardDescription";
53
- var CardContent = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-4 pt-0", className), ...props }));
53
+ var CardContent = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-4 pt-0", className), ...props }));
54
54
  CardContent.displayName = "CardContent";
55
- var CardFooter = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
55
+ var CardFooter = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
56
56
  "div",
57
57
  {
58
58
  ref,
@@ -67,7 +67,7 @@ var DropdownGroup = DropdownMenuPrimitive.Group;
67
67
  var DropdownPortal = DropdownMenuPrimitive.Portal;
68
68
  var DropdownSub = DropdownMenuPrimitive.Sub;
69
69
  var DropdownRadioGroup = DropdownMenuPrimitive.RadioGroup;
70
- var DropdownSubTrigger = React2.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ jsxs(
70
+ var DropdownSubTrigger = React4.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ jsxs(
71
71
  DropdownMenuPrimitive.SubTrigger,
72
72
  {
73
73
  ref,
@@ -84,7 +84,7 @@ var DropdownSubTrigger = React2.forwardRef(({ className, inset, children, ...pro
84
84
  }
85
85
  ));
86
86
  DropdownSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
87
- var DropdownSubContent = React2.forwardRef(({ className, ...props }, ref) => (
87
+ var DropdownSubContent = React4.forwardRef(({ className, ...props }, ref) => (
88
88
  // Portaled, like DropdownContent. Without it the submenu renders inside the
89
89
  // parent panel's DOM — and that panel is `overflow-hidden`, so the submenu
90
90
  // was clipped to its box: a flyout you could open and never reach.
@@ -101,7 +101,7 @@ var DropdownSubContent = React2.forwardRef(({ className, ...props }, ref) => (
101
101
  ) })
102
102
  ));
103
103
  DropdownSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
104
- var DropdownContent = React2.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx(
104
+ var DropdownContent = React4.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx(
105
105
  DropdownMenuPrimitive.Content,
106
106
  {
107
107
  ref,
@@ -114,7 +114,7 @@ var DropdownContent = React2.forwardRef(({ className, sideOffset = 4, ...props }
114
114
  }
115
115
  ) }));
116
116
  DropdownContent.displayName = DropdownMenuPrimitive.Content.displayName;
117
- var DropdownItem = React2.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx(
117
+ var DropdownItem = React4.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx(
118
118
  DropdownMenuPrimitive.Item,
119
119
  {
120
120
  ref,
@@ -127,7 +127,7 @@ var DropdownItem = React2.forwardRef(({ className, inset, ...props }, ref) => /*
127
127
  }
128
128
  ));
129
129
  DropdownItem.displayName = DropdownMenuPrimitive.Item.displayName;
130
- var DropdownCheckboxItem = React2.forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ jsxs(
130
+ var DropdownCheckboxItem = React4.forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ jsxs(
131
131
  DropdownMenuPrimitive.CheckboxItem,
132
132
  {
133
133
  ref,
@@ -144,7 +144,7 @@ var DropdownCheckboxItem = React2.forwardRef(({ className, children, checked, ..
144
144
  }
145
145
  ));
146
146
  DropdownCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;
147
- var DropdownRadioItem = React2.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
147
+ var DropdownRadioItem = React4.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
148
148
  DropdownMenuPrimitive.RadioItem,
149
149
  {
150
150
  ref,
@@ -160,7 +160,7 @@ var DropdownRadioItem = React2.forwardRef(({ className, children, ...props }, re
160
160
  }
161
161
  ));
162
162
  DropdownRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
163
- var DropdownLabel = React2.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx(
163
+ var DropdownLabel = React4.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx(
164
164
  DropdownMenuPrimitive.Label,
165
165
  {
166
166
  ref,
@@ -173,7 +173,7 @@ var DropdownLabel = React2.forwardRef(({ className, inset, ...props }, ref) => /
173
173
  }
174
174
  ));
175
175
  DropdownLabel.displayName = DropdownMenuPrimitive.Label.displayName;
176
- var DropdownSeparator = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
176
+ var DropdownSeparator = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
177
177
  DropdownMenuPrimitive.Separator,
178
178
  {
179
179
  ref,
@@ -201,7 +201,7 @@ var COLOR_CLASSES = {
201
201
  warning: "border-warning bg-warning text-white",
202
202
  destructive: "border-destructive bg-destructive text-destructive-foreground"
203
203
  };
204
- var Checkbox = React2.forwardRef(
204
+ var Checkbox = React4.forwardRef(
205
205
  ({ checked = false, onChange, disabled, className, color = "primary", id, indeterminate = false, ...props }, ref) => {
206
206
  const filled = checked || indeterminate;
207
207
  return /* @__PURE__ */ jsx(
@@ -242,7 +242,8 @@ function DataTable({
242
242
  selectedIds,
243
243
  onSelectedIdsChange,
244
244
  getRowId,
245
- rowClassName
245
+ rowClassName,
246
+ groupBy
246
247
  }) {
247
248
  const t = useTranslation();
248
249
  const isCard = variant === "card";
@@ -252,28 +253,37 @@ function DataTable({
252
253
  const tdCls = compact ? "px-3 py-1.5 align-middle text-xs" : "px-4 py-3 align-middle";
253
254
  const tableCls = compact ? "w-full text-xs min-w-max" : "w-full text-sm min-w-max";
254
255
  const rowHoverCls = isCard ? "hover:bg-muted/30" : "hover:bg-muted/20";
255
- const [sorting, setSorting] = React2.useState([]);
256
- const rowId = React2.useCallback(
256
+ const [sorting, setSorting] = React4.useState([]);
257
+ const [ownCollapsed, setOwnCollapsed] = React4.useState([]);
258
+ const collapsedKeys = groupBy?.collapsed ?? ownCollapsed;
259
+ const collapsed = React4.useMemo(() => new Set(collapsedKeys), [collapsedKeys]);
260
+ const onCollapsedChange = groupBy?.onCollapsedChange;
261
+ const toggleGroup = React4.useCallback((key) => {
262
+ const next = collapsed.has(key) ? [...collapsed].filter((k) => k !== key) : [...collapsed, key];
263
+ if (onCollapsedChange) onCollapsedChange(next);
264
+ else setOwnCollapsed(next);
265
+ }, [collapsed, onCollapsedChange]);
266
+ const rowId = React4.useCallback(
257
267
  (row) => getRowId ? getRowId(row) : String(row.id ?? ""),
258
268
  [getRowId]
259
269
  );
260
- const selected = React2.useMemo(() => new Set(selectedIds ?? []), [selectedIds]);
261
- const pageIds = React2.useMemo(() => data.map(rowId), [data, rowId]);
270
+ const selected = React4.useMemo(() => new Set(selectedIds ?? []), [selectedIds]);
271
+ const pageIds = React4.useMemo(() => data.map(rowId), [data, rowId]);
262
272
  const selectedOnPage = pageIds.filter((id) => selected.has(id)).length;
263
273
  const allOnPageSelected = pageIds.length > 0 && selectedOnPage === pageIds.length;
264
- const toggleRow = React2.useCallback((id) => {
274
+ const toggleRow = React4.useCallback((id) => {
265
275
  const next = new Set(selected);
266
276
  if (next.has(id)) next.delete(id);
267
277
  else next.add(id);
268
278
  onSelectedIdsChange?.([...next]);
269
279
  }, [selected, onSelectedIdsChange]);
270
- const toggleAllOnPage = React2.useCallback(() => {
280
+ const toggleAllOnPage = React4.useCallback(() => {
271
281
  const next = new Set(selected);
272
282
  if (allOnPageSelected) pageIds.forEach((id) => next.delete(id));
273
283
  else pageIds.forEach((id) => next.add(id));
274
284
  onSelectedIdsChange?.([...next]);
275
285
  }, [selected, allOnPageSelected, pageIds, onSelectedIdsChange]);
276
- const selectionColumn = React2.useMemo(() => ({
286
+ const selectionColumn = React4.useMemo(() => ({
277
287
  id: "__select__",
278
288
  enableSorting: false,
279
289
  header: () => /* @__PURE__ */ jsx(
@@ -300,7 +310,7 @@ function DataTable({
300
310
  // ids: turning the page with nothing selected changes no other dep, and the
301
311
  // memo would hand the header a button that ticks the previous page's rows.
302
312
  }), [allOnPageSelected, selectedOnPage, selected, rowId, toggleRow, toggleAllOnPage, t]);
303
- const allColumns = React2.useMemo(
313
+ const allColumns = React4.useMemo(
304
314
  () => selectable ? [selectionColumn, ...columns] : columns,
305
315
  [selectable, selectionColumn, columns]
306
316
  );
@@ -312,6 +322,10 @@ function DataTable({
312
322
  onSortingChange: setSorting,
313
323
  state: { sorting }
314
324
  });
325
+ const [tableEl, setTableEl] = React4.useState(null);
326
+ const headScrollRef = React4.useRef(null);
327
+ const floating = useFloatingHeader(tableEl, [data, allColumns, collapsed, sorting]);
328
+ const groupBandBackground = "linear-gradient(hsl(var(--muted) / 0.4), hsl(var(--muted) / 0.4)), hsl(var(--card))";
315
329
  if (loading) {
316
330
  return /* @__PURE__ */ jsx("div", { className: wrapperCls, children: /* @__PURE__ */ jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs("table", { className: tableCls, children: [
317
331
  /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { className: headerCls, children: allColumns.map((_, i) => /* @__PURE__ */ jsx("th", { className: thCls, children: /* @__PURE__ */ jsx("div", { className: "h-3.5 w-20 animate-pulse rounded bg-muted" }) }, i)) }) }),
@@ -322,68 +336,204 @@ function DataTable({
322
336
  if (showEmptyBlock) {
323
337
  return /* @__PURE__ */ jsx("div", { className: wrapperCls, children: /* @__PURE__ */ jsx("div", { className: "flex min-h-64 w-full items-center justify-center px-4 py-10 text-center text-muted-foreground", children: emptyMessage }) });
324
338
  }
325
- return /* @__PURE__ */ jsx("div", { className: wrapperCls, children: /* @__PURE__ */ jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs("table", { className: tableCls, children: [
326
- /* @__PURE__ */ jsx("thead", { children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx("tr", { className: headerCls, children: headerGroup.headers.map((header) => {
327
- const sorted = header.column.getIsSorted();
328
- return /* @__PURE__ */ jsx(
329
- "th",
339
+ const headerRows = /* @__PURE__ */ jsx(Fragment, { children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx("tr", { className: headerCls, children: headerGroup.headers.map((header) => {
340
+ const sorted = header.column.getIsSorted();
341
+ return /* @__PURE__ */ jsx(
342
+ "th",
343
+ {
344
+ className: cn(thCls, header.column.id === "__select__" && "w-10 pr-0"),
345
+ children: header.isPlaceholder ? null : sortIndicator?.columnId === header.column.id ? /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 text-foreground", children: [
346
+ flexRender(header.column.columnDef.header, header.getContext()),
347
+ sortIndicator.dir === "desc" ? /* @__PURE__ */ jsx(ArrowDown, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx(ArrowUp, { className: "h-3 w-3" })
348
+ ] }) : header.column.getCanSort() ? /* @__PURE__ */ jsxs(
349
+ "button",
350
+ {
351
+ className: "flex items-center gap-1 hover:text-foreground transition-colors",
352
+ onClick: header.column.getToggleSortingHandler(),
353
+ children: [
354
+ flexRender(header.column.columnDef.header, header.getContext()),
355
+ sorted === "asc" ? /* @__PURE__ */ jsx(ArrowUp, { className: "h-3 w-3" }) : sorted === "desc" ? /* @__PURE__ */ jsx(ArrowDown, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx(ArrowUpDown, { className: "h-3 w-3 opacity-40" })
356
+ ]
357
+ }
358
+ ) : flexRender(header.column.columnDef.header, header.getContext())
359
+ },
360
+ header.id
361
+ );
362
+ }) }, headerGroup.id)) });
363
+ const renderGroupButton = (key, rows, isCollapsed) => /* @__PURE__ */ jsxs(
364
+ "button",
365
+ {
366
+ type: "button",
367
+ className: cn("flex w-full items-center gap-2 text-left font-medium text-foreground hover:bg-muted/60", compact ? "px-3 py-1.5" : "px-4 py-2"),
368
+ onClick: () => toggleGroup(key),
369
+ "aria-expanded": !isCollapsed,
370
+ children: [
371
+ isCollapsed ? /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4 text-muted-foreground" }) : /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4 text-muted-foreground" }),
372
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: key ? groupBy?.renderLabel?.(key, rows.map((r) => r.original)) ?? key : groupBy?.emptyLabel ?? "\u2014" }),
373
+ /* @__PURE__ */ jsx("span", { className: "rounded-full bg-background px-2 py-0.5 text-[11px] font-medium tabular-nums text-muted-foreground", children: rows.length })
374
+ ]
375
+ }
376
+ );
377
+ const activeGroup = floating.activeGroup != null ? groupRows(table.getRowModel().rows, groupBy).find((g) => g?.key === floating.activeGroup) : void 0;
378
+ const overlayHeight = floating.headH + (activeGroup ? floating.bandH : 0);
379
+ return (
380
+ // `clip`, not `hidden`: it rounds the corners without becoming a scroll
381
+ // container, which would capture the sticky header.
382
+ /* @__PURE__ */ jsxs("div", { className: wrapperCls, style: { overflow: "clip" }, children: [
383
+ floating.widths.length > 0 && /* @__PURE__ */ jsxs(
384
+ "div",
330
385
  {
331
- className: cn(thCls, header.column.id === "__select__" && "w-10 pr-0"),
332
- children: header.isPlaceholder ? null : sortIndicator?.columnId === header.column.id ? /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 text-foreground", children: [
333
- flexRender(header.column.columnDef.header, header.getContext()),
334
- sortIndicator.dir === "desc" ? /* @__PURE__ */ jsx(ArrowDown, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx(ArrowUp, { className: "h-3 w-3" })
335
- ] }) : header.column.getCanSort() ? /* @__PURE__ */ jsxs(
336
- "button",
386
+ className: "bg-card",
387
+ style: { position: "sticky", top: 0, zIndex: 10, height: overlayHeight, marginBottom: -overlayHeight, overflow: "hidden" },
388
+ children: [
389
+ /* @__PURE__ */ jsx("div", { ref: headScrollRef, style: { overflow: "hidden" }, children: /* @__PURE__ */ jsxs("table", { className: tableCls, style: { tableLayout: "fixed", width: floating.tableWidth, minWidth: 0 }, children: [
390
+ /* @__PURE__ */ jsx("colgroup", { children: floating.widths.map((w, i) => /* @__PURE__ */ jsx("col", { style: { width: w } }, i)) }),
391
+ /* @__PURE__ */ jsx("thead", { children: headerRows })
392
+ ] }) }),
393
+ activeGroup && /* @__PURE__ */ jsx("div", { className: "border-b", style: { background: groupBandBackground }, children: renderGroupButton(activeGroup.key, activeGroup.rows, collapsed.has(activeGroup.key)) })
394
+ ]
395
+ }
396
+ ),
397
+ /* @__PURE__ */ jsx("div", { className: "overflow-x-auto", onScroll: (e) => {
398
+ if (headScrollRef.current) headScrollRef.current.scrollLeft = e.currentTarget.scrollLeft;
399
+ }, children: /* @__PURE__ */ jsxs("table", { ref: setTableEl, className: tableCls, children: [
400
+ /* @__PURE__ */ jsx("thead", { style: { visibility: floating.widths.length > 0 ? "hidden" : void 0 }, children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx("tr", { className: headerCls, children: headerGroup.headers.map((header) => {
401
+ const sorted = header.column.getIsSorted();
402
+ return /* @__PURE__ */ jsx(
403
+ "th",
337
404
  {
338
- className: "flex items-center gap-1 hover:text-foreground transition-colors",
339
- onClick: header.column.getToggleSortingHandler(),
340
- children: [
405
+ className: cn(thCls, header.column.id === "__select__" && "w-10 pr-0"),
406
+ children: header.isPlaceholder ? null : sortIndicator?.columnId === header.column.id ? /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 text-foreground", children: [
341
407
  flexRender(header.column.columnDef.header, header.getContext()),
342
- sorted === "asc" ? /* @__PURE__ */ jsx(ArrowUp, { className: "h-3 w-3" }) : sorted === "desc" ? /* @__PURE__ */ jsx(ArrowDown, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx(ArrowUpDown, { className: "h-3 w-3 opacity-40" })
343
- ]
408
+ sortIndicator.dir === "desc" ? /* @__PURE__ */ jsx(ArrowDown, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx(ArrowUp, { className: "h-3 w-3" })
409
+ ] }) : header.column.getCanSort() ? /* @__PURE__ */ jsxs(
410
+ "button",
411
+ {
412
+ className: "flex items-center gap-1 hover:text-foreground transition-colors",
413
+ onClick: header.column.getToggleSortingHandler(),
414
+ children: [
415
+ flexRender(header.column.columnDef.header, header.getContext()),
416
+ sorted === "asc" ? /* @__PURE__ */ jsx(ArrowUp, { className: "h-3 w-3" }) : sorted === "desc" ? /* @__PURE__ */ jsx(ArrowDown, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx(ArrowUpDown, { className: "h-3 w-3 opacity-40" })
417
+ ]
418
+ }
419
+ ) : flexRender(header.column.columnDef.header, header.getContext())
420
+ },
421
+ header.id
422
+ );
423
+ }) }, headerGroup.id)) }),
424
+ /* @__PURE__ */ jsx("tbody", { children: table.getRowModel().rows?.length ? groupRows(table.getRowModel().rows, groupBy).flatMap((group) => {
425
+ const isCollapsed = group && collapsed.has(group.key);
426
+ const header = group ? /* @__PURE__ */ jsx("tr", { className: "border-b", "data-group-key": group.key, children: /* @__PURE__ */ jsx(
427
+ "td",
428
+ {
429
+ colSpan: allColumns.length,
430
+ className: "p-0",
431
+ style: { background: groupBandBackground },
432
+ children: renderGroupButton(group.key, group.rows, !!isCollapsed)
344
433
  }
345
- ) : flexRender(header.column.columnDef.header, header.getContext())
346
- },
347
- header.id
348
- );
349
- }) }, headerGroup.id)) }),
350
- /* @__PURE__ */ jsx("tbody", { children: table.getRowModel().rows?.length ? table.getRowModel().rows.map((row) => {
351
- const isSelected = selectable && selected.has(rowId(row.original));
352
- return /* @__PURE__ */ jsx(
353
- "tr",
354
- {
355
- className: cn(
356
- `border-b last:border-0 transition-colors ${rowHoverCls}`,
357
- onRowClick && "cursor-pointer",
358
- isSelected && "bg-muted/40",
359
- rowClassName?.(row.original)
360
- ),
361
- onClick: () => onRowClick?.(row.original),
362
- "data-selected": isSelected || void 0,
363
- children: row.getVisibleCells().map((cell) => {
364
- const isSelectCell = cell.column.id === "__select__";
434
+ ) }, `__group__${group.key}`) : null;
435
+ const rows = isCollapsed ? [] : group?.rows ?? table.getRowModel().rows;
436
+ return [header, ...rows.map((row) => {
437
+ const isSelected = selectable && selected.has(rowId(row.original));
365
438
  return /* @__PURE__ */ jsx(
366
- "td",
439
+ "tr",
367
440
  {
368
- className: cn(tdCls, isSelectCell && "w-10 pr-0"),
369
- onClick: isSelectCell ? (e) => e.stopPropagation() : void 0,
370
- children: flexRender(cell.column.columnDef.cell, cell.getContext())
441
+ className: cn(
442
+ `border-b last:border-0 transition-colors ${rowHoverCls}`,
443
+ onRowClick && "cursor-pointer",
444
+ isSelected && "bg-muted/40",
445
+ rowClassName?.(row.original)
446
+ ),
447
+ onClick: () => onRowClick?.(row.original),
448
+ "data-selected": isSelected || void 0,
449
+ children: row.getVisibleCells().map((cell) => {
450
+ const isSelectCell = cell.column.id === "__select__";
451
+ return /* @__PURE__ */ jsx(
452
+ "td",
453
+ {
454
+ className: cn(tdCls, isSelectCell && "w-10 pr-0"),
455
+ onClick: isSelectCell ? (e) => e.stopPropagation() : void 0,
456
+ children: flexRender(cell.column.columnDef.cell, cell.getContext())
457
+ },
458
+ cell.id
459
+ );
460
+ })
371
461
  },
372
- cell.id
462
+ row.id
373
463
  );
374
- })
375
- },
376
- row.id
377
- );
378
- }) : /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { colSpan: allColumns.length, className: "h-64 px-6 text-center align-middle text-muted-foreground", children: emptyMessage }) }) })
379
- ] }) }) });
464
+ })];
465
+ }) : /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { colSpan: allColumns.length, className: "h-64 px-6 text-center align-middle text-muted-foreground", children: emptyMessage }) }) })
466
+ ] }) })
467
+ ] })
468
+ );
469
+ }
470
+ function useFloatingHeader(table, deps) {
471
+ const [state, setState] = React4.useState({ widths: [], tableWidth: 0, headH: 0, bandH: 0, activeGroup: null });
472
+ const measure = React4.useCallback(() => {
473
+ if (!table?.tHead) return;
474
+ const cells = [...table.tHead.rows[0]?.cells ?? []];
475
+ const widths = cells.map((c) => c.getBoundingClientRect().width);
476
+ const tableWidth = table.getBoundingClientRect().width;
477
+ const headH = table.tHead.getBoundingClientRect().height;
478
+ const bands = [...table.querySelectorAll("tr[data-group-key]")];
479
+ const bandH = bands[0]?.getBoundingClientRect().height ?? 0;
480
+ const top = table.getBoundingClientRect().top;
481
+ let scrollerTop = 0;
482
+ for (let el = table.parentElement?.parentElement ?? null; el; el = el.parentElement) {
483
+ const oy = getComputedStyle(el).overflowY;
484
+ if ((oy === "auto" || oy === "scroll") && el.scrollHeight > el.clientHeight) {
485
+ scrollerTop = el.getBoundingClientRect().top;
486
+ break;
487
+ }
488
+ }
489
+ const line = Math.max(top, scrollerTop) + headH;
490
+ let activeGroup = null;
491
+ for (const band of bands) {
492
+ if (band.getBoundingClientRect().top < line - 0.5) activeGroup = band.dataset.groupKey ?? "";
493
+ else break;
494
+ }
495
+ setState((prev) => prev.tableWidth === tableWidth && prev.headH === headH && prev.bandH === bandH && prev.activeGroup === activeGroup && prev.widths.length === widths.length && prev.widths.every((w, i) => w === widths[i]) ? prev : { widths, tableWidth, headH, bandH, activeGroup });
496
+ }, [table]);
497
+ React4.useLayoutEffect(() => {
498
+ measure();
499
+ }, [measure, ...deps]);
500
+ React4.useEffect(() => {
501
+ if (!table) return;
502
+ let frame = 0;
503
+ const schedule = () => {
504
+ if (!frame) frame = requestAnimationFrame(() => {
505
+ frame = 0;
506
+ measure();
507
+ });
508
+ };
509
+ const observer = new ResizeObserver(schedule);
510
+ observer.observe(table);
511
+ document.addEventListener("scroll", schedule, true);
512
+ return () => {
513
+ observer.disconnect();
514
+ document.removeEventListener("scroll", schedule, true);
515
+ cancelAnimationFrame(frame);
516
+ };
517
+ }, [table, measure]);
518
+ return state;
519
+ }
520
+ function groupRows(rows, groupBy) {
521
+ if (!groupBy) return [null];
522
+ const byKey = /* @__PURE__ */ new Map();
523
+ for (const row of rows) {
524
+ const key = groupBy.getKey(row.original)?.trim() ?? "";
525
+ const list = byKey.get(key);
526
+ if (list) list.push(row);
527
+ else byKey.set(key, [row]);
528
+ }
529
+ return [...byKey.entries()].sort(([a], [b]) => a === "" ? 1 : b === "" ? -1 : a.localeCompare(b, void 0, { sensitivity: "base" })).map(([key, list]) => ({ key, rows: list }));
380
530
  }
381
531
  var WIDE_QUERY = "(min-width: 768px)";
382
532
  function useIsWide(query = WIDE_QUERY) {
383
- const [wide, setWide] = React2.useState(
533
+ const [wide, setWide] = React4.useState(
384
534
  () => typeof window === "undefined" ? true : window.matchMedia(query).matches
385
535
  );
386
- React2.useEffect(() => {
536
+ React4.useEffect(() => {
387
537
  const mq = window.matchMedia(query);
388
538
  const onChange = () => setWide(mq.matches);
389
539
  mq.addEventListener("change", onChange);
@@ -421,7 +571,7 @@ function TableSkeleton({ columns = 4, rows = 2 }) {
421
571
  var Popover = PopoverPrimitive.Root;
422
572
  var PopoverTrigger = PopoverPrimitive.Trigger;
423
573
  var PopoverAnchor = PopoverPrimitive.Anchor;
424
- var PopoverContent = React2.forwardRef(({ className, align = "start", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
574
+ var PopoverContent = React4.forwardRef(({ className, align = "start", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
425
575
  PopoverPrimitive.Content,
426
576
  {
427
577
  ref,
@@ -453,14 +603,14 @@ function FilterMenuRow({ active, onClick, children }) {
453
603
  );
454
604
  }
455
605
  function FilterMenu({ fields, label = "Filtros", activeCount = 0, onClear, clearLabel = "Limpar filtros", header, align = "end", className }) {
456
- const [open, setOpen] = React2.useState(false);
457
- const [hovered, setHoveredRaw] = React2.useState(null);
458
- const [query, setQuery] = React2.useState("");
459
- const setHovered = React2.useCallback((id) => {
606
+ const [open, setOpen] = React4.useState(false);
607
+ const [hovered, setHoveredRaw] = React4.useState(null);
608
+ const [query, setQuery] = React4.useState("");
609
+ const setHovered = React4.useCallback((id) => {
460
610
  setHoveredRaw(id);
461
611
  setQuery("");
462
612
  }, []);
463
- const close = React2.useCallback(() => setOpen(false), []);
613
+ const close = React4.useCallback(() => setOpen(false), []);
464
614
  return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: (o) => {
465
615
  setOpen(o);
466
616
  if (!o) setHovered(null);
@@ -556,18 +706,18 @@ function FilterMenu({ fields, label = "Filtros", activeCount = 0, onClear, clear
556
706
  ] })
557
707
  ] });
558
708
  }
559
- var ToolbarSurfaceContext = React2.createContext({
709
+ var ToolbarSurfaceContext = React4.createContext({
560
710
  surface: "bar",
561
711
  close: () => {
562
712
  }
563
713
  });
564
714
  function useToolbarSurface() {
565
- return React2.useContext(ToolbarSurfaceContext).surface;
715
+ return React4.useContext(ToolbarSurfaceContext).surface;
566
716
  }
567
717
  function useToolbarPanelClose() {
568
- return React2.useContext(ToolbarSurfaceContext).close;
718
+ return React4.useContext(ToolbarSurfaceContext).close;
569
719
  }
570
- var ToolbarButton = React2.forwardRef(function ToolbarButton2({ icon: Icon, caret = true, children, className, ...props }, ref) {
720
+ var ToolbarButton = React4.forwardRef(function ToolbarButton2({ icon: Icon, caret = true, children, className, ...props }, ref) {
571
721
  const panel = useToolbarSurface() === "panel";
572
722
  if (panel) {
573
723
  return /* @__PURE__ */ jsxs(
@@ -611,7 +761,7 @@ var ToolbarButton = React2.forwardRef(function ToolbarButton2({ icon: Icon, care
611
761
  }
612
762
  );
613
763
  });
614
- var ToolbarAction = React2.forwardRef(function ToolbarAction2({ icon: Icon, caret = false, children, className, ...props }, ref) {
764
+ var ToolbarAction = React4.forwardRef(function ToolbarAction2({ icon: Icon, caret = false, children, className, ...props }, ref) {
615
765
  const panel = useToolbarSurface() === "panel";
616
766
  if (panel) {
617
767
  return /* @__PURE__ */ jsxs(
@@ -689,8 +839,8 @@ function PageToolbar({
689
839
  className
690
840
  }) {
691
841
  const wide = useIsWide();
692
- const [open, setOpen] = React2.useState(false);
693
- const panelSurface = React2.useMemo(
842
+ const [open, setOpen] = React4.useState(false);
843
+ const panelSurface = React4.useMemo(
694
844
  () => ({ surface: "panel", close: () => setOpen(false) }),
695
845
  []
696
846
  );
@@ -757,5 +907,5 @@ function PageToolbar({
757
907
  }
758
908
 
759
909
  export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, DataTable, Dropdown, DropdownCheckboxItem, DropdownContent, DropdownGroup, DropdownItem, DropdownLabel, DropdownPortal, DropdownRadioGroup, DropdownRadioItem, DropdownSeparator, DropdownShortcut, DropdownSub, DropdownSubContent, DropdownSubTrigger, DropdownTrigger, FilterMenu, FilterMenuRow, PageToolbar, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, RangeControl, Skeleton, TOOLBAR_ICON_DOT, TOOLBAR_ICON_TRIGGER, TableSkeleton, ToolbarAction, ToolbarButton, WIDE_QUERY, useIsWide, useToolbarPanelClose, useToolbarSurface };
760
- //# sourceMappingURL=chunk-5MXNQ6HZ.js.map
761
- //# sourceMappingURL=chunk-5MXNQ6HZ.js.map
910
+ //# sourceMappingURL=chunk-4LNSCAM4.js.map
911
+ //# sourceMappingURL=chunk-4LNSCAM4.js.map