UNPKG

laif-ds

Version:

Design System di Laif con componenti React basati su principi di Atomic Design

578 lines (577 loc) 19.3 kB
"use client"; import { jsx as c, jsxs as ie } from "react/jsx-runtime"; import { useReactTable as at } from "../../../../node_modules/@tanstack/react-table/build/lib/index.js"; import { cn as it } from "../../../../lib/utils.js"; import { useRef as f, useState as d, useEffect as H, useMemo as F } from "react"; import { Button as st } from "../../button.js"; import { Checkbox as ye } from "../../checkbox.js"; import { DataTableBody as lt } from "./components/data-table-body.js"; import { DataTableColumnVisibility as ct } from "./components/data-table-column-visibility.js"; import { DataTableFilters as dt } from "./components/data-table-filters.js"; import { DataTablePaginationComponent as ut } from "./components/data-table-pagination.js"; import { DataTableSearchbar as gt } from "./components/data-table-searchbar.js"; import { DataTableSortingComponent as mt } from "./components/data-table-sorting.js"; import { applySearchFilterToRow as we, debounce as pt, buildSearchFilter as ft, updatePageSizeFromContainer as ht, createDefaultAdvancedFilter as St, createBadgeFilterFromHeader as bt } from "./data-table.service.js"; import { DataTableActionsComponent as vt } from "./components/data-table-actions.js"; import { defaultDataTableI18n as Ft } from "./data-table-i18n.js"; import { getPaginationRowModel as Ct, getFilteredRowModel as xt, getSortedRowModel as yt, getCoreRowModel as wt } from "../../../../node_modules/@tanstack/table-core/build/lib/index.js"; function Pt({ columns: Y, data: j, loading: z = !1, emptyComponent: Re, className: Ie, rowSelection: Te = {}, onRowSelectionChange: se, checkable: P = !1, onCheckedRowsChange: Z, actions: ze = [], customComponentsLeft: De, customComponentsRight: Be, hidePagination: _e = !1, hideActionsRow: Me = !1, i18n: h = Ft, maxSortedColumns: le = 2, initialState: u, // New mode-based API serverMode: He = !1, serverConfig: Ne, disableAutoPageSize: b = !1, // Test & Accessibility id: Oe, "data-testid": Le }) { const q = f(null), a = He === !0, g = a ? Ne : void 0, ce = (e) => !e || !e.sort_by || !e.sort_order ? [] : e.sort_by.map((t, o) => ({ id: t, desc: e.sort_order[o] === "desc" })), Ge = (e) => { const t = ce(e?.sorting), o = { sort_by: t.map((s) => s.id), sort_order: t.map((s) => s.desc ? "desc" : "asc") }; return { computedSorting: t.length > 0 ? o : void 0, computedFilter: e?.computedFilter // Use provided value or undefined }; }, [N, ke] = d(() => ce(u?.sorting)), [Ae] = d([]), [Ve, je] = d( () => u?.columnVisibility ?? {} ), [m, Pe] = d(() => u?.filters?.searchbarFilter), [K, O] = d(() => u?.pagination ?? { pageIndex: 0, pageSize: 10 }), de = f(g); de.current = g; const E = f(g?.onStateChange); E.current = g?.onStateChange; const W = f(null), D = f(null), qe = f(0), ue = f(!1), ge = f(null), J = f({}), me = f(null), $ = f(z); $.current = z; const L = (e) => { e.computedFilter && (J.current.computedFilter = e.computedFilter), e.computedSorting && (J.current.computedSorting = e.computedSorting); const t = { ...e, // Use new computed values if available, otherwise use last known values computedFilter: e.computedFilter || J.current.computedFilter, computedSorting: e.computedSorting || J.current.computedSorting }; W.current = t, D.current && clearTimeout(D.current), D.current = setTimeout(() => { W.current && E.current && (qe.current = Date.now(), E.current(W.current), W.current = null, D.current = null); }, 400); }; H(() => { const e = setTimeout(() => { ue.current = !0; }, 100); return () => { clearTimeout(e), D.current && clearTimeout(D.current); }; }, []); const [r, G] = d(() => { const { computedSorting: e, computedFilter: t } = Ge(u); return { pagination: u?.pagination ?? { pageIndex: 0, pageSize: 10 }, sorting: u?.sorting, filters: u?.filters, computedFilter: u?.computedFilter ?? t, computedSorting: u?.computedSorting ?? e }; }); a && !g && console.warn("DataTable: Server mode requires serverConfig"); const [Ke, pe] = d(0), [Ee, fe] = d(0), [We, Je] = d({}), he = se ? Te : We, Ue = se || Je, [C, ee] = d( () => u?.filters?.filterBadges ?? [] ), [x, te] = d(() => u?.filters?.advancedFilterBadge), [U, Xe] = d(""), [Se, be] = d([]), ve = F(() => P ? [ { id: "data-table-integrated-checkbox-column", size: 24, minSize: 24, maxSize: 24, header: ({ table: e }) => /* @__PURE__ */ c( "div", { className: "flex w-6 max-w-6 min-w-6 items-center justify-center", style: { width: "24px", minWidth: "24px", maxWidth: "24px" }, children: /* @__PURE__ */ c( ye, { className: "cursor-pointer", checked: e.getIsAllPageRowsSelected(), onCheckedChange: (t) => e.toggleAllPageRowsSelected(!!t), "aria-label": h.selectAll } ) } ), cell: ({ row: e }) => /* @__PURE__ */ c( "div", { className: "flex w-6 max-w-6 min-w-6 items-center justify-center", style: { width: "24px", minWidth: "24px", maxWidth: "24px" }, children: /* @__PURE__ */ c( ye, { className: "cursor-pointer", checked: e.getIsSelected(), onCheckedChange: (t) => e.toggleSelected(!!t), "aria-label": h.selectRow } ) } ), enableSorting: !1, enableHiding: !1, enableResizing: !1, meta: { pinned: "left", sortable: !1, searchable: !1, filterable: !1, type: "other", listOptions: [] } }, ...Y ] : Y, [Y, P]), I = F(() => ve.map( (e) => e ), [ve]), X = (e) => { if (e.id) return e.id; if ("accessorKey" in e && typeof e.accessorKey == "string") return e.accessorKey; }, Qe = (e) => { const t = e.meta?.headerLabel; return t || (typeof e.header == "string" ? e.header : X(e) ?? "-"); }; H(() => { const e = (I ?? []).map(X).filter((l) => !!l), t = new Set(Se), o = new Set(e); t.size === o.size && [...t].every((l) => o.has(l)) || be(e); }, [I]); const B = F(() => I.filter((e) => !!e.meta?.searchable), [I]), T = F(() => B.map((e) => "accessorKey" in e && typeof e.accessorKey == "string" ? e.accessorKey : e.id).filter((e) => !!e), [B]), [Q, Ye] = d(() => u?.computedFilter ?? {}), Ze = { data: F(() => a || Object.keys(Q).length === 0 ? j : j.filter((e) => we({ original: e, getValue: (o) => e[o] }, Q)), [j, Q, a]), columns: I, getCoreRowModel: wt(), onSortingChange: (e) => { const t = typeof e == "function" ? e(N) : e; ke(t); }, getSortedRowModel: yt(), manualSorting: a, onColumnVisibilityChange: je, onRowSelectionChange: Ue, onColumnOrderChange: be, getFilteredRowModel: xt(), manualFiltering: a, globalFilterFn: (e, t, o) => a || !o ? !0 : (T ?? []).some((s) => { const l = e.getValue(s); return Array.isArray(l) ? l.some( (p) => String(p).toLowerCase().includes(o.toLowerCase()) ) : String(l).toLowerCase().includes(o.toLowerCase()); }) ?? !1, filterFns: { advancedFilter: (e) => a ? !0 : we(e, Q) }, onPaginationChange: (e) => { if (a && g) { if (typeof e == "object") { const t = b ? { ...r.pagination, pageIndex: e.pageIndex } : { ...r.pagination, pageIndex: e.pageIndex, pageSize: e.pageSize }, o = { ...r, pagination: t, // Preserve computed values if they exist computedFilter: r.computedFilter, computedSorting: r.computedSorting }; G(o), L(o); } } else O( typeof e == "object" ? (t) => b ? { ...t, pageIndex: e.pageIndex } : { pageIndex: e.pageIndex, pageSize: e.pageSize } : e ); }, getPaginationRowModel: Ct(), manualPagination: a, pageCount: a && z ? Ee : Ke, state: { sorting: N, columnFilters: Ae, columnVisibility: Ve, rowSelection: he, globalFilter: m, pagination: a ? r.pagination : K, columnOrder: Se }, // Prevent implicit resets on data/columns changes so filters/sorting persist autoResetPageIndex: !1 }, i = at(Ze), re = i.getFilteredRowModel(); H(() => { if (a && g) { const e = Math.ceil( g.totalItems / (r.pagination.pageSize || 10) ); pe(e), !z && e > 0 && fe(e); } else { const e = re.rows.length, t = Math.ceil(e / K.pageSize); pe(t), fe(t); } }, [ a, g?.totalItems, r.pagination.pageSize, r.pagination.pageIndex, i, re, K.pageSize, z ]), H(() => { if (b) return; const e = () => { const y = q.current; if (!y) return; const _ = y.querySelector( "thead tr" ), n = y.querySelector( "tbody tr" ), w = _?.getBoundingClientRect().height ?? 40; if (!!!n?.querySelector("td")) return; const A = n?.getBoundingClientRect().height ?? 32.5; ht(y, { rowHeight: A, headerHeight: w, onPageChange: a ? (R, v) => { if (g && ue.current) { const S = b ? { ...r.pagination, pageIndex: R } : { ...r.pagination, pageIndex: R, pageSize: v }, oe = S.pageIndex === r.pagination.pageIndex, ae = b || S.pageSize === r.pagination.pageSize; if (oe && ae) return; const V = { ...r, pagination: S, // Preserve computed values if they exist computedFilter: r.computedFilter, computedSorting: r.computedSorting }; G(V), $.current || L(V); } } : (R, v) => { O( (S) => b ? { ...S, pageIndex: R } : { pageIndex: R, pageSize: v } ); }, setPagination: (R) => { const v = typeof R == "function" ? R(r.pagination) : R; if (a && g) { const S = b ? { ...r.pagination, pageIndex: v.pageIndex } : { ...r.pagination, pageIndex: v.pageIndex, pageSize: v.pageSize }, oe = S.pageIndex === r.pagination.pageIndex, ae = b || S.pageSize === r.pagination.pageSize; if (oe && ae) return; const V = { ...r, pagination: S, // Preserve computed values if they exist computedFilter: r.computedFilter, computedSorting: r.computedSorting }; G(V), $.current || L(V); } else O( (S) => b ? { ...S, pageIndex: v.pageIndex } : { pageIndex: v.pageIndex, pageSize: v.pageSize } ); } }); }, t = pt(() => { requestAnimationFrame(() => { e(); }); }, 200); requestAnimationFrame(() => { requestAnimationFrame(() => { e(); }); }); const o = setTimeout(e, 200), s = document.fonts; s && typeof s.ready?.then == "function" && s.ready.then(() => e()), window.addEventListener("resize", t); const l = q.current, p = typeof ResizeObserver < "u" ? new ResizeObserver((y) => { const _ = y[0]; if (!_) return; const n = _.contentRect.height, w = me.current; (w === null || Math.abs(n - w) > 0.5) && (me.current = n, t()); }) : null; return l && p && p.observe(l), () => { window.removeEventListener("resize", t), clearTimeout(o), p && p.disconnect(), clearTimeout(o); }; }, [ a, q, b, // Recalculate when the rendered rows count changes; helps when data arrives async re.rows.length ]), H(() => { if (Z && P) { const e = i.getFilteredSelectedRowModel().rows.map((t) => t.original); Z(e); } }, [i, Z, P, he]); const $e = F(() => { const e = i.getHeaderGroups()[0], t = e ? e.headers : []; return (i.getState().sorting || []).map((l) => t.find((p) => p.column.id === l.id)).filter(Boolean); }, [ i.getHeaderGroups, i.getState().sorting, I ]), ne = F(() => i.getHeaderGroups()[0].headers.filter((e) => e.column.columnDef.meta?.sortable), [i.getHeaderGroups, I]), k = F(() => i.getHeaderGroups()[0].headers.filter((e) => e.column.columnDef.meta?.filterable), [i.getHeaderGroups, I]), et = F(() => U ? k.filter((e) => (e.column.columnDef.meta?.headerLabel ?? (typeof e.column.columnDef.header == "string" ? e.column.columnDef.header : void 0) ?? e.column.id).toLowerCase().includes(U.toLowerCase())) : k, [k, U]), Fe = (e) => { ee((t) => [...t, bt(e)]); }, tt = () => { te(St()); }, rt = F(() => C.sort((e, t) => e.value === void 0 || e.value === "" ? 1 : t.value === void 0 || t.value === "" ? -1 : 1), [C]), Ce = f({ filterBadges: [], advancedFilterBadge: void 0, searchbarGlobalFilter: void 0 }); H(() => { const e = ft( C, x ?? void 0 ), t = m && T.length > 0 ? T.length === 1 ? (() => { const n = T[0], M = B.find( (A) => X(A) === n )?.meta?.type; return M === "list_multi_select" || M === "list_single_select" ? { [n]: { operator: "array_overlap", value: [m] } } : { [n]: { operator: "like", value: m } }; })() : { _or: T.map((n) => { const M = B.find( (A) => X(A) === n )?.meta?.type; return M === "list_multi_select" || M === "list_single_select" ? { [n]: { operator: "array_overlap", value: [m] } } : { [n]: { operator: "like", value: m } }; }) } : null, o = [ ...e && Object.keys(e).length > 0 ? [e] : [], ...t ? [t] : [] ], s = o.length === 0 ? {} : o.length === 1 ? o[0] : { _and: o }, l = { sort_by: N.map((n) => n.id), sort_order: N.map((n) => n.desc ? "desc" : "asc") }, p = Ce.current, y = JSON.stringify(C) !== JSON.stringify(p.filterBadges) || JSON.stringify(x) !== JSON.stringify(p.advancedFilterBadge) || m !== p.searchbarGlobalFilter; Ce.current = { filterBadges: [...C], advancedFilterBadge: x ? { ...x } : void 0, searchbarGlobalFilter: m }; const _ = de.current; if (Ye(s), a && E.current && _) { const n = { ...r, computedFilter: s, // Emit only computedSorting. Use empty arrays to signal "no sorting" when cleared. computedSorting: l, filters: { filterBadges: C, advancedFilterBadge: x, searchbarFilter: m }, pagination: { ...r.pagination, // Only reset pageIndex to 0 when filters actually changed, not when just sorting changed pageIndex: y ? 0 : r.pagination.pageIndex } }; G(n); const w = JSON.stringify({ computedFilter: n.computedFilter, computedSorting: n.computedSorting, filters: n.filters, pagination: n.pagination }); ge.current !== w && (ge.current = w, L(n)); } else y && O((n) => ({ ...n, pageIndex: 0 })); }, [ C, x, m, T, B, N, a ]); const xe = i.getAllLeafColumns(), nt = xe.filter((e) => e.getIsVisible()), ot = xe.filter((e) => !e.getIsVisible()); return /* @__PURE__ */ ie( "div", { id: Oe, "data-testid": Le, className: it( "flex h-full max-h-full min-h-[250px] w-full max-w-full min-w-0 flex-col gap-2", Ie ), children: [ !Me && /* @__PURE__ */ ie("div", { className: "flex w-full items-center justify-between gap-1", children: [ /* @__PURE__ */ ie("div", { className: "flex min-w-0 flex-1 items-center gap-1 overflow-x-auto", children: [ ne.length > 0 && /* @__PURE__ */ c( mt, { table: i, sortedColumns: $e, sortableColumns: ne, i18n: h, maxSortedColumns: le } ), ne.length > 0 && k.length > 0 && /* @__PURE__ */ c("div", { className: "border-d-border h-4 min-h-4 w-[1px] border-r" }), De, /* @__PURE__ */ c( dt, { advancedFilterBadge: x, setAdvancedFilterBadge: te, filterableColumns: k, sortedFilterBadges: rt, setFilterBadges: ee, filterSearch: U, setFilterSearch: Xe, filteredColumns: et, handleAddFilter: Fe, handleAddAdvancedFilter: tt, i18n: h } ) ] }), /* @__PURE__ */ c("div", { className: "border-d-border h-4 min-h-4 w-[1px] border-r" }), Be, (C.length || x) && /* @__PURE__ */ c( st, { className: "h-6 text-xs", iconLeft: "FunnelX", size: "sm", variant: "ghost-destructive", onClick: () => { ee([]), te(void 0); }, children: h.reset } ), T.length > 0 && /* @__PURE__ */ c( gt, { debounceMs: 300, onSearch: Pe, i18n: h, initialValue: m ?? "", searchableColumnsHeaders: B.map( (e) => Qe(e) ) } ), /* @__PURE__ */ c( ct, { table: i, visibleColumns: nt, hiddenColumns: ot, i18n: h } ), /* @__PURE__ */ c(vt, { actions: ze, i18n: h }) ] }), /* @__PURE__ */ c( lt, { table: i, tableContainerRef: q, loading: z, data: j, emptyComponent: Re, notFoundMessage: h?.notFoundMessage ?? "N/A", onAddFilter: Fe, maxSortedColumns: le, i18n: h, isServerSide: a, filterBadges: C, advancedFilterBadge: x, searchbarGlobalFilter: m } ), !_e && /* @__PURE__ */ c( ut, { table: i, isServerSide: a, clientPagination: K, serverState: a ? r : void 0, onServerStateChange: a && g ? (e) => { G(e), L(e); } : void 0, totalItems: g?.totalItems, i18n: h } ) ] } ); } export { Pt as DataTable };