UNPKG

analytica-frontend-lib

Version:

Repositório público dos componentes utilizados nas plataformas da Analytica Ensino

484 lines (456 loc) 18 kB
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _chunkJL5R5KTYjs = require('./chunk-JL5R5KTY.js'); var _chunkNEDUOGWUjs = require('./chunk-NEDUOGWU.js'); var _chunkEKKSTC6Qjs = require('./chunk-EKKSTC6Q.js'); var _chunkTN3AYOMVjs = require('./chunk-TN3AYOMV.js'); // src/components/Table/Table.tsx var _react = require('react'); var _ArrowUp = require('@phosphor-icons/react/dist/csr/ArrowUp'); var _ArrowDown = require('@phosphor-icons/react/dist/csr/ArrowDown'); var _jsxruntime = require('react/jsx-runtime'); var getUrlKeys = (prefix) => ({ sortBy: prefix ? `${prefix}_sortBy` : "sortBy", sortOrder: prefix ? `${prefix}_sortOrder` : "sortOrder", /** Contrato antigo (`sort=ASC`), ainda lido para não quebrar links salvos. */ legacySort: prefix ? `${prefix}_sort` : "sort" }); function useTableSort(data, options = {}) { const { syncWithUrl = false, mode = "client", urlKeyPrefix, allowedColumns, defaultSort, onSortChange } = options; const urlKeys = _react.useMemo.call(void 0, () => getUrlKeys(urlKeyPrefix), [urlKeyPrefix]); const allowedColumnsRef = _react.useRef.call(void 0, allowedColumns); allowedColumnsRef.current = allowedColumns; const onSortChangeRef = _react.useRef.call(void 0, onSortChange); onSortChangeRef.current = onSortChange; const defaultSortRef = _react.useRef.call(void 0, defaultSort); defaultSortRef.current = defaultSort; const readFromUrl = _react.useCallback.call(void 0, () => { const fallback = defaultSortRef.current ? { column: defaultSortRef.current.sortBy, direction: defaultSortRef.current.sortOrder } : { column: null, direction: null }; if (!syncWithUrl || globalThis.window === void 0) { return fallback; } const params = new URLSearchParams(globalThis.location.search); const column = params.get(urlKeys.sortBy); if (!column) return fallback; const rawOrder = _nullishCoalesce(params.get(urlKeys.sortOrder), () => ( params.get(urlKeys.legacySort))); const direction = _optionalChain([rawOrder, 'optionalAccess', _ => _.toLowerCase, 'call', _2 => _2()]); if (direction !== "asc" && direction !== "desc") return fallback; const allowed = allowedColumnsRef.current; if (allowed && !allowed.includes(column)) return fallback; return { column, direction }; }, [syncWithUrl, urlKeys]); const [initialState] = _react.useState.call(void 0, readFromUrl); const [sortColumn, setSortColumn] = _react.useState.call(void 0, initialState.column ); const [sortDirection, setSortDirection] = _react.useState.call(void 0, initialState.direction ); const hasWrittenUrlRef = _react.useRef.call(void 0, false); _react.useEffect.call(void 0, () => { if (!syncWithUrl || globalThis.window === void 0) return; const url = new URL(globalThis.location.href); const params = url.searchParams; if (sortColumn && sortDirection) { params.set(urlKeys.sortBy, sortColumn); params.set(urlKeys.sortOrder, sortDirection); params.delete(urlKeys.legacySort); hasWrittenUrlRef.current = true; } else if (hasWrittenUrlRef.current) { params.delete(urlKeys.sortBy); params.delete(urlKeys.sortOrder); params.delete(urlKeys.legacySort); } else { return; } globalThis.history.replaceState({}, "", url.toString()); }, [sortColumn, sortDirection, syncWithUrl, urlKeys]); _react.useEffect.call(void 0, () => { if (!syncWithUrl || globalThis.window === void 0) return; const handlePopState = () => { const next = readFromUrl(); setSortColumn(next.column); setSortDirection(next.direction); }; globalThis.addEventListener("popstate", handlePopState); return () => globalThis.removeEventListener("popstate", handlePopState); }, [syncWithUrl, readFromUrl]); const handleSort = (column) => { if (sortColumn === column && sortDirection === "asc") { setSortDirection("desc"); } else if (sortColumn === column && sortDirection === "desc") { setSortColumn(null); setSortDirection(null); } else { setSortColumn(column); setSortDirection("asc"); } _optionalChain([onSortChangeRef, 'access', _3 => _3.current, 'optionalCall', _4 => _4()]); }; const sortedData = _react.useMemo.call(void 0, () => { if (mode === "server" || !sortColumn || !sortDirection) { return data; } return [...data].sort((a, b) => { const aValue = a[sortColumn]; const bValue = b[sortColumn]; if (typeof aValue === "string" && typeof bValue === "string") { const comparison = aValue.localeCompare(bValue); return sortDirection === "asc" ? comparison : -comparison; } if (typeof aValue === "number" && typeof bValue === "number") { return sortDirection === "asc" ? aValue - bValue : bValue - aValue; } return 0; }); }, [data, sortColumn, sortDirection, mode]); return { sortedData, sortColumn, sortDirection, handleSort }; } var renderHeaderElements = (children) => { return _react.Children.map(children, (child) => { if (_react.isValidElement.call(void 0, child) && (child.type === TableCaption || child.type === TableHeader)) { return child; } return null; }); }; var getNoSearchResultContent = (config, defaultTitle, defaultDescription) => { if (config.component) { return config.component; } if (config.image) { return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkEKKSTC6Qjs.NoSearchResult_default, { image: config.image, title: config.title || defaultTitle, description: config.description || defaultDescription } ); } return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "text-center", children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-text-600 text-lg font-semibold mb-2", children: config.title || defaultTitle }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-text-500 text-sm", children: config.description || defaultDescription }) ] }); }; var getEmptyStateContent = (config, defaultTitle, defaultDescription) => { if (_optionalChain([config, 'optionalAccess', _5 => _5.component])) { return config.component; } return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkJL5R5KTYjs.EmptyState_default, { image: _optionalChain([config, 'optionalAccess', _6 => _6.image]), title: _optionalChain([config, 'optionalAccess', _7 => _7.title]) || defaultTitle, description: _optionalChain([config, 'optionalAccess', _8 => _8.description]) || defaultDescription, buttonText: _optionalChain([config, 'optionalAccess', _9 => _9.buttonText]), buttonIcon: _optionalChain([config, 'optionalAccess', _10 => _10.buttonIcon]), onButtonClick: _optionalChain([config, 'optionalAccess', _11 => _11.onButtonClick]), buttonVariant: _optionalChain([config, 'optionalAccess', _12 => _12.buttonVariant]), buttonAction: _optionalChain([config, 'optionalAccess', _13 => _13.buttonAction]) } ); }; var renderTableWrapper = (variant, tableRef, className, children, stateContent, tableProps) => { return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: _chunkTN3AYOMVjs.cn.call(void 0, "relative w-full overflow-x-auto", variant === "default" && "border border-border-200 rounded-xl" ), children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "table", { ref: tableRef, className: _chunkTN3AYOMVjs.cn.call(void 0, "analytica-table w-full caption-bottom text-sm border-separate border-spacing-0", className ), ...tableProps, children: renderHeaderElements(children) } ), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "py-8 flex justify-center", children: stateContent }) ] } ); }; var Table = _react.forwardRef.call(void 0, ({ variant = "default", className, children, showLoading = false, loadingState, showNoSearchResult = false, noSearchResultState, showEmpty = false, emptyState, ...props }, ref) => { const defaultNoSearchResultState = { title: "Nenhum resultado encontrado", description: "N\xE3o encontramos nenhum resultado com esse nome. Tente revisar a busca ou usar outra palavra-chave." }; const defaultEmptyState = { title: "Nenhum dado dispon\xEDvel", description: "N\xE3o h\xE1 dados para exibir no momento." }; const finalNoSearchResultState = noSearchResultState || defaultNoSearchResultState; const finalEmptyState = emptyState || defaultEmptyState; if (showLoading) { const loadingContent = _optionalChain([loadingState, 'optionalAccess', _14 => _14.component]) || /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkNEDUOGWUjs.SkeletonTable, { rows: 5, columns: 4, showHeader: false }); return renderTableWrapper( variant, ref, className, children, loadingContent, props ); } if (showNoSearchResult) { const noSearchContent = getNoSearchResultContent( finalNoSearchResultState, defaultNoSearchResultState.title || "", defaultNoSearchResultState.description || "" ); return renderTableWrapper( variant, ref, className, children, noSearchContent, props ); } if (showEmpty) { const emptyContent = getEmptyStateContent( finalEmptyState, defaultEmptyState.title || "Nenhum dado dispon\xEDvel", defaultEmptyState.description || "N\xE3o h\xE1 dados para exibir no momento." ); return renderTableWrapper( variant, ref, className, children, emptyContent, props ); } return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: _chunkTN3AYOMVjs.cn.call(void 0, "relative w-full overflow-x-auto", variant === "default" && "border border-border-200 rounded-xl" ), children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "table", { ref, className: _chunkTN3AYOMVjs.cn.call(void 0, variant === "default" && "analytica-table", variant === "default" && "border-separate border-spacing-0", "w-full caption-bottom text-sm", className ), ...props, children: [ !_react.Children.toArray(children).some( (child) => _react.isValidElement.call(void 0, child) && child.type === TableCaption ) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "caption", { className: "sr-only", children: "My Table" }), children ] } ) } ); } ); Table.displayName = "Table"; var TableHeader = _react.forwardRef.call(void 0, ({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "thead", { ref, className: _chunkTN3AYOMVjs.cn.call(void 0, "[&_tr:first-child]:border-0", className), ...props } )); TableHeader.displayName = "TableHeader"; var TableBody = _react.forwardRef.call(void 0, ({ className, variant = "default", ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "tbody", { ref, className: _chunkTN3AYOMVjs.cn.call(void 0, "[&_tr:last-child]:border-border-200", variant === "default" && "border-t border-border-200", className ), ...props } ) ); TableBody.displayName = "TableBody"; var TableFooter = _react.forwardRef.call(void 0, ({ variant = "default", className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "tfoot", { ref, className: _chunkTN3AYOMVjs.cn.call(void 0, "bg-background-50 font-medium [&>tr]:last:border-b-0 px-6 py-3.5", variant === "default" && "border-t border-border-200", className ), ...props } ) ); TableFooter.displayName = "TableFooter"; var VARIANT_STATES_ROW = { default: { default: "border border-border-200", defaultBorderless: "border-b border-border-200", borderless: "" }, selected: { default: "border-b-2 border-indicator-primary", defaultBorderless: "border-b border-indicator-primary", borderless: "bg-indicator-primary/10" }, invalid: { default: "border-b-2 border-indicator-error", defaultBorderless: "border-b border-indicator-error", borderless: "bg-indicator-error/10" }, disabled: { default: "border-b border-border-100 bg-background-50 opacity-50 cursor-not-allowed", defaultBorderless: "border-b border-border-100 bg-background-50 opacity-50 cursor-not-allowed", borderless: "bg-background-50 opacity-50 cursor-not-allowed" } }; var TableRow = _react.forwardRef.call(void 0, ({ variant = "default", state = "default", clickable = false, className, ...props }, ref) => { return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "tr", { ref, className: _chunkTN3AYOMVjs.cn.call(void 0, "transition-colors", state === "disabled" ? "" : "hover:bg-muted/50", state === "disabled" || !clickable ? "" : "cursor-pointer", VARIANT_STATES_ROW[state][variant], className ), "aria-disabled": state === "disabled", ...props } ); } ); TableRow.displayName = "TableRow"; var TableHead = _react.forwardRef.call(void 0, ({ className, sortable = false, sortDirection = null, onSort, filterSlot, children, ...props }, ref) => { const handleClick = () => { if (sortable && onSort) { onSort(); } }; const ariaSort = (() => { if (!sortable) return void 0; if (sortDirection === "asc") return "ascending"; if (sortDirection === "desc") return "descending"; return "none"; })(); const sortArrow = sortable && sortDirection && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "flex shrink-0", children: sortDirection === "asc" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _ArrowUp.ArrowUpIcon, { size: 16, className: "text-text-800" }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _ArrowDown.ArrowDownIcon, { size: 16, className: "text-text-800" }) }); return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "th", { ref, className: _chunkTN3AYOMVjs.cn.call(void 0, "h-10 px-6 py-3.5 text-left align-middle font-bold text-base text-text-800 tracking-[0.2px] leading-none [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px] whitespace-nowrap", sortable && "cursor-pointer select-none hover:bg-muted/30", className ), "aria-sort": ariaSort, ...props, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-2", children: [ sortable ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "button", { type: "button", onClick: handleClick, className: _chunkTN3AYOMVjs.cn.call(void 0, "flex items-center gap-2 text-left cursor-pointer select-none hover:opacity-80", // Span the cell so pointer users keep a full-width target — but // not when a filter caret follows, or it would be shoved to the // far edge of the column instead of sitting next to the label. !filterSlot && "flex-1" ), children: [ children, sortArrow ] } ) : children, filterSlot ] }) } ); } ); TableHead.displayName = "TableHead"; var TableCell = _react.forwardRef.call(void 0, ({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "td", { ref, className: _chunkTN3AYOMVjs.cn.call(void 0, "p-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px] text-base font-normal text-text-800 leading-[150%] tracking-normal px-6 py-3.5 whitespace-nowrap", className ), ...props } )); TableCell.displayName = "TableCell"; var TableCaption = _react.forwardRef.call(void 0, ({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "caption", { ref, className: _chunkTN3AYOMVjs.cn.call(void 0, "border-t border-border-200 text-sm text-text-800 px-6 py-3.5", className ), ...props } )); TableCaption.displayName = "TableCaption"; var Table_default = Table; exports.useTableSort = useTableSort; exports.TableHeader = TableHeader; exports.TableBody = TableBody; exports.TableFooter = TableFooter; exports.TableRow = TableRow; exports.TableHead = TableHead; exports.TableCell = TableCell; exports.TableCaption = TableCaption; exports.Table_default = Table_default; //# sourceMappingURL=chunk-LWUL5WRW.js.map