@apipass/design-system 6.1.0 → 7.0.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/lib/charts.index.cjs +1 -1
- package/dist/lib/charts.index.js +7 -5
- package/dist/lib/charts.index.js.map +1 -1
- package/dist/lib/embedded-styles.js +2 -2
- package/dist/lib/style.css +1 -1
- package/dist/lib/ui/components/DataTable/DataTable.cjs +1 -1
- package/dist/lib/ui/components/DataTable/DataTable.cjs.map +1 -1
- package/dist/lib/ui/components/DataTable/DataTable.js +81 -83
- package/dist/lib/ui/components/DataTable/DataTable.js.map +1 -1
- package/dist/lib/ui/components/charts/PieChart/PieChart.cjs +1 -1
- package/dist/lib/ui/components/charts/PieChart/PieChart.cjs.map +1 -1
- package/dist/lib/ui/components/charts/PieChart/PieChart.js +39 -38
- package/dist/lib/ui/components/charts/PieChart/PieChart.js.map +1 -1
- package/dist/lib/ui/components/charts/PieChart/pie-chart-option.cjs +1 -1
- package/dist/lib/ui/components/charts/PieChart/pie-chart-option.cjs.map +1 -1
- package/dist/lib/ui/components/charts/PieChart/pie-chart-option.js +65 -71
- package/dist/lib/ui/components/charts/PieChart/pie-chart-option.js.map +1 -1
- package/dist/lib/ui/components/charts/TopList/TopList.cjs +2 -0
- package/dist/lib/ui/components/charts/TopList/TopList.cjs.map +1 -0
- package/dist/lib/ui/components/charts/TopList/TopList.js +79 -0
- package/dist/lib/ui/components/charts/TopList/TopList.js.map +1 -0
- package/dist/lib/ui/components/charts/TopList/top-list-option.cjs +2 -0
- package/dist/lib/ui/components/charts/TopList/top-list-option.cjs.map +1 -0
- package/dist/lib/ui/components/charts/TopList/top-list-option.js +178 -0
- package/dist/lib/ui/components/charts/TopList/top-list-option.js.map +1 -0
- package/dist/lib/ui/components/charts/chart-share.cjs +2 -0
- package/dist/lib/ui/components/charts/chart-share.cjs.map +1 -0
- package/dist/lib/ui/components/charts/chart-share.js +11 -0
- package/dist/lib/ui/components/charts/chart-share.js.map +1 -0
- package/dist/lib/ui/primitives/Table/Table.cjs +1 -1
- package/dist/lib/ui/primitives/Table/Table.cjs.map +1 -1
- package/dist/lib/ui/primitives/Table/Table.js +53 -55
- package/dist/lib/ui/primitives/Table/Table.js.map +1 -1
- package/dist/types/charts.index.d.ts +1 -0
- package/dist/types/ui/components/DataTable/DataTable.d.ts +1 -3
- package/dist/types/ui/components/charts/PieChart/pie-chart-option.d.ts +0 -1
- package/dist/types/ui/components/charts/TopList/TopList.d.ts +13 -0
- package/dist/types/ui/components/charts/TopList/top-list-option.d.ts +24 -0
- package/dist/types/ui/components/charts/chart-share.d.ts +1 -0
- package/dist/types/ui/primitives/Table/Table.d.ts +1 -2
- package/package.json +1 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("react/jsx-runtime"),h=require("react");;/* empty css */const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("react/jsx-runtime"),h=require("react");;/* empty css */const ce=require("../../primitives/Search/Search.cjs"),o=require("../../primitives/Table/Table.cjs"),de=require("../../icons/IconChevronDown.cjs"),ue=require("../../icons/IconChevronRight.cjs"),he=require("../../primitives/Pagination/Pagination.cjs"),be=require("../../primitives/PermissionGate/PermissionGate.cjs"),ge=require("../../layout/Flex/Flex.cjs"),xe=new Intl.Collator(void 0,{numeric:!0,sensitivity:"base"});function fe(n,s){return n==null||s==null?n==null?s==null?0:1:-1:n instanceof Date&&s instanceof Date?n.getTime()-s.getTime():typeof n=="number"&&typeof s=="number"?n-s:xe.compare(String(n),String(s))}function pe(n,s,d){const i=s.sortValue??(b=>b[s.key]),m=d==="descending"?-1:1;return[...n].sort((b,g)=>fe(i(b),i(g))*m)}function we({action:n,item:s}){const d=n.isAllowed!==!1,i=a.jsx("button",{type:"button",className:"data-table-row-action-btn","aria-label":n.label,disabled:!d,onClick:d?()=>n.onPress(s):void 0,children:n.icon});return d?i:a.jsx(be.PermissionGate,{isAllowed:!1,noAccessLabel:n.noAccessLabel??"",children:i})}function G({columns:n,data:s,actions:d,rowActions:i,rowActionsLabel:m="",selectable:b=!1,selectionType:g="checkbox",selectedKeys:H,onSelectionChange:O,defaultSortDescriptor:V,sortDescriptor:$,onSortChange:S,searchPlaceholder:Q="Search...",searchKeys:C=[],isLoading:z=!1,loadingMessage:q="Loading...",emptyMessage:J="No records found",previousLabel:U="Previous",nextLabel:W="Next",pageSize:x=10,nestedColumns:k,getNestedData:D,nestedLoadingMessage:X="Loading...",nestedEmptyMessage:Y="No records found",nestedSearchKeys:Z,nestedSearchPlaceholder:_,nestedActions:N,nestedPageSize:A}){const[y,K]=h.useState(""),[ee,T]=h.useState(1),[ae,te]=h.useState(V),u=$??ae,[L,ne]=h.useState(new Set),[I,f]=h.useState(new Map),v=!!D&&!!k,M=!!i;function E(e,t){ne(r=>{const c=new Set(r);return t?c.add(e):c.delete(e),c})}function se(e){const t=e.id,r=!L.has(t);if(E(t,r),!r||I.has(t))return;const c=D(e);c instanceof Promise?(f(l=>new Map(l).set(t,{status:"loading",data:[]})),c.then(l=>{f(j=>new Map(j).set(t,{status:"loaded",data:l}))},()=>{f(l=>{const j=new Map(l);return j.delete(t),j}),E(t,!1)})):f(l=>new Map(l).set(t,{status:"loaded",data:c}))}const p=C.length>0,le=p||!!d,w=h.useMemo(()=>{if(!y.trim()||!p)return s;const e=y.toLowerCase();return s.filter(t=>C.some(r=>String(t[r]??"").toLowerCase().includes(e)))},[s,y,C,p]),P=n.find(e=>e.sortable&&String(e.key)===String(u==null?void 0:u.column)),F=h.useMemo(()=>P&&u?pe(w,P,u.direction):w,[w,P,u]);function re(e){te(e),T(1),S==null||S(e)}const B=Math.max(1,Math.ceil(F.length/x)),R=Math.min(ee,B),oe=F.slice((R-1)*x,R*x);function ie(e,t){return t.render?t.render(e):String(e[t.key]??"")}return a.jsxs(ge.Flex,{direction:"column",gap:"300",className:"data-table",children:[le&&a.jsxs("div",{className:"data-table-toolbar",children:[p&&a.jsx(ce.Search,{placeholder:Q,onSearch:e=>{K(e),T(1)},className:"data-table-search"}),d&&a.jsx("div",{className:"data-table-actions",children:d})]}),z?a.jsx("div",{role:"status","aria-live":"polite","aria-label":q,className:"data-table-status",children:q}):w.length===0?a.jsx("div",{role:"status",className:"data-table-status data-table-empty",children:J}):a.jsxs(o.Table,{selectionMode:b?g==="radio"?"single":"multiple":"none",selectionType:g,selectedKeys:H,onSelectionChange:O,sortDescriptor:u,onSortChange:re,children:[a.jsxs(o.TableHead,{children:[v&&a.jsx(o.TableColumn,{className:"data-table-expand-col"}),n.map((e,t)=>a.jsx(o.TableColumn,{id:String(e.key),align:e.align,allowsSorting:e.sortable,isRowHeader:t===0,children:e.label},String(e.key))),M&&a.jsx(o.TableColumn,{align:"right",className:"data-table-row-actions-col",children:m})]}),a.jsx(o.TableBody,{children:oe.flatMap(e=>{const t=L.has(e.id),r=I.get(e.id),c=[a.jsxs(o.TableRow,{id:e.id,children:[v&&a.jsx(o.TableCell,{className:"data-table-expand-cell",children:a.jsx("button",{type:"button",className:"data-table-expand-btn","aria-label":t?"Collapse row":"Expand row","aria-expanded":t,onClick:()=>se(e),children:t?a.jsx(de.IconChevronDown,{size:"16"}):a.jsx(ue.IconChevronRight,{size:"16"})})}),n.map(l=>a.jsx(o.TableCell,{align:l.align,children:ie(e,l)},String(l.key))),M&&a.jsx(o.TableCell,{align:"right",className:"data-table-row-actions-cell",children:a.jsx("div",{className:"data-table-row-actions",children:(typeof i=="function"?i(e):i).map(l=>a.jsx(we,{action:l,item:e},l.key))})})]},e.id)];return t&&c.push(a.jsx(o.TableRow,{id:`${e.id}-nested`,className:"data-table-nested-row",children:a.jsx(o.TableCell,{colSpan:n.length+(v?1:0)+(b?1:0)+(M?1:0),className:"data-table-nested-cell",children:a.jsx(G,{columns:k,data:(r==null?void 0:r.data)??[],isLoading:!r||r.status==="loading",loadingMessage:X,emptyMessage:Y,searchKeys:Z,searchPlaceholder:_,actions:N==null?void 0:N(e),pageSize:A??x})})},`${e.id}-nested`)),c})})]}),a.jsx(he.Pagination,{page:R,totalPages:B,onPageChange:T,previousLabel:U,nextLabel:W})]})}exports.DataTable=G;
|
|
2
2
|
//# sourceMappingURL=DataTable.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataTable.cjs","sources":["../../../../../src/ui/components/DataTable/DataTable.tsx"],"sourcesContent":["import {\n Pagination,\n PermissionGate,\n Search,\n Table,\n TableBody,\n TableCell,\n TableColumn,\n TableHead,\n TableRow,\n} from \"primitives\";\nimport { Flex } from \"layout\";\nimport { IconChevronDown, IconChevronRight } from \"icons\";\nimport type { ReactNode } from \"react\";\nimport { useMemo, useState } from \"react\";\nimport type { Selection, SortDescriptor } from \"react-aria-components\";\nimport \"./datatable.css\";\n\nexport interface Column<T> {\n key: keyof T | string;\n label: string;\n align?: \"start\" | \"center\" | \"right\";\n render?: (item: T) => ReactNode;\n /** When true, the header becomes clickable and the rows can be sorted by this column. */\n sortable?: boolean;\n /** Value used to sort this column. Defaults to `item[key]`. */\n sortValue?: (item: T) => SortableValue;\n}\n\ntype SortableValue = string | number | Date | null | undefined;\n\nconst sortCollator = new Intl.Collator(undefined, { numeric: true, sensitivity: \"base\" });\n\nfunction compareSortableValues(a: SortableValue, b: SortableValue): number {\n if (a == null || b == null) return a == null ? (b == null ? 0 : 1) : -1;\n if (a instanceof Date && b instanceof Date) return a.getTime() - b.getTime();\n if (typeof a === \"number\" && typeof b === \"number\") return a - b;\n return sortCollator.compare(String(a), String(b));\n}\n\nfunction sortRows<T>(rows: T[], column: Column<T>, direction: SortDescriptor[\"direction\"]): T[] {\n const valueOf = column.sortValue ?? ((item: T) => (item as Record<string, unknown>)[column.key as string] as SortableValue);\n const directionFactor = direction === \"descending\" ? -1 : 1;\n return [...rows].sort((a, b) => compareSortableValues(valueOf(a), valueOf(b)) * directionFactor);\n}\n\nexport interface RowActionDef<T> {\n /** Unique key for this action. */\n key: string;\n /** aria-label for the button. */\n label: string;\n /** Icon element rendered inside the button. */\n icon: ReactNode;\n /** When false, button is disabled and a tooltip with `noAccessLabel` is shown. Default: true. */\n isAllowed?: boolean;\n /** Tooltip text shown when `isAllowed` is false. */\n noAccessLabel?: string;\n /** Called with the row item when the button is pressed. */\n onPress: (item: T) => void;\n}\n\nfunction RowActionButton<T>({\n action,\n item,\n}: {\n action: RowActionDef<T>;\n item: T;\n}) {\n const allowed = action.isAllowed !== false;\n const btn = (\n <button\n type=\"button\"\n className=\"data-table-row-action-btn\"\n aria-label={action.label}\n disabled={!allowed}\n onClick={allowed ? () => action.onPress(item) : undefined}\n >\n {action.icon}\n </button>\n );\n if (allowed) return btn;\n return (\n <PermissionGate isAllowed={false} noAccessLabel={action.noAccessLabel ?? \"\"}>\n {btn}\n </PermissionGate>\n );\n}\n\n// O tipo da linha aninhada é independente de T (não há relação genérica entre linha pai e linhas\n// filhas), então \"any\" é usado deliberadamente como fronteira de erasure de tipo.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype NestedStatus = { status: \"loading\"; data: never[] } | { status: \"loaded\"; data: any[] };\n\nexport interface DataTableProps<T extends { id: string }> {\n columns: Column<T>[];\n data: T[];\n actions?: ReactNode;\n /** Per-row action buttons rendered in a dedicated last column. */\n rowActions?: RowActionDef<T>[] | ((item: T) => RowActionDef<T>[]);\n /** Label for the row actions column header. Defaults to empty string. */\n rowActionsLabel?: string;\n /**\n * When true, renders a selection column before the first data column — a per-row control on\n * every row (see `selectionType`), plus a \"select all\" checkbox in the header when\n * `selectionType` is \"checkbox\". Off by default.\n */\n selectable?: boolean;\n /**\n * Visual style of the built-in selection control. \"checkbox\" (default) allows selecting\n * multiple rows and shows a \"select all\" in the header. \"radio\" restricts selection to a\n * single row (no \"select all\" — there is nothing to select all *to* with one choice) and\n * renders a round control instead of a checkbox.\n */\n selectionType?: \"checkbox\" | \"radio\";\n /** When true, draws vertical lines between columns. Off by default. */\n grid?: boolean;\n /** Controlled selection state. Omit to let the table manage its own selection internally. */\n selectedKeys?: Selection;\n onSelectionChange?: (keys: Selection) => void;\n /** Initial sort when the table manages its own sorting. Only columns with `sortable` can be sorted. */\n defaultSortDescriptor?: SortDescriptor;\n /** Controlled sort state. Omit to let the table manage its own sorting internally. */\n sortDescriptor?: SortDescriptor;\n onSortChange?: (descriptor: SortDescriptor) => void;\n searchPlaceholder?: string;\n searchKeys?: (keyof T)[];\n isLoading?: boolean;\n loadingMessage?: string;\n emptyMessage?: string;\n previousLabel?: string;\n nextLabel?: string;\n pageSize?: number;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- linha aninhada é de tipo independente de T\n nestedColumns?: Column<any>[];\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- linha aninhada é de tipo independente de T\n getNestedData?: (item: T) => any[] | Promise<any[]>;\n nestedLoadingMessage?: string;\n nestedEmptyMessage?: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- linha aninhada é de tipo independente de T\n nestedSearchKeys?: (keyof any)[];\n nestedSearchPlaceholder?: string;\n nestedActions?: (item: T) => ReactNode;\n nestedPageSize?: number;\n}\n\nexport function DataTable<T extends { id: string }>({\n columns,\n data,\n actions,\n rowActions,\n rowActionsLabel = \"\",\n selectable = false,\n selectionType = \"checkbox\",\n grid = false,\n selectedKeys,\n onSelectionChange,\n defaultSortDescriptor,\n sortDescriptor: controlledSortDescriptor,\n onSortChange,\n searchPlaceholder = \"Search...\",\n searchKeys = [],\n isLoading = false,\n loadingMessage = \"Loading...\",\n emptyMessage = \"No records found\",\n previousLabel = \"Previous\",\n nextLabel = \"Next\",\n pageSize = 10,\n nestedColumns,\n getNestedData,\n nestedLoadingMessage = \"Loading...\",\n nestedEmptyMessage = \"No records found\",\n nestedSearchKeys,\n nestedSearchPlaceholder,\n nestedActions,\n nestedPageSize,\n}: DataTableProps<T>) {\n const [query, setQuery] = useState(\"\");\n const [page, setPage] = useState(1);\n const [internalSortDescriptor, setInternalSortDescriptor] = useState(defaultSortDescriptor);\n const sortDescriptor = controlledSortDescriptor ?? internalSortDescriptor;\n const [expanded, setExpanded] = useState<Set<string>>(new Set());\n const [nestedCache, setNestedCache] = useState<Map<string, NestedStatus>>(new Map());\n\n const hasNested = !!getNestedData && !!nestedColumns;\n const hasRowActions = !!rowActions;\n\n function setRowExpanded(id: string, isExpanded: boolean) {\n setExpanded((prev) => {\n const next = new Set(prev);\n if (isExpanded) next.add(id);\n else next.delete(id);\n return next;\n });\n }\n\n // A carga fica fora do updater do setExpanded: o React pode chamar updaters mais de uma\n // vez (StrictMode), o que dispararia getNestedData em dobro.\n function toggleRow(item: T) {\n const id = item.id;\n const willExpand = !expanded.has(id);\n setRowExpanded(id, willExpand);\n if (!willExpand || nestedCache.has(id)) return;\n\n const result = getNestedData!(item);\n if (result instanceof Promise) {\n setNestedCache((c) => new Map(c).set(id, { status: \"loading\", data: [] }));\n result.then(\n (rows) => {\n setNestedCache((c) => new Map(c).set(id, { status: \"loaded\", data: rows }));\n },\n () => {\n // Na falha, descarta a entrada e recolhe a linha: expandir de novo refaz a carga,\n // em vez de a linha ficar presa em \"loading\".\n setNestedCache((c) => {\n const next = new Map(c);\n next.delete(id);\n return next;\n });\n setRowExpanded(id, false);\n },\n );\n } else {\n setNestedCache((c) => new Map(c).set(id, { status: \"loaded\", data: result }));\n }\n }\n\n const hasSearch = searchKeys.length > 0;\n const hasToolbar = hasSearch || !!actions;\n\n const filtered = useMemo(() => {\n if (!query.trim() || !hasSearch) return data;\n const lower = query.toLowerCase();\n return data.filter((item) =>\n searchKeys.some((k) =>\n String(item[k] ?? \"\")\n .toLowerCase()\n .includes(lower),\n ),\n );\n }, [data, query, searchKeys, hasSearch]);\n\n const sortColumn = columns.find((col) => col.sortable && String(col.key) === String(sortDescriptor?.column));\n\n const sorted = useMemo(\n () => (sortColumn && sortDescriptor ? sortRows(filtered, sortColumn, sortDescriptor.direction) : filtered),\n [filtered, sortColumn, sortDescriptor],\n );\n\n function handleSortChange(descriptor: SortDescriptor) {\n setInternalSortDescriptor(descriptor);\n setPage(1);\n onSortChange?.(descriptor);\n }\n\n const totalPages = Math.max(1, Math.ceil(sorted.length / pageSize));\n const currentPage = Math.min(page, totalPages);\n const pageData = sorted.slice(\n (currentPage - 1) * pageSize,\n currentPage * pageSize,\n );\n\n function getCell(item: T, col: Column<T>): ReactNode {\n if (col.render) return col.render(item);\n return String((item as Record<string, unknown>)[col.key as string] ?? \"\");\n }\n\n return (\n <Flex direction=\"column\" gap=\"300\" className=\"data-table\">\n {hasToolbar && (\n <div className=\"data-table-toolbar\">\n {hasSearch && (\n <Search\n placeholder={searchPlaceholder}\n onSearch={(v) => {\n setQuery(v);\n setPage(1);\n }}\n className=\"data-table-search\"\n />\n )}\n {actions && <div className=\"data-table-actions\">{actions}</div>}\n </div>\n )}\n\n {isLoading ? (\n <div\n role=\"status\"\n aria-live=\"polite\"\n aria-label={loadingMessage}\n className=\"data-table-status\"\n >\n {loadingMessage}\n </div>\n ) : filtered.length === 0 ? (\n <div role=\"status\" className=\"data-table-status data-table-empty\">\n {emptyMessage}\n </div>\n ) : (\n <Table\n selectionMode={selectable ? (selectionType === \"radio\" ? \"single\" : \"multiple\") : \"none\"}\n selectionType={selectionType}\n grid={grid}\n selectedKeys={selectedKeys}\n onSelectionChange={onSelectionChange}\n sortDescriptor={sortDescriptor}\n onSortChange={handleSortChange}\n >\n <TableHead>\n {hasNested && <TableColumn className=\"data-table-expand-col\" />}\n {columns.map((col, idx) => (\n <TableColumn\n key={String(col.key)}\n id={String(col.key)}\n align={col.align}\n allowsSorting={col.sortable}\n isRowHeader={idx === 0}\n >\n {col.label}\n </TableColumn>\n ))}\n {hasRowActions && (\n <TableColumn align=\"right\" className=\"data-table-row-actions-col\">\n {rowActionsLabel}\n </TableColumn>\n )}\n </TableHead>\n <TableBody>\n {pageData.flatMap((item) => {\n const isExpanded = expanded.has(item.id);\n const cached = nestedCache.get(item.id);\n const rows: ReactNode[] = [\n <TableRow key={item.id} id={item.id}>\n {hasNested && (\n <TableCell className=\"data-table-expand-cell\">\n <button\n type=\"button\"\n className=\"data-table-expand-btn\"\n aria-label={isExpanded ? \"Collapse row\" : \"Expand row\"}\n aria-expanded={isExpanded}\n onClick={() => toggleRow(item)}\n >\n {isExpanded ? (\n <IconChevronDown size=\"16\" />\n ) : (\n <IconChevronRight size=\"16\" />\n )}\n </button>\n </TableCell>\n )}\n {columns.map((col) => (\n <TableCell key={String(col.key)} align={col.align}>\n {getCell(item, col)}\n </TableCell>\n ))}\n {hasRowActions && (\n <TableCell align=\"right\" className=\"data-table-row-actions-cell\">\n <div className=\"data-table-row-actions\">\n {(typeof rowActions === \"function\"\n ? rowActions(item)\n : rowActions!\n ).map((action) => (\n <RowActionButton key={action.key} action={action} item={item} />\n ))}\n </div>\n </TableCell>\n )}\n </TableRow>,\n ];\n if (isExpanded) {\n rows.push(\n <TableRow key={`${item.id}-nested`} id={`${item.id}-nested`} className=\"data-table-nested-row\">\n <TableCell\n colSpan={\n columns.length +\n (hasNested ? 1 : 0) +\n (selectable ? 1 : 0) +\n (hasRowActions ? 1 : 0)\n }\n className=\"data-table-nested-cell\"\n >\n <DataTable\n columns={nestedColumns!}\n data={cached?.data ?? []}\n isLoading={!cached || cached.status === \"loading\"}\n loadingMessage={nestedLoadingMessage}\n emptyMessage={nestedEmptyMessage}\n searchKeys={nestedSearchKeys}\n searchPlaceholder={nestedSearchPlaceholder}\n actions={nestedActions?.(item)}\n pageSize={nestedPageSize ?? pageSize}\n />\n </TableCell>\n </TableRow>,\n );\n }\n return rows;\n })}\n </TableBody>\n </Table>\n )}\n\n <Pagination\n page={currentPage}\n totalPages={totalPages}\n onPageChange={setPage}\n previousLabel={previousLabel}\n nextLabel={nextLabel}\n />\n </Flex>\n );\n}\n"],"names":["sortCollator","compareSortableValues","a","b","sortRows","rows","column","direction","valueOf","item","directionFactor","RowActionButton","action","allowed","btn","jsx","PermissionGate","DataTable","columns","data","actions","rowActions","rowActionsLabel","selectable","selectionType","grid","selectedKeys","onSelectionChange","defaultSortDescriptor","controlledSortDescriptor","onSortChange","searchPlaceholder","searchKeys","isLoading","loadingMessage","emptyMessage","previousLabel","nextLabel","pageSize","nestedColumns","getNestedData","nestedLoadingMessage","nestedEmptyMessage","nestedSearchKeys","nestedSearchPlaceholder","nestedActions","nestedPageSize","query","setQuery","useState","page","setPage","internalSortDescriptor","setInternalSortDescriptor","sortDescriptor","expanded","setExpanded","nestedCache","setNestedCache","hasNested","hasRowActions","setRowExpanded","id","isExpanded","prev","next","toggleRow","willExpand","result","c","hasSearch","hasToolbar","filtered","useMemo","lower","k","sortColumn","col","sorted","handleSortChange","descriptor","totalPages","currentPage","pageData","getCell","Flex","jsxs","Search","v","Table","TableHead","TableColumn","idx","TableBody","cached","TableRow","TableCell","IconChevronDown","IconChevronRight","Pagination"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DataTable.cjs","sources":["../../../../../src/ui/components/DataTable/DataTable.tsx"],"sourcesContent":["import {\n Pagination,\n PermissionGate,\n Search,\n Table,\n TableBody,\n TableCell,\n TableColumn,\n TableHead,\n TableRow,\n} from \"primitives\";\nimport { Flex } from \"layout\";\nimport { IconChevronDown, IconChevronRight } from \"icons\";\nimport type { ReactNode } from \"react\";\nimport { useMemo, useState } from \"react\";\nimport type { Selection, SortDescriptor } from \"react-aria-components\";\nimport \"./datatable.css\";\n\nexport interface Column<T> {\n key: keyof T | string;\n label: string;\n align?: \"start\" | \"center\" | \"right\";\n render?: (item: T) => ReactNode;\n /** When true, the header becomes clickable and the rows can be sorted by this column. */\n sortable?: boolean;\n /** Value used to sort this column. Defaults to `item[key]`. */\n sortValue?: (item: T) => SortableValue;\n}\n\ntype SortableValue = string | number | Date | null | undefined;\n\nconst sortCollator = new Intl.Collator(undefined, { numeric: true, sensitivity: \"base\" });\n\nfunction compareSortableValues(a: SortableValue, b: SortableValue): number {\n if (a == null || b == null) return a == null ? (b == null ? 0 : 1) : -1;\n if (a instanceof Date && b instanceof Date) return a.getTime() - b.getTime();\n if (typeof a === \"number\" && typeof b === \"number\") return a - b;\n return sortCollator.compare(String(a), String(b));\n}\n\nfunction sortRows<T>(rows: T[], column: Column<T>, direction: SortDescriptor[\"direction\"]): T[] {\n const valueOf = column.sortValue ?? ((item: T) => (item as Record<string, unknown>)[column.key as string] as SortableValue);\n const directionFactor = direction === \"descending\" ? -1 : 1;\n return [...rows].sort((a, b) => compareSortableValues(valueOf(a), valueOf(b)) * directionFactor);\n}\n\nexport interface RowActionDef<T> {\n /** Unique key for this action. */\n key: string;\n /** aria-label for the button. */\n label: string;\n /** Icon element rendered inside the button. */\n icon: ReactNode;\n /** When false, button is disabled and a tooltip with `noAccessLabel` is shown. Default: true. */\n isAllowed?: boolean;\n /** Tooltip text shown when `isAllowed` is false. */\n noAccessLabel?: string;\n /** Called with the row item when the button is pressed. */\n onPress: (item: T) => void;\n}\n\nfunction RowActionButton<T>({\n action,\n item,\n}: {\n action: RowActionDef<T>;\n item: T;\n}) {\n const allowed = action.isAllowed !== false;\n const btn = (\n <button\n type=\"button\"\n className=\"data-table-row-action-btn\"\n aria-label={action.label}\n disabled={!allowed}\n onClick={allowed ? () => action.onPress(item) : undefined}\n >\n {action.icon}\n </button>\n );\n if (allowed) return btn;\n return (\n <PermissionGate isAllowed={false} noAccessLabel={action.noAccessLabel ?? \"\"}>\n {btn}\n </PermissionGate>\n );\n}\n\n// O tipo da linha aninhada é independente de T (não há relação genérica entre linha pai e linhas\n// filhas), então \"any\" é usado deliberadamente como fronteira de erasure de tipo.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype NestedStatus = { status: \"loading\"; data: never[] } | { status: \"loaded\"; data: any[] };\n\nexport interface DataTableProps<T extends { id: string }> {\n columns: Column<T>[];\n data: T[];\n actions?: ReactNode;\n /** Per-row action buttons rendered in a dedicated last column. */\n rowActions?: RowActionDef<T>[] | ((item: T) => RowActionDef<T>[]);\n /** Label for the row actions column header. Defaults to empty string. */\n rowActionsLabel?: string;\n /**\n * When true, renders a selection column before the first data column — a per-row control on\n * every row (see `selectionType`), plus a \"select all\" checkbox in the header when\n * `selectionType` is \"checkbox\". Off by default.\n */\n selectable?: boolean;\n /**\n * Visual style of the built-in selection control. \"checkbox\" (default) allows selecting\n * multiple rows and shows a \"select all\" in the header. \"radio\" restricts selection to a\n * single row (no \"select all\" — there is nothing to select all *to* with one choice) and\n * renders a round control instead of a checkbox.\n */\n selectionType?: \"checkbox\" | \"radio\";\n /** Controlled selection state. Omit to let the table manage its own selection internally. */\n selectedKeys?: Selection;\n onSelectionChange?: (keys: Selection) => void;\n /** Initial sort when the table manages its own sorting. Only columns with `sortable` can be sorted. */\n defaultSortDescriptor?: SortDescriptor;\n /** Controlled sort state. Omit to let the table manage its own sorting internally. */\n sortDescriptor?: SortDescriptor;\n onSortChange?: (descriptor: SortDescriptor) => void;\n searchPlaceholder?: string;\n searchKeys?: (keyof T)[];\n isLoading?: boolean;\n loadingMessage?: string;\n emptyMessage?: string;\n previousLabel?: string;\n nextLabel?: string;\n pageSize?: number;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- linha aninhada é de tipo independente de T\n nestedColumns?: Column<any>[];\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- linha aninhada é de tipo independente de T\n getNestedData?: (item: T) => any[] | Promise<any[]>;\n nestedLoadingMessage?: string;\n nestedEmptyMessage?: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- linha aninhada é de tipo independente de T\n nestedSearchKeys?: (keyof any)[];\n nestedSearchPlaceholder?: string;\n nestedActions?: (item: T) => ReactNode;\n nestedPageSize?: number;\n}\n\nexport function DataTable<T extends { id: string }>({\n columns,\n data,\n actions,\n rowActions,\n rowActionsLabel = \"\",\n selectable = false,\n selectionType = \"checkbox\",\n selectedKeys,\n onSelectionChange,\n defaultSortDescriptor,\n sortDescriptor: controlledSortDescriptor,\n onSortChange,\n searchPlaceholder = \"Search...\",\n searchKeys = [],\n isLoading = false,\n loadingMessage = \"Loading...\",\n emptyMessage = \"No records found\",\n previousLabel = \"Previous\",\n nextLabel = \"Next\",\n pageSize = 10,\n nestedColumns,\n getNestedData,\n nestedLoadingMessage = \"Loading...\",\n nestedEmptyMessage = \"No records found\",\n nestedSearchKeys,\n nestedSearchPlaceholder,\n nestedActions,\n nestedPageSize,\n}: DataTableProps<T>) {\n const [query, setQuery] = useState(\"\");\n const [page, setPage] = useState(1);\n const [internalSortDescriptor, setInternalSortDescriptor] = useState(defaultSortDescriptor);\n const sortDescriptor = controlledSortDescriptor ?? internalSortDescriptor;\n const [expanded, setExpanded] = useState<Set<string>>(new Set());\n const [nestedCache, setNestedCache] = useState<Map<string, NestedStatus>>(new Map());\n\n const hasNested = !!getNestedData && !!nestedColumns;\n const hasRowActions = !!rowActions;\n\n function setRowExpanded(id: string, isExpanded: boolean) {\n setExpanded((prev) => {\n const next = new Set(prev);\n if (isExpanded) next.add(id);\n else next.delete(id);\n return next;\n });\n }\n\n // A carga fica fora do updater do setExpanded: o React pode chamar updaters mais de uma\n // vez (StrictMode), o que dispararia getNestedData em dobro.\n function toggleRow(item: T) {\n const id = item.id;\n const willExpand = !expanded.has(id);\n setRowExpanded(id, willExpand);\n if (!willExpand || nestedCache.has(id)) return;\n\n const result = getNestedData!(item);\n if (result instanceof Promise) {\n setNestedCache((c) => new Map(c).set(id, { status: \"loading\", data: [] }));\n result.then(\n (rows) => {\n setNestedCache((c) => new Map(c).set(id, { status: \"loaded\", data: rows }));\n },\n () => {\n // Na falha, descarta a entrada e recolhe a linha: expandir de novo refaz a carga,\n // em vez de a linha ficar presa em \"loading\".\n setNestedCache((c) => {\n const next = new Map(c);\n next.delete(id);\n return next;\n });\n setRowExpanded(id, false);\n },\n );\n } else {\n setNestedCache((c) => new Map(c).set(id, { status: \"loaded\", data: result }));\n }\n }\n\n const hasSearch = searchKeys.length > 0;\n const hasToolbar = hasSearch || !!actions;\n\n const filtered = useMemo(() => {\n if (!query.trim() || !hasSearch) return data;\n const lower = query.toLowerCase();\n return data.filter((item) =>\n searchKeys.some((k) =>\n String(item[k] ?? \"\")\n .toLowerCase()\n .includes(lower),\n ),\n );\n }, [data, query, searchKeys, hasSearch]);\n\n const sortColumn = columns.find((col) => col.sortable && String(col.key) === String(sortDescriptor?.column));\n\n const sorted = useMemo(\n () => (sortColumn && sortDescriptor ? sortRows(filtered, sortColumn, sortDescriptor.direction) : filtered),\n [filtered, sortColumn, sortDescriptor],\n );\n\n function handleSortChange(descriptor: SortDescriptor) {\n setInternalSortDescriptor(descriptor);\n setPage(1);\n onSortChange?.(descriptor);\n }\n\n const totalPages = Math.max(1, Math.ceil(sorted.length / pageSize));\n const currentPage = Math.min(page, totalPages);\n const pageData = sorted.slice(\n (currentPage - 1) * pageSize,\n currentPage * pageSize,\n );\n\n function getCell(item: T, col: Column<T>): ReactNode {\n if (col.render) return col.render(item);\n return String((item as Record<string, unknown>)[col.key as string] ?? \"\");\n }\n\n return (\n <Flex direction=\"column\" gap=\"300\" className=\"data-table\">\n {hasToolbar && (\n <div className=\"data-table-toolbar\">\n {hasSearch && (\n <Search\n placeholder={searchPlaceholder}\n onSearch={(v) => {\n setQuery(v);\n setPage(1);\n }}\n className=\"data-table-search\"\n />\n )}\n {actions && <div className=\"data-table-actions\">{actions}</div>}\n </div>\n )}\n\n {isLoading ? (\n <div\n role=\"status\"\n aria-live=\"polite\"\n aria-label={loadingMessage}\n className=\"data-table-status\"\n >\n {loadingMessage}\n </div>\n ) : filtered.length === 0 ? (\n <div role=\"status\" className=\"data-table-status data-table-empty\">\n {emptyMessage}\n </div>\n ) : (\n <Table\n selectionMode={selectable ? (selectionType === \"radio\" ? \"single\" : \"multiple\") : \"none\"}\n selectionType={selectionType}\n selectedKeys={selectedKeys}\n onSelectionChange={onSelectionChange}\n sortDescriptor={sortDescriptor}\n onSortChange={handleSortChange}\n >\n <TableHead>\n {hasNested && <TableColumn className=\"data-table-expand-col\" />}\n {columns.map((col, idx) => (\n <TableColumn\n key={String(col.key)}\n id={String(col.key)}\n align={col.align}\n allowsSorting={col.sortable}\n isRowHeader={idx === 0}\n >\n {col.label}\n </TableColumn>\n ))}\n {hasRowActions && (\n <TableColumn align=\"right\" className=\"data-table-row-actions-col\">\n {rowActionsLabel}\n </TableColumn>\n )}\n </TableHead>\n <TableBody>\n {pageData.flatMap((item) => {\n const isExpanded = expanded.has(item.id);\n const cached = nestedCache.get(item.id);\n const rows: ReactNode[] = [\n <TableRow key={item.id} id={item.id}>\n {hasNested && (\n <TableCell className=\"data-table-expand-cell\">\n <button\n type=\"button\"\n className=\"data-table-expand-btn\"\n aria-label={isExpanded ? \"Collapse row\" : \"Expand row\"}\n aria-expanded={isExpanded}\n onClick={() => toggleRow(item)}\n >\n {isExpanded ? (\n <IconChevronDown size=\"16\" />\n ) : (\n <IconChevronRight size=\"16\" />\n )}\n </button>\n </TableCell>\n )}\n {columns.map((col) => (\n <TableCell key={String(col.key)} align={col.align}>\n {getCell(item, col)}\n </TableCell>\n ))}\n {hasRowActions && (\n <TableCell align=\"right\" className=\"data-table-row-actions-cell\">\n <div className=\"data-table-row-actions\">\n {(typeof rowActions === \"function\"\n ? rowActions(item)\n : rowActions!\n ).map((action) => (\n <RowActionButton key={action.key} action={action} item={item} />\n ))}\n </div>\n </TableCell>\n )}\n </TableRow>,\n ];\n if (isExpanded) {\n rows.push(\n <TableRow key={`${item.id}-nested`} id={`${item.id}-nested`} className=\"data-table-nested-row\">\n <TableCell\n colSpan={\n columns.length +\n (hasNested ? 1 : 0) +\n (selectable ? 1 : 0) +\n (hasRowActions ? 1 : 0)\n }\n className=\"data-table-nested-cell\"\n >\n <DataTable\n columns={nestedColumns!}\n data={cached?.data ?? []}\n isLoading={!cached || cached.status === \"loading\"}\n loadingMessage={nestedLoadingMessage}\n emptyMessage={nestedEmptyMessage}\n searchKeys={nestedSearchKeys}\n searchPlaceholder={nestedSearchPlaceholder}\n actions={nestedActions?.(item)}\n pageSize={nestedPageSize ?? pageSize}\n />\n </TableCell>\n </TableRow>,\n );\n }\n return rows;\n })}\n </TableBody>\n </Table>\n )}\n\n <Pagination\n page={currentPage}\n totalPages={totalPages}\n onPageChange={setPage}\n previousLabel={previousLabel}\n nextLabel={nextLabel}\n />\n </Flex>\n );\n}\n"],"names":["sortCollator","compareSortableValues","a","b","sortRows","rows","column","direction","valueOf","item","directionFactor","RowActionButton","action","allowed","btn","jsx","PermissionGate","DataTable","columns","data","actions","rowActions","rowActionsLabel","selectable","selectionType","selectedKeys","onSelectionChange","defaultSortDescriptor","controlledSortDescriptor","onSortChange","searchPlaceholder","searchKeys","isLoading","loadingMessage","emptyMessage","previousLabel","nextLabel","pageSize","nestedColumns","getNestedData","nestedLoadingMessage","nestedEmptyMessage","nestedSearchKeys","nestedSearchPlaceholder","nestedActions","nestedPageSize","query","setQuery","useState","page","setPage","internalSortDescriptor","setInternalSortDescriptor","sortDescriptor","expanded","setExpanded","nestedCache","setNestedCache","hasNested","hasRowActions","setRowExpanded","id","isExpanded","prev","next","toggleRow","willExpand","result","c","hasSearch","hasToolbar","filtered","useMemo","lower","k","sortColumn","col","sorted","handleSortChange","descriptor","totalPages","currentPage","pageData","getCell","Flex","jsxs","Search","v","Table","TableHead","TableColumn","idx","TableBody","cached","TableRow","TableCell","IconChevronDown","IconChevronRight","Pagination"],"mappings":"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"}
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
import { jsxs as h, jsx as t } from "react/jsx-runtime";
|
|
2
|
-
import { useState as
|
|
2
|
+
import { useState as p, useMemo as q } from "react";
|
|
3
3
|
/* empty css */
|
|
4
|
-
import { Search as
|
|
5
|
-
import { Table as pe, TableHead as
|
|
6
|
-
import { IconChevronDown as
|
|
7
|
-
import { IconChevronRight as
|
|
8
|
-
import { Pagination as
|
|
9
|
-
import { PermissionGate as
|
|
10
|
-
import { Flex as
|
|
11
|
-
const
|
|
12
|
-
function
|
|
13
|
-
return n == null ||
|
|
4
|
+
import { Search as he } from "../../primitives/Search/Search.js";
|
|
5
|
+
import { Table as pe, TableHead as fe, TableColumn as D, TableBody as ge, TableRow as G, TableCell as N } from "../../primitives/Table/Table.js";
|
|
6
|
+
import { IconChevronDown as me } from "../../icons/IconChevronDown.js";
|
|
7
|
+
import { IconChevronRight as be } from "../../icons/IconChevronRight.js";
|
|
8
|
+
import { Pagination as we } from "../../primitives/Pagination/Pagination.js";
|
|
9
|
+
import { PermissionGate as xe } from "../../primitives/PermissionGate/PermissionGate.js";
|
|
10
|
+
import { Flex as Ne } from "../../layout/Flex/Flex.js";
|
|
11
|
+
const Se = new Intl.Collator(void 0, { numeric: !0, sensitivity: "base" });
|
|
12
|
+
function ye(n, r) {
|
|
13
|
+
return n == null || r == null ? n == null ? r == null ? 0 : 1 : -1 : n instanceof Date && r instanceof Date ? n.getTime() - r.getTime() : typeof n == "number" && typeof r == "number" ? n - r : Se.compare(String(n), String(r));
|
|
14
14
|
}
|
|
15
|
-
function
|
|
16
|
-
const o =
|
|
17
|
-
return [...n].sort((u,
|
|
15
|
+
function ve(n, r, d) {
|
|
16
|
+
const o = r.sortValue ?? ((u) => u[r.key]), S = d === "descending" ? -1 : 1;
|
|
17
|
+
return [...n].sort((u, f) => ye(o(u), o(f)) * S);
|
|
18
18
|
}
|
|
19
|
-
function
|
|
19
|
+
function Ce({
|
|
20
20
|
action: n,
|
|
21
|
-
item:
|
|
21
|
+
item: r
|
|
22
22
|
}) {
|
|
23
23
|
const d = n.isAllowed !== !1, o = /* @__PURE__ */ t(
|
|
24
24
|
"button",
|
|
@@ -27,103 +27,102 @@ function Me({
|
|
|
27
27
|
className: "data-table-row-action-btn",
|
|
28
28
|
"aria-label": n.label,
|
|
29
29
|
disabled: !d,
|
|
30
|
-
onClick: d ? () => n.onPress(
|
|
30
|
+
onClick: d ? () => n.onPress(r) : void 0,
|
|
31
31
|
children: n.icon
|
|
32
32
|
}
|
|
33
33
|
);
|
|
34
|
-
return d ? o : /* @__PURE__ */ t(
|
|
34
|
+
return d ? o : /* @__PURE__ */ t(xe, { isAllowed: !1, noAccessLabel: n.noAccessLabel ?? "", children: o });
|
|
35
35
|
}
|
|
36
|
-
function
|
|
36
|
+
function Me({
|
|
37
37
|
columns: n,
|
|
38
|
-
data:
|
|
38
|
+
data: r,
|
|
39
39
|
actions: d,
|
|
40
40
|
rowActions: o,
|
|
41
41
|
rowActionsLabel: S = "",
|
|
42
42
|
selectable: u = !1,
|
|
43
|
-
selectionType:
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
sortDescriptor: U,
|
|
43
|
+
selectionType: f = "checkbox",
|
|
44
|
+
selectedKeys: O,
|
|
45
|
+
onSelectionChange: Q,
|
|
46
|
+
defaultSortDescriptor: z,
|
|
47
|
+
sortDescriptor: J,
|
|
49
48
|
onSortChange: y,
|
|
50
|
-
searchPlaceholder:
|
|
49
|
+
searchPlaceholder: U = "Search...",
|
|
51
50
|
searchKeys: v = [],
|
|
52
|
-
isLoading:
|
|
51
|
+
isLoading: W = !1,
|
|
53
52
|
loadingMessage: E = "Loading...",
|
|
54
|
-
emptyMessage:
|
|
55
|
-
previousLabel:
|
|
56
|
-
nextLabel:
|
|
53
|
+
emptyMessage: X = "No records found",
|
|
54
|
+
previousLabel: Y = "Previous",
|
|
55
|
+
nextLabel: Z = "Next",
|
|
57
56
|
pageSize: g = 10,
|
|
58
57
|
nestedColumns: I,
|
|
59
58
|
getNestedData: j,
|
|
60
|
-
nestedLoadingMessage:
|
|
61
|
-
nestedEmptyMessage:
|
|
62
|
-
nestedSearchKeys:
|
|
63
|
-
nestedSearchPlaceholder:
|
|
59
|
+
nestedLoadingMessage: _ = "Loading...",
|
|
60
|
+
nestedEmptyMessage: A = "No records found",
|
|
61
|
+
nestedSearchKeys: K,
|
|
62
|
+
nestedSearchPlaceholder: ee,
|
|
64
63
|
nestedActions: C,
|
|
65
|
-
nestedPageSize:
|
|
64
|
+
nestedPageSize: ae
|
|
66
65
|
}) {
|
|
67
|
-
const [M,
|
|
66
|
+
const [M, te] = p(""), [ne, k] = p(1), [re, le] = p(z), c = J ?? re, [B, se] = p(/* @__PURE__ */ new Set()), [F, m] = p(/* @__PURE__ */ new Map()), P = !!j && !!I, T = !!o;
|
|
68
67
|
function H(e, a) {
|
|
69
|
-
|
|
68
|
+
se((s) => {
|
|
70
69
|
const i = new Set(s);
|
|
71
70
|
return a ? i.add(e) : i.delete(e), i;
|
|
72
71
|
});
|
|
73
72
|
}
|
|
74
|
-
function
|
|
73
|
+
function oe(e) {
|
|
75
74
|
const a = e.id, s = !B.has(a);
|
|
76
75
|
if (H(a, s), !s || F.has(a)) return;
|
|
77
76
|
const i = j(e);
|
|
78
|
-
i instanceof Promise ? (m((
|
|
79
|
-
(
|
|
80
|
-
m((x) => new Map(x).set(a, { status: "loaded", data:
|
|
77
|
+
i instanceof Promise ? (m((l) => new Map(l).set(a, { status: "loading", data: [] })), i.then(
|
|
78
|
+
(l) => {
|
|
79
|
+
m((x) => new Map(x).set(a, { status: "loaded", data: l }));
|
|
81
80
|
},
|
|
82
81
|
() => {
|
|
83
|
-
m((
|
|
84
|
-
const x = new Map(
|
|
82
|
+
m((l) => {
|
|
83
|
+
const x = new Map(l);
|
|
85
84
|
return x.delete(a), x;
|
|
86
85
|
}), H(a, !1);
|
|
87
86
|
}
|
|
88
|
-
)) : m((
|
|
87
|
+
)) : m((l) => new Map(l).set(a, { status: "loaded", data: i }));
|
|
89
88
|
}
|
|
90
|
-
const b = v.length > 0,
|
|
91
|
-
if (!M.trim() || !b) return
|
|
89
|
+
const b = v.length > 0, ie = b || !!d, w = q(() => {
|
|
90
|
+
if (!M.trim() || !b) return r;
|
|
92
91
|
const e = M.toLowerCase();
|
|
93
|
-
return
|
|
92
|
+
return r.filter(
|
|
94
93
|
(a) => v.some(
|
|
95
94
|
(s) => String(a[s] ?? "").toLowerCase().includes(e)
|
|
96
95
|
)
|
|
97
96
|
);
|
|
98
|
-
}, [
|
|
99
|
-
() => R && c ?
|
|
97
|
+
}, [r, M, v, b]), R = n.find((e) => e.sortable && String(e.key) === String(c == null ? void 0 : c.column)), V = q(
|
|
98
|
+
() => R && c ? ve(w, R, c.direction) : w,
|
|
100
99
|
[w, R, c]
|
|
101
100
|
);
|
|
102
|
-
function
|
|
103
|
-
|
|
101
|
+
function de(e) {
|
|
102
|
+
le(e), k(1), y == null || y(e);
|
|
104
103
|
}
|
|
105
|
-
const $ = Math.max(1, Math.ceil(V.length / g)), L = Math.min(
|
|
104
|
+
const $ = Math.max(1, Math.ceil(V.length / g)), L = Math.min(ne, $), ce = V.slice(
|
|
106
105
|
(L - 1) * g,
|
|
107
106
|
L * g
|
|
108
107
|
);
|
|
109
|
-
function
|
|
108
|
+
function ue(e, a) {
|
|
110
109
|
return a.render ? a.render(e) : String(e[a.key] ?? "");
|
|
111
110
|
}
|
|
112
|
-
return /* @__PURE__ */ h(
|
|
113
|
-
|
|
111
|
+
return /* @__PURE__ */ h(Ne, { direction: "column", gap: "300", className: "data-table", children: [
|
|
112
|
+
ie && /* @__PURE__ */ h("div", { className: "data-table-toolbar", children: [
|
|
114
113
|
b && /* @__PURE__ */ t(
|
|
115
|
-
|
|
114
|
+
he,
|
|
116
115
|
{
|
|
117
|
-
placeholder:
|
|
116
|
+
placeholder: U,
|
|
118
117
|
onSearch: (e) => {
|
|
119
|
-
|
|
118
|
+
te(e), k(1);
|
|
120
119
|
},
|
|
121
120
|
className: "data-table-search"
|
|
122
121
|
}
|
|
123
122
|
),
|
|
124
123
|
d && /* @__PURE__ */ t("div", { className: "data-table-actions", children: d })
|
|
125
124
|
] }),
|
|
126
|
-
|
|
125
|
+
W ? /* @__PURE__ */ t(
|
|
127
126
|
"div",
|
|
128
127
|
{
|
|
129
128
|
role: "status",
|
|
@@ -132,18 +131,17 @@ function ke({
|
|
|
132
131
|
className: "data-table-status",
|
|
133
132
|
children: E
|
|
134
133
|
}
|
|
135
|
-
) : w.length === 0 ? /* @__PURE__ */ t("div", { role: "status", className: "data-table-status data-table-empty", children:
|
|
134
|
+
) : w.length === 0 ? /* @__PURE__ */ t("div", { role: "status", className: "data-table-status data-table-empty", children: X }) : /* @__PURE__ */ h(
|
|
136
135
|
pe,
|
|
137
136
|
{
|
|
138
|
-
selectionMode: u ?
|
|
139
|
-
selectionType:
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
onSelectionChange: z,
|
|
137
|
+
selectionMode: u ? f === "radio" ? "single" : "multiple" : "none",
|
|
138
|
+
selectionType: f,
|
|
139
|
+
selectedKeys: O,
|
|
140
|
+
onSelectionChange: Q,
|
|
143
141
|
sortDescriptor: c,
|
|
144
|
-
onSortChange:
|
|
142
|
+
onSortChange: de,
|
|
145
143
|
children: [
|
|
146
|
-
/* @__PURE__ */ h(
|
|
144
|
+
/* @__PURE__ */ h(fe, { children: [
|
|
147
145
|
P && /* @__PURE__ */ t(D, { className: "data-table-expand-col" }),
|
|
148
146
|
n.map((e, a) => /* @__PURE__ */ t(
|
|
149
147
|
D,
|
|
@@ -158,7 +156,7 @@ function ke({
|
|
|
158
156
|
)),
|
|
159
157
|
T && /* @__PURE__ */ t(D, { align: "right", className: "data-table-row-actions-col", children: S })
|
|
160
158
|
] }),
|
|
161
|
-
/* @__PURE__ */ t(
|
|
159
|
+
/* @__PURE__ */ t(ge, { children: ce.flatMap((e) => {
|
|
162
160
|
const a = B.has(e.id), s = F.get(e.id), i = [
|
|
163
161
|
/* @__PURE__ */ h(G, { id: e.id, children: [
|
|
164
162
|
P && /* @__PURE__ */ t(N, { className: "data-table-expand-cell", children: /* @__PURE__ */ t(
|
|
@@ -168,12 +166,12 @@ function ke({
|
|
|
168
166
|
className: "data-table-expand-btn",
|
|
169
167
|
"aria-label": a ? "Collapse row" : "Expand row",
|
|
170
168
|
"aria-expanded": a,
|
|
171
|
-
onClick: () =>
|
|
172
|
-
children: a ? /* @__PURE__ */ t(
|
|
169
|
+
onClick: () => oe(e),
|
|
170
|
+
children: a ? /* @__PURE__ */ t(me, { size: "16" }) : /* @__PURE__ */ t(be, { size: "16" })
|
|
173
171
|
}
|
|
174
172
|
) }),
|
|
175
|
-
n.map((
|
|
176
|
-
T && /* @__PURE__ */ t(N, { align: "right", className: "data-table-row-actions-cell", children: /* @__PURE__ */ t("div", { className: "data-table-row-actions", children: (typeof o == "function" ? o(e) : o).map((
|
|
173
|
+
n.map((l) => /* @__PURE__ */ t(N, { align: l.align, children: ue(e, l) }, String(l.key))),
|
|
174
|
+
T && /* @__PURE__ */ t(N, { align: "right", className: "data-table-row-actions-cell", children: /* @__PURE__ */ t("div", { className: "data-table-row-actions", children: (typeof o == "function" ? o(e) : o).map((l) => /* @__PURE__ */ t(Ce, { action: l, item: e }, l.key)) }) })
|
|
177
175
|
] }, e.id)
|
|
178
176
|
];
|
|
179
177
|
return a && i.push(
|
|
@@ -183,17 +181,17 @@ function ke({
|
|
|
183
181
|
colSpan: n.length + (P ? 1 : 0) + (u ? 1 : 0) + (T ? 1 : 0),
|
|
184
182
|
className: "data-table-nested-cell",
|
|
185
183
|
children: /* @__PURE__ */ t(
|
|
186
|
-
|
|
184
|
+
Me,
|
|
187
185
|
{
|
|
188
186
|
columns: I,
|
|
189
187
|
data: (s == null ? void 0 : s.data) ?? [],
|
|
190
188
|
isLoading: !s || s.status === "loading",
|
|
191
|
-
loadingMessage:
|
|
192
|
-
emptyMessage:
|
|
193
|
-
searchKeys:
|
|
194
|
-
searchPlaceholder:
|
|
189
|
+
loadingMessage: _,
|
|
190
|
+
emptyMessage: A,
|
|
191
|
+
searchKeys: K,
|
|
192
|
+
searchPlaceholder: ee,
|
|
195
193
|
actions: C == null ? void 0 : C(e),
|
|
196
|
-
pageSize:
|
|
194
|
+
pageSize: ae ?? g
|
|
197
195
|
}
|
|
198
196
|
)
|
|
199
197
|
}
|
|
@@ -204,18 +202,18 @@ function ke({
|
|
|
204
202
|
}
|
|
205
203
|
),
|
|
206
204
|
/* @__PURE__ */ t(
|
|
207
|
-
|
|
205
|
+
we,
|
|
208
206
|
{
|
|
209
207
|
page: L,
|
|
210
208
|
totalPages: $,
|
|
211
209
|
onPageChange: k,
|
|
212
|
-
previousLabel:
|
|
213
|
-
nextLabel:
|
|
210
|
+
previousLabel: Y,
|
|
211
|
+
nextLabel: Z
|
|
214
212
|
}
|
|
215
213
|
)
|
|
216
214
|
] });
|
|
217
215
|
}
|
|
218
216
|
export {
|
|
219
|
-
|
|
217
|
+
Me as DataTable
|
|
220
218
|
};
|
|
221
219
|
//# sourceMappingURL=DataTable.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataTable.js","sources":["../../../../../src/ui/components/DataTable/DataTable.tsx"],"sourcesContent":["import {\n Pagination,\n PermissionGate,\n Search,\n Table,\n TableBody,\n TableCell,\n TableColumn,\n TableHead,\n TableRow,\n} from \"primitives\";\nimport { Flex } from \"layout\";\nimport { IconChevronDown, IconChevronRight } from \"icons\";\nimport type { ReactNode } from \"react\";\nimport { useMemo, useState } from \"react\";\nimport type { Selection, SortDescriptor } from \"react-aria-components\";\nimport \"./datatable.css\";\n\nexport interface Column<T> {\n key: keyof T | string;\n label: string;\n align?: \"start\" | \"center\" | \"right\";\n render?: (item: T) => ReactNode;\n /** When true, the header becomes clickable and the rows can be sorted by this column. */\n sortable?: boolean;\n /** Value used to sort this column. Defaults to `item[key]`. */\n sortValue?: (item: T) => SortableValue;\n}\n\ntype SortableValue = string | number | Date | null | undefined;\n\nconst sortCollator = new Intl.Collator(undefined, { numeric: true, sensitivity: \"base\" });\n\nfunction compareSortableValues(a: SortableValue, b: SortableValue): number {\n if (a == null || b == null) return a == null ? (b == null ? 0 : 1) : -1;\n if (a instanceof Date && b instanceof Date) return a.getTime() - b.getTime();\n if (typeof a === \"number\" && typeof b === \"number\") return a - b;\n return sortCollator.compare(String(a), String(b));\n}\n\nfunction sortRows<T>(rows: T[], column: Column<T>, direction: SortDescriptor[\"direction\"]): T[] {\n const valueOf = column.sortValue ?? ((item: T) => (item as Record<string, unknown>)[column.key as string] as SortableValue);\n const directionFactor = direction === \"descending\" ? -1 : 1;\n return [...rows].sort((a, b) => compareSortableValues(valueOf(a), valueOf(b)) * directionFactor);\n}\n\nexport interface RowActionDef<T> {\n /** Unique key for this action. */\n key: string;\n /** aria-label for the button. */\n label: string;\n /** Icon element rendered inside the button. */\n icon: ReactNode;\n /** When false, button is disabled and a tooltip with `noAccessLabel` is shown. Default: true. */\n isAllowed?: boolean;\n /** Tooltip text shown when `isAllowed` is false. */\n noAccessLabel?: string;\n /** Called with the row item when the button is pressed. */\n onPress: (item: T) => void;\n}\n\nfunction RowActionButton<T>({\n action,\n item,\n}: {\n action: RowActionDef<T>;\n item: T;\n}) {\n const allowed = action.isAllowed !== false;\n const btn = (\n <button\n type=\"button\"\n className=\"data-table-row-action-btn\"\n aria-label={action.label}\n disabled={!allowed}\n onClick={allowed ? () => action.onPress(item) : undefined}\n >\n {action.icon}\n </button>\n );\n if (allowed) return btn;\n return (\n <PermissionGate isAllowed={false} noAccessLabel={action.noAccessLabel ?? \"\"}>\n {btn}\n </PermissionGate>\n );\n}\n\n// O tipo da linha aninhada é independente de T (não há relação genérica entre linha pai e linhas\n// filhas), então \"any\" é usado deliberadamente como fronteira de erasure de tipo.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype NestedStatus = { status: \"loading\"; data: never[] } | { status: \"loaded\"; data: any[] };\n\nexport interface DataTableProps<T extends { id: string }> {\n columns: Column<T>[];\n data: T[];\n actions?: ReactNode;\n /** Per-row action buttons rendered in a dedicated last column. */\n rowActions?: RowActionDef<T>[] | ((item: T) => RowActionDef<T>[]);\n /** Label for the row actions column header. Defaults to empty string. */\n rowActionsLabel?: string;\n /**\n * When true, renders a selection column before the first data column — a per-row control on\n * every row (see `selectionType`), plus a \"select all\" checkbox in the header when\n * `selectionType` is \"checkbox\". Off by default.\n */\n selectable?: boolean;\n /**\n * Visual style of the built-in selection control. \"checkbox\" (default) allows selecting\n * multiple rows and shows a \"select all\" in the header. \"radio\" restricts selection to a\n * single row (no \"select all\" — there is nothing to select all *to* with one choice) and\n * renders a round control instead of a checkbox.\n */\n selectionType?: \"checkbox\" | \"radio\";\n /** When true, draws vertical lines between columns. Off by default. */\n grid?: boolean;\n /** Controlled selection state. Omit to let the table manage its own selection internally. */\n selectedKeys?: Selection;\n onSelectionChange?: (keys: Selection) => void;\n /** Initial sort when the table manages its own sorting. Only columns with `sortable` can be sorted. */\n defaultSortDescriptor?: SortDescriptor;\n /** Controlled sort state. Omit to let the table manage its own sorting internally. */\n sortDescriptor?: SortDescriptor;\n onSortChange?: (descriptor: SortDescriptor) => void;\n searchPlaceholder?: string;\n searchKeys?: (keyof T)[];\n isLoading?: boolean;\n loadingMessage?: string;\n emptyMessage?: string;\n previousLabel?: string;\n nextLabel?: string;\n pageSize?: number;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- linha aninhada é de tipo independente de T\n nestedColumns?: Column<any>[];\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- linha aninhada é de tipo independente de T\n getNestedData?: (item: T) => any[] | Promise<any[]>;\n nestedLoadingMessage?: string;\n nestedEmptyMessage?: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- linha aninhada é de tipo independente de T\n nestedSearchKeys?: (keyof any)[];\n nestedSearchPlaceholder?: string;\n nestedActions?: (item: T) => ReactNode;\n nestedPageSize?: number;\n}\n\nexport function DataTable<T extends { id: string }>({\n columns,\n data,\n actions,\n rowActions,\n rowActionsLabel = \"\",\n selectable = false,\n selectionType = \"checkbox\",\n grid = false,\n selectedKeys,\n onSelectionChange,\n defaultSortDescriptor,\n sortDescriptor: controlledSortDescriptor,\n onSortChange,\n searchPlaceholder = \"Search...\",\n searchKeys = [],\n isLoading = false,\n loadingMessage = \"Loading...\",\n emptyMessage = \"No records found\",\n previousLabel = \"Previous\",\n nextLabel = \"Next\",\n pageSize = 10,\n nestedColumns,\n getNestedData,\n nestedLoadingMessage = \"Loading...\",\n nestedEmptyMessage = \"No records found\",\n nestedSearchKeys,\n nestedSearchPlaceholder,\n nestedActions,\n nestedPageSize,\n}: DataTableProps<T>) {\n const [query, setQuery] = useState(\"\");\n const [page, setPage] = useState(1);\n const [internalSortDescriptor, setInternalSortDescriptor] = useState(defaultSortDescriptor);\n const sortDescriptor = controlledSortDescriptor ?? internalSortDescriptor;\n const [expanded, setExpanded] = useState<Set<string>>(new Set());\n const [nestedCache, setNestedCache] = useState<Map<string, NestedStatus>>(new Map());\n\n const hasNested = !!getNestedData && !!nestedColumns;\n const hasRowActions = !!rowActions;\n\n function setRowExpanded(id: string, isExpanded: boolean) {\n setExpanded((prev) => {\n const next = new Set(prev);\n if (isExpanded) next.add(id);\n else next.delete(id);\n return next;\n });\n }\n\n // A carga fica fora do updater do setExpanded: o React pode chamar updaters mais de uma\n // vez (StrictMode), o que dispararia getNestedData em dobro.\n function toggleRow(item: T) {\n const id = item.id;\n const willExpand = !expanded.has(id);\n setRowExpanded(id, willExpand);\n if (!willExpand || nestedCache.has(id)) return;\n\n const result = getNestedData!(item);\n if (result instanceof Promise) {\n setNestedCache((c) => new Map(c).set(id, { status: \"loading\", data: [] }));\n result.then(\n (rows) => {\n setNestedCache((c) => new Map(c).set(id, { status: \"loaded\", data: rows }));\n },\n () => {\n // Na falha, descarta a entrada e recolhe a linha: expandir de novo refaz a carga,\n // em vez de a linha ficar presa em \"loading\".\n setNestedCache((c) => {\n const next = new Map(c);\n next.delete(id);\n return next;\n });\n setRowExpanded(id, false);\n },\n );\n } else {\n setNestedCache((c) => new Map(c).set(id, { status: \"loaded\", data: result }));\n }\n }\n\n const hasSearch = searchKeys.length > 0;\n const hasToolbar = hasSearch || !!actions;\n\n const filtered = useMemo(() => {\n if (!query.trim() || !hasSearch) return data;\n const lower = query.toLowerCase();\n return data.filter((item) =>\n searchKeys.some((k) =>\n String(item[k] ?? \"\")\n .toLowerCase()\n .includes(lower),\n ),\n );\n }, [data, query, searchKeys, hasSearch]);\n\n const sortColumn = columns.find((col) => col.sortable && String(col.key) === String(sortDescriptor?.column));\n\n const sorted = useMemo(\n () => (sortColumn && sortDescriptor ? sortRows(filtered, sortColumn, sortDescriptor.direction) : filtered),\n [filtered, sortColumn, sortDescriptor],\n );\n\n function handleSortChange(descriptor: SortDescriptor) {\n setInternalSortDescriptor(descriptor);\n setPage(1);\n onSortChange?.(descriptor);\n }\n\n const totalPages = Math.max(1, Math.ceil(sorted.length / pageSize));\n const currentPage = Math.min(page, totalPages);\n const pageData = sorted.slice(\n (currentPage - 1) * pageSize,\n currentPage * pageSize,\n );\n\n function getCell(item: T, col: Column<T>): ReactNode {\n if (col.render) return col.render(item);\n return String((item as Record<string, unknown>)[col.key as string] ?? \"\");\n }\n\n return (\n <Flex direction=\"column\" gap=\"300\" className=\"data-table\">\n {hasToolbar && (\n <div className=\"data-table-toolbar\">\n {hasSearch && (\n <Search\n placeholder={searchPlaceholder}\n onSearch={(v) => {\n setQuery(v);\n setPage(1);\n }}\n className=\"data-table-search\"\n />\n )}\n {actions && <div className=\"data-table-actions\">{actions}</div>}\n </div>\n )}\n\n {isLoading ? (\n <div\n role=\"status\"\n aria-live=\"polite\"\n aria-label={loadingMessage}\n className=\"data-table-status\"\n >\n {loadingMessage}\n </div>\n ) : filtered.length === 0 ? (\n <div role=\"status\" className=\"data-table-status data-table-empty\">\n {emptyMessage}\n </div>\n ) : (\n <Table\n selectionMode={selectable ? (selectionType === \"radio\" ? \"single\" : \"multiple\") : \"none\"}\n selectionType={selectionType}\n grid={grid}\n selectedKeys={selectedKeys}\n onSelectionChange={onSelectionChange}\n sortDescriptor={sortDescriptor}\n onSortChange={handleSortChange}\n >\n <TableHead>\n {hasNested && <TableColumn className=\"data-table-expand-col\" />}\n {columns.map((col, idx) => (\n <TableColumn\n key={String(col.key)}\n id={String(col.key)}\n align={col.align}\n allowsSorting={col.sortable}\n isRowHeader={idx === 0}\n >\n {col.label}\n </TableColumn>\n ))}\n {hasRowActions && (\n <TableColumn align=\"right\" className=\"data-table-row-actions-col\">\n {rowActionsLabel}\n </TableColumn>\n )}\n </TableHead>\n <TableBody>\n {pageData.flatMap((item) => {\n const isExpanded = expanded.has(item.id);\n const cached = nestedCache.get(item.id);\n const rows: ReactNode[] = [\n <TableRow key={item.id} id={item.id}>\n {hasNested && (\n <TableCell className=\"data-table-expand-cell\">\n <button\n type=\"button\"\n className=\"data-table-expand-btn\"\n aria-label={isExpanded ? \"Collapse row\" : \"Expand row\"}\n aria-expanded={isExpanded}\n onClick={() => toggleRow(item)}\n >\n {isExpanded ? (\n <IconChevronDown size=\"16\" />\n ) : (\n <IconChevronRight size=\"16\" />\n )}\n </button>\n </TableCell>\n )}\n {columns.map((col) => (\n <TableCell key={String(col.key)} align={col.align}>\n {getCell(item, col)}\n </TableCell>\n ))}\n {hasRowActions && (\n <TableCell align=\"right\" className=\"data-table-row-actions-cell\">\n <div className=\"data-table-row-actions\">\n {(typeof rowActions === \"function\"\n ? rowActions(item)\n : rowActions!\n ).map((action) => (\n <RowActionButton key={action.key} action={action} item={item} />\n ))}\n </div>\n </TableCell>\n )}\n </TableRow>,\n ];\n if (isExpanded) {\n rows.push(\n <TableRow key={`${item.id}-nested`} id={`${item.id}-nested`} className=\"data-table-nested-row\">\n <TableCell\n colSpan={\n columns.length +\n (hasNested ? 1 : 0) +\n (selectable ? 1 : 0) +\n (hasRowActions ? 1 : 0)\n }\n className=\"data-table-nested-cell\"\n >\n <DataTable\n columns={nestedColumns!}\n data={cached?.data ?? []}\n isLoading={!cached || cached.status === \"loading\"}\n loadingMessage={nestedLoadingMessage}\n emptyMessage={nestedEmptyMessage}\n searchKeys={nestedSearchKeys}\n searchPlaceholder={nestedSearchPlaceholder}\n actions={nestedActions?.(item)}\n pageSize={nestedPageSize ?? pageSize}\n />\n </TableCell>\n </TableRow>,\n );\n }\n return rows;\n })}\n </TableBody>\n </Table>\n )}\n\n <Pagination\n page={currentPage}\n totalPages={totalPages}\n onPageChange={setPage}\n previousLabel={previousLabel}\n nextLabel={nextLabel}\n />\n </Flex>\n );\n}\n"],"names":["sortCollator","compareSortableValues","a","b","sortRows","rows","column","direction","valueOf","item","directionFactor","RowActionButton","action","allowed","btn","jsx","PermissionGate","DataTable","columns","data","actions","rowActions","rowActionsLabel","selectable","selectionType","grid","selectedKeys","onSelectionChange","defaultSortDescriptor","controlledSortDescriptor","onSortChange","searchPlaceholder","searchKeys","isLoading","loadingMessage","emptyMessage","previousLabel","nextLabel","pageSize","nestedColumns","getNestedData","nestedLoadingMessage","nestedEmptyMessage","nestedSearchKeys","nestedSearchPlaceholder","nestedActions","nestedPageSize","query","setQuery","useState","page","setPage","internalSortDescriptor","setInternalSortDescriptor","sortDescriptor","expanded","setExpanded","nestedCache","setNestedCache","hasNested","hasRowActions","setRowExpanded","id","isExpanded","prev","next","toggleRow","willExpand","result","c","hasSearch","hasToolbar","filtered","useMemo","lower","k","sortColumn","col","sorted","handleSortChange","descriptor","totalPages","currentPage","pageData","getCell","Flex","jsxs","Search","v","Table","TableHead","TableColumn","idx","TableBody","cached","TableRow","TableCell","IconChevronDown","IconChevronRight","Pagination"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DataTable.js","sources":["../../../../../src/ui/components/DataTable/DataTable.tsx"],"sourcesContent":["import {\n Pagination,\n PermissionGate,\n Search,\n Table,\n TableBody,\n TableCell,\n TableColumn,\n TableHead,\n TableRow,\n} from \"primitives\";\nimport { Flex } from \"layout\";\nimport { IconChevronDown, IconChevronRight } from \"icons\";\nimport type { ReactNode } from \"react\";\nimport { useMemo, useState } from \"react\";\nimport type { Selection, SortDescriptor } from \"react-aria-components\";\nimport \"./datatable.css\";\n\nexport interface Column<T> {\n key: keyof T | string;\n label: string;\n align?: \"start\" | \"center\" | \"right\";\n render?: (item: T) => ReactNode;\n /** When true, the header becomes clickable and the rows can be sorted by this column. */\n sortable?: boolean;\n /** Value used to sort this column. Defaults to `item[key]`. */\n sortValue?: (item: T) => SortableValue;\n}\n\ntype SortableValue = string | number | Date | null | undefined;\n\nconst sortCollator = new Intl.Collator(undefined, { numeric: true, sensitivity: \"base\" });\n\nfunction compareSortableValues(a: SortableValue, b: SortableValue): number {\n if (a == null || b == null) return a == null ? (b == null ? 0 : 1) : -1;\n if (a instanceof Date && b instanceof Date) return a.getTime() - b.getTime();\n if (typeof a === \"number\" && typeof b === \"number\") return a - b;\n return sortCollator.compare(String(a), String(b));\n}\n\nfunction sortRows<T>(rows: T[], column: Column<T>, direction: SortDescriptor[\"direction\"]): T[] {\n const valueOf = column.sortValue ?? ((item: T) => (item as Record<string, unknown>)[column.key as string] as SortableValue);\n const directionFactor = direction === \"descending\" ? -1 : 1;\n return [...rows].sort((a, b) => compareSortableValues(valueOf(a), valueOf(b)) * directionFactor);\n}\n\nexport interface RowActionDef<T> {\n /** Unique key for this action. */\n key: string;\n /** aria-label for the button. */\n label: string;\n /** Icon element rendered inside the button. */\n icon: ReactNode;\n /** When false, button is disabled and a tooltip with `noAccessLabel` is shown. Default: true. */\n isAllowed?: boolean;\n /** Tooltip text shown when `isAllowed` is false. */\n noAccessLabel?: string;\n /** Called with the row item when the button is pressed. */\n onPress: (item: T) => void;\n}\n\nfunction RowActionButton<T>({\n action,\n item,\n}: {\n action: RowActionDef<T>;\n item: T;\n}) {\n const allowed = action.isAllowed !== false;\n const btn = (\n <button\n type=\"button\"\n className=\"data-table-row-action-btn\"\n aria-label={action.label}\n disabled={!allowed}\n onClick={allowed ? () => action.onPress(item) : undefined}\n >\n {action.icon}\n </button>\n );\n if (allowed) return btn;\n return (\n <PermissionGate isAllowed={false} noAccessLabel={action.noAccessLabel ?? \"\"}>\n {btn}\n </PermissionGate>\n );\n}\n\n// O tipo da linha aninhada é independente de T (não há relação genérica entre linha pai e linhas\n// filhas), então \"any\" é usado deliberadamente como fronteira de erasure de tipo.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype NestedStatus = { status: \"loading\"; data: never[] } | { status: \"loaded\"; data: any[] };\n\nexport interface DataTableProps<T extends { id: string }> {\n columns: Column<T>[];\n data: T[];\n actions?: ReactNode;\n /** Per-row action buttons rendered in a dedicated last column. */\n rowActions?: RowActionDef<T>[] | ((item: T) => RowActionDef<T>[]);\n /** Label for the row actions column header. Defaults to empty string. */\n rowActionsLabel?: string;\n /**\n * When true, renders a selection column before the first data column — a per-row control on\n * every row (see `selectionType`), plus a \"select all\" checkbox in the header when\n * `selectionType` is \"checkbox\". Off by default.\n */\n selectable?: boolean;\n /**\n * Visual style of the built-in selection control. \"checkbox\" (default) allows selecting\n * multiple rows and shows a \"select all\" in the header. \"radio\" restricts selection to a\n * single row (no \"select all\" — there is nothing to select all *to* with one choice) and\n * renders a round control instead of a checkbox.\n */\n selectionType?: \"checkbox\" | \"radio\";\n /** Controlled selection state. Omit to let the table manage its own selection internally. */\n selectedKeys?: Selection;\n onSelectionChange?: (keys: Selection) => void;\n /** Initial sort when the table manages its own sorting. Only columns with `sortable` can be sorted. */\n defaultSortDescriptor?: SortDescriptor;\n /** Controlled sort state. Omit to let the table manage its own sorting internally. */\n sortDescriptor?: SortDescriptor;\n onSortChange?: (descriptor: SortDescriptor) => void;\n searchPlaceholder?: string;\n searchKeys?: (keyof T)[];\n isLoading?: boolean;\n loadingMessage?: string;\n emptyMessage?: string;\n previousLabel?: string;\n nextLabel?: string;\n pageSize?: number;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- linha aninhada é de tipo independente de T\n nestedColumns?: Column<any>[];\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- linha aninhada é de tipo independente de T\n getNestedData?: (item: T) => any[] | Promise<any[]>;\n nestedLoadingMessage?: string;\n nestedEmptyMessage?: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- linha aninhada é de tipo independente de T\n nestedSearchKeys?: (keyof any)[];\n nestedSearchPlaceholder?: string;\n nestedActions?: (item: T) => ReactNode;\n nestedPageSize?: number;\n}\n\nexport function DataTable<T extends { id: string }>({\n columns,\n data,\n actions,\n rowActions,\n rowActionsLabel = \"\",\n selectable = false,\n selectionType = \"checkbox\",\n selectedKeys,\n onSelectionChange,\n defaultSortDescriptor,\n sortDescriptor: controlledSortDescriptor,\n onSortChange,\n searchPlaceholder = \"Search...\",\n searchKeys = [],\n isLoading = false,\n loadingMessage = \"Loading...\",\n emptyMessage = \"No records found\",\n previousLabel = \"Previous\",\n nextLabel = \"Next\",\n pageSize = 10,\n nestedColumns,\n getNestedData,\n nestedLoadingMessage = \"Loading...\",\n nestedEmptyMessage = \"No records found\",\n nestedSearchKeys,\n nestedSearchPlaceholder,\n nestedActions,\n nestedPageSize,\n}: DataTableProps<T>) {\n const [query, setQuery] = useState(\"\");\n const [page, setPage] = useState(1);\n const [internalSortDescriptor, setInternalSortDescriptor] = useState(defaultSortDescriptor);\n const sortDescriptor = controlledSortDescriptor ?? internalSortDescriptor;\n const [expanded, setExpanded] = useState<Set<string>>(new Set());\n const [nestedCache, setNestedCache] = useState<Map<string, NestedStatus>>(new Map());\n\n const hasNested = !!getNestedData && !!nestedColumns;\n const hasRowActions = !!rowActions;\n\n function setRowExpanded(id: string, isExpanded: boolean) {\n setExpanded((prev) => {\n const next = new Set(prev);\n if (isExpanded) next.add(id);\n else next.delete(id);\n return next;\n });\n }\n\n // A carga fica fora do updater do setExpanded: o React pode chamar updaters mais de uma\n // vez (StrictMode), o que dispararia getNestedData em dobro.\n function toggleRow(item: T) {\n const id = item.id;\n const willExpand = !expanded.has(id);\n setRowExpanded(id, willExpand);\n if (!willExpand || nestedCache.has(id)) return;\n\n const result = getNestedData!(item);\n if (result instanceof Promise) {\n setNestedCache((c) => new Map(c).set(id, { status: \"loading\", data: [] }));\n result.then(\n (rows) => {\n setNestedCache((c) => new Map(c).set(id, { status: \"loaded\", data: rows }));\n },\n () => {\n // Na falha, descarta a entrada e recolhe a linha: expandir de novo refaz a carga,\n // em vez de a linha ficar presa em \"loading\".\n setNestedCache((c) => {\n const next = new Map(c);\n next.delete(id);\n return next;\n });\n setRowExpanded(id, false);\n },\n );\n } else {\n setNestedCache((c) => new Map(c).set(id, { status: \"loaded\", data: result }));\n }\n }\n\n const hasSearch = searchKeys.length > 0;\n const hasToolbar = hasSearch || !!actions;\n\n const filtered = useMemo(() => {\n if (!query.trim() || !hasSearch) return data;\n const lower = query.toLowerCase();\n return data.filter((item) =>\n searchKeys.some((k) =>\n String(item[k] ?? \"\")\n .toLowerCase()\n .includes(lower),\n ),\n );\n }, [data, query, searchKeys, hasSearch]);\n\n const sortColumn = columns.find((col) => col.sortable && String(col.key) === String(sortDescriptor?.column));\n\n const sorted = useMemo(\n () => (sortColumn && sortDescriptor ? sortRows(filtered, sortColumn, sortDescriptor.direction) : filtered),\n [filtered, sortColumn, sortDescriptor],\n );\n\n function handleSortChange(descriptor: SortDescriptor) {\n setInternalSortDescriptor(descriptor);\n setPage(1);\n onSortChange?.(descriptor);\n }\n\n const totalPages = Math.max(1, Math.ceil(sorted.length / pageSize));\n const currentPage = Math.min(page, totalPages);\n const pageData = sorted.slice(\n (currentPage - 1) * pageSize,\n currentPage * pageSize,\n );\n\n function getCell(item: T, col: Column<T>): ReactNode {\n if (col.render) return col.render(item);\n return String((item as Record<string, unknown>)[col.key as string] ?? \"\");\n }\n\n return (\n <Flex direction=\"column\" gap=\"300\" className=\"data-table\">\n {hasToolbar && (\n <div className=\"data-table-toolbar\">\n {hasSearch && (\n <Search\n placeholder={searchPlaceholder}\n onSearch={(v) => {\n setQuery(v);\n setPage(1);\n }}\n className=\"data-table-search\"\n />\n )}\n {actions && <div className=\"data-table-actions\">{actions}</div>}\n </div>\n )}\n\n {isLoading ? (\n <div\n role=\"status\"\n aria-live=\"polite\"\n aria-label={loadingMessage}\n className=\"data-table-status\"\n >\n {loadingMessage}\n </div>\n ) : filtered.length === 0 ? (\n <div role=\"status\" className=\"data-table-status data-table-empty\">\n {emptyMessage}\n </div>\n ) : (\n <Table\n selectionMode={selectable ? (selectionType === \"radio\" ? \"single\" : \"multiple\") : \"none\"}\n selectionType={selectionType}\n selectedKeys={selectedKeys}\n onSelectionChange={onSelectionChange}\n sortDescriptor={sortDescriptor}\n onSortChange={handleSortChange}\n >\n <TableHead>\n {hasNested && <TableColumn className=\"data-table-expand-col\" />}\n {columns.map((col, idx) => (\n <TableColumn\n key={String(col.key)}\n id={String(col.key)}\n align={col.align}\n allowsSorting={col.sortable}\n isRowHeader={idx === 0}\n >\n {col.label}\n </TableColumn>\n ))}\n {hasRowActions && (\n <TableColumn align=\"right\" className=\"data-table-row-actions-col\">\n {rowActionsLabel}\n </TableColumn>\n )}\n </TableHead>\n <TableBody>\n {pageData.flatMap((item) => {\n const isExpanded = expanded.has(item.id);\n const cached = nestedCache.get(item.id);\n const rows: ReactNode[] = [\n <TableRow key={item.id} id={item.id}>\n {hasNested && (\n <TableCell className=\"data-table-expand-cell\">\n <button\n type=\"button\"\n className=\"data-table-expand-btn\"\n aria-label={isExpanded ? \"Collapse row\" : \"Expand row\"}\n aria-expanded={isExpanded}\n onClick={() => toggleRow(item)}\n >\n {isExpanded ? (\n <IconChevronDown size=\"16\" />\n ) : (\n <IconChevronRight size=\"16\" />\n )}\n </button>\n </TableCell>\n )}\n {columns.map((col) => (\n <TableCell key={String(col.key)} align={col.align}>\n {getCell(item, col)}\n </TableCell>\n ))}\n {hasRowActions && (\n <TableCell align=\"right\" className=\"data-table-row-actions-cell\">\n <div className=\"data-table-row-actions\">\n {(typeof rowActions === \"function\"\n ? rowActions(item)\n : rowActions!\n ).map((action) => (\n <RowActionButton key={action.key} action={action} item={item} />\n ))}\n </div>\n </TableCell>\n )}\n </TableRow>,\n ];\n if (isExpanded) {\n rows.push(\n <TableRow key={`${item.id}-nested`} id={`${item.id}-nested`} className=\"data-table-nested-row\">\n <TableCell\n colSpan={\n columns.length +\n (hasNested ? 1 : 0) +\n (selectable ? 1 : 0) +\n (hasRowActions ? 1 : 0)\n }\n className=\"data-table-nested-cell\"\n >\n <DataTable\n columns={nestedColumns!}\n data={cached?.data ?? []}\n isLoading={!cached || cached.status === \"loading\"}\n loadingMessage={nestedLoadingMessage}\n emptyMessage={nestedEmptyMessage}\n searchKeys={nestedSearchKeys}\n searchPlaceholder={nestedSearchPlaceholder}\n actions={nestedActions?.(item)}\n pageSize={nestedPageSize ?? pageSize}\n />\n </TableCell>\n </TableRow>,\n );\n }\n return rows;\n })}\n </TableBody>\n </Table>\n )}\n\n <Pagination\n page={currentPage}\n totalPages={totalPages}\n onPageChange={setPage}\n previousLabel={previousLabel}\n nextLabel={nextLabel}\n />\n </Flex>\n );\n}\n"],"names":["sortCollator","compareSortableValues","a","b","sortRows","rows","column","direction","valueOf","item","directionFactor","RowActionButton","action","allowed","btn","jsx","PermissionGate","DataTable","columns","data","actions","rowActions","rowActionsLabel","selectable","selectionType","selectedKeys","onSelectionChange","defaultSortDescriptor","controlledSortDescriptor","onSortChange","searchPlaceholder","searchKeys","isLoading","loadingMessage","emptyMessage","previousLabel","nextLabel","pageSize","nestedColumns","getNestedData","nestedLoadingMessage","nestedEmptyMessage","nestedSearchKeys","nestedSearchPlaceholder","nestedActions","nestedPageSize","query","setQuery","useState","page","setPage","internalSortDescriptor","setInternalSortDescriptor","sortDescriptor","expanded","setExpanded","nestedCache","setNestedCache","hasNested","hasRowActions","setRowExpanded","id","isExpanded","prev","next","toggleRow","willExpand","result","c","hasSearch","hasToolbar","filtered","useMemo","lower","k","sortColumn","col","sorted","handleSortChange","descriptor","totalPages","currentPage","pageData","getCell","Flex","jsxs","Search","v","Table","TableHead","TableColumn","idx","TableBody","cached","TableRow","TableCell","IconChevronDown","IconChevronRight","Pagination"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("react/jsx-runtime"),ee=require("../../../../vendor/clsx/dist/clsx.cjs"),i=require("react"),te=require("../ChartLegend/ChartLegend.cjs"),re=require("../ChartLegend/use-chart-legend.cjs"),ne=require("../chart-palette.cjs"),ie=require("../useChartInstance.cjs"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("react/jsx-runtime"),ee=require("../../../../vendor/clsx/dist/clsx.cjs"),i=require("react"),te=require("../ChartLegend/ChartLegend.cjs"),re=require("../ChartLegend/use-chart-legend.cjs"),ne=require("../chart-palette.cjs"),I=require("../chart-share.cjs"),ie=require("../useChartInstance.cjs"),se=require("./pie-chart-option.cjs"),h=require("./pie-chart-slices.cjs");;/* empty css */const ce={others:"Others",total:"Total",backToPrevious:e=>`Back from ${e}`},oe=200,ae=["percent"],le=[];function ue(e,s,a){if(!e||s.length===0)return;const l=s.includes("percent"),S=s.includes("value");return l&&S?`${a(e.value)} (${I.formatShare(e.share)})`:S?a(e.value):I.formatShare(e.share)}function de(e){const[s,a]=i.useState(0);return i.useLayoutEffect(()=>{if(!e)return;const l=new ResizeObserver(()=>a(Math.min(e.clientWidth,e.clientHeight)));return l.observe(e),()=>l.disconnect()},[e]),s}function he({data:e,shape:s="donut",labelContent:a=ae,showTotal:l="auto",total:S,valueFormatter:p,legend:q="inline",legendPosition:y="bottom",legendValues:M=le,onSeriesColorChange:A,onFocusChange:b,legendLabels:R,labels:B,className:$,...D}){const{containerRef:U,chart:u,theme:c,resolveSeriesColor:H}=ie.useChartInstance(),o={...ce,...B},[f,V]=i.useState(null),[w,z]=i.useState(null),G=de(w),K=i.useMemo(()=>e.map(t=>({id:t.id,name:h.displayNameOf(t,o.others),colorToken:t.colorToken??(t.isOthers?ne.CHART_NEUTRAL_COLOR_TOKEN:void 0)})),[e,o.others]),{items:W,colorsBySeriesId:L,colorTokensBySeriesId:X,hiddenSeriesIds:O,toggleSeries:Z}=re.useChartLegend(K,(c==null?void 0:c.seriesColors)??[],H),d=i.useMemo(()=>h.buildPieSlices({nodes:e.filter(t=>!O.has(t.id)),colorsByRootId:L,fallbackColor:(c==null?void 0:c.neutralColor)??"#9ca3af",othersName:o.others}),[e,O,L,c,o.others]),r=i.useMemo(()=>f===null?void 0:h.findSlice(d,f),[d,f]),m=r?r.children:d,_=i.useCallback(t=>{V(t),b==null||b(t)},[b]);i.useEffect(()=>{f!==null&&!r&&_(null)},[f,r,_]),i.useEffect(()=>{!u||!c||u.setOption(se.buildPieChartOption({slices:m,shape:s,labelContent:a,theme:c,valueFormatter:p}),{notMerge:!0})},[u,c,m,s,a,p]),i.useEffect(()=>{if(!u)return;function t(C){var P;const x=(P=C.data)==null?void 0:P.id;if(typeof x!="string")return;const T=h.findSlice(m,x);T&&T.children.length>0&&_(T.id)}return u.on("click",t),()=>{u.off("click",t)}},[u,m,_]);function v(t){return p?p(t):String(t)}const J=W.map(t=>({...t,detail:ue(d.find(C=>C.id===t.id),M,v)})),g=l==="on"||l==="auto"&&G>=oe,N=r?r.value:S??h.totalOf(d),k=r?h.findParentSlice(d,r.id):void 0,Q=q!=="none"&&e.length>0,E=n.jsxs(n.Fragment,{children:[n.jsx("span",{className:"pie-chart__total-value",children:v(N)}),n.jsx("span",{className:"pie-chart__total-caption",children:r?r.name:o.total})]});function j(){_(k?k.id:null)}function Y(){return r?n.jsx("button",{type:"button",className:"pie-chart__center pie-chart__center--button","aria-label":o.backToPrevious(r.name),onClick:j,children:g&&E}):g&&n.jsx("div",{className:"pie-chart__center",children:E})}function F(){return r?n.jsxs("button",{type:"button",className:"pie-chart__footer pie-chart__footer--button","aria-label":o.backToPrevious(r.name),onClick:j,children:[r.name,g&&`: ${v(N)}`]}):g&&n.jsx("div",{className:"pie-chart__footer",children:`${o.total}: ${v(N)}`})}return n.jsxs("div",{className:ee.clsx("pie-chart",`pie-chart--legend-${y}`,$),...D,children:[Q&&n.jsx(te.ChartLegend,{className:"pie-chart__legend",items:J,onToggle:Z,onColorChange:A,colorTokensBySeriesId:X,labels:R}),n.jsxs("div",{className:"pie-chart__body",children:[n.jsxs("div",{ref:z,className:"pie-chart__stage",children:[n.jsx("div",{ref:U,className:"pie-chart__canvas"}),s==="donut"&&Y()]}),s==="pie"&&F()]})]})}exports.PieChart=he;
|
|
2
2
|
//# sourceMappingURL=PieChart.cjs.map
|