@apipass/design-system 7.1.0 → 7.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("react/jsx-runtime"),xe=require("../../../vendor/clsx/dist/clsx.cjs"),h=require("react");;/* empty css */const ge=require("../../primitives/Search/Search.cjs"),o=require("../../primitives/Table/Table.cjs"),fe=require("../../icons/IconChevronDown.cjs"),pe=require("../../icons/IconChevronRight.cjs"),we=require("../../primitives/Pagination/Pagination.cjs"),je=require("../../primitives/PermissionGate/PermissionGate.cjs"),me=require("../../layout/Flex/Flex.cjs"),Se=new Intl.Collator(void 0,{numeric:!0,sensitivity:"base"});function Ce(s,n){return s==null||n==null?s==null?n==null?0:1:-1:s instanceof Date&&n instanceof Date?s.getTime()-n.getTime():typeof s=="number"&&typeof n=="number"?s-n:Se.compare(String(s),String(n))}function Ne(s,n,c){const i=n.sortValue??(b=>b[n.key]),m=c==="descending"?-1:1;return[...s].sort((b,x)=>Ce(i(b),i(x))*m)}function ye({action:s,item:n}){const c=s.isAllowed!==!1,i=a.jsx("button",{type:"button",className:"data-table-row-action-btn","aria-label":s.label,disabled:!c,onClick:c?()=>s.onPress(n):void 0,children:s.icon});return c?i:a.jsx(je.PermissionGate,{isAllowed:!1,noAccessLabel:s.noAccessLabel??"",children:i})}function G({columns:s,data:n,actions:c,rowActions:i,rowActionsLabel:m="",selectable:b=!1,selectionType:x="checkbox",selectedKeys:O,onSelectionChange:V,defaultSortDescriptor:$,sortDescriptor:Q,onSortChange:S,ariaLabel:z,dense:J,striped:U,maxHeight:q,searchPlaceholder:W="Search...",searchKeys:C=[],isLoading:X=!1,loadingMessage:k="Loading...",emptyMessage:Y="No records found",previousLabel:Z="Previous",nextLabel:_="Next",pageSize:g=10,nestedColumns:D,getNestedData:L,nestedLoadingMessage:A="Loading...",nestedEmptyMessage:K="No records found",nestedSearchKeys:ee,nestedSearchPlaceholder:ae,nestedActions:N,nestedPageSize:te}){const[y,se]=h.useState(""),[ne,T]=h.useState(1),[le,re]=h.useState($),u=Q??le,[E,oe]=h.useState(new Set),[I,f]=h.useState(new Map),v=!!L&&!!D,R=!!i;function H(e,t){oe(r=>{const d=new Set(r);return t?d.add(e):d.delete(e),d})}function ie(e){const t=e.id,r=!E.has(t);if(H(t,r),!r||I.has(t))return;const d=L(e);d instanceof Promise?(f(l=>new Map(l).set(t,{status:"loading",data:[]})),d.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}),H(t,!1)})):f(l=>new Map(l).set(t,{status:"loaded",data:d}))}const p=C.length>0,de=s.some(e=>e.isRowHeader),ce=p||!!c,w=h.useMemo(()=>{if(!y.trim()||!p)return n;const e=y.toLowerCase();return n.filter(t=>C.some(r=>String(t[r]??"").toLowerCase().includes(e)))},[n,y,C,p]),M=s.find(e=>e.sortable&&String(e.key)===String(u==null?void 0:u.column)),F=h.useMemo(()=>M&&u?Ne(w,M,u.direction):w,[w,M,u]);function ue(e){re(e),T(1),S==null||S(e)}const B=Math.max(1,Math.ceil(F.length/g)),P=Math.min(ne,B),he=F.slice((P-1)*g,P*g);function be(e,t){return t.render?t.render(e):String(e[t.key]??"")}return a.jsxs(me.Flex,{direction:"column",gap:"300",className:xe.clsx("data-table",q!==void 0&&"data-table--fill"),children:[ce&&a.jsxs("div",{className:"data-table-toolbar",children:[p&&a.jsx(ge.Search,{placeholder:W,onSearch:e=>{se(e),T(1)},className:"data-table-search"}),c&&a.jsx("div",{className:"data-table-actions",children:c})]}),X?a.jsx("div",{role:"status","aria-live":"polite","aria-label":k,className:"data-table-status",children:k}):w.length===0?a.jsx("div",{role:"status",className:"data-table-status data-table-empty",children:Y}):a.jsxs(o.Table,{"aria-label":z,dense:J,striped:U,maxHeight:q,selectionMode:b?x==="radio"?"single":"multiple":"none",selectionType:x,selectedKeys:O,onSelectionChange:V,sortDescriptor:u,onSortChange:ue,children:[a.jsxs(o.TableHead,{children:[v&&a.jsx(o.TableColumn,{className:"data-table-expand-col"}),s.map((e,t)=>a.jsx(o.TableColumn,{id:String(e.key),align:e.align,allowsSorting:e.sortable,isRowHeader:de?e.isRowHeader:t===0,children:e.label},String(e.key))),R&&a.jsx(o.TableColumn,{align:"right",className:"data-table-row-actions-col",children:m})]}),a.jsx(o.TableBody,{children:he.flatMap(e=>{const t=E.has(e.id),r=I.get(e.id),d=[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:()=>ie(e),children:t?a.jsx(fe.IconChevronDown,{size:"16"}):a.jsx(pe.IconChevronRight,{size:"16"})})}),s.map(l=>a.jsx(o.TableCell,{align:l.align,children:be(e,l)},String(l.key))),R&&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(ye,{action:l,item:e},l.key))})})]},e.id)];return t&&d.push(a.jsx(o.TableRow,{id:`${e.id}-nested`,className:"data-table-nested-row",children:a.jsx(o.TableCell,{colSpan:s.length+(v?1:0)+(b?1:0)+(R?1:0),className:"data-table-nested-cell",children:a.jsx(G,{columns:D,data:(r==null?void 0:r.data)??[],isLoading:!r||r.status==="loading",loadingMessage:A,emptyMessage:K,searchKeys:ee,searchPlaceholder:ae,actions:N==null?void 0:N(e),pageSize:te??g})})},`${e.id}-nested`)),d})})]}),a.jsx(we.Pagination,{page:P,totalPages:B,onPageChange:T,previousLabel:Z,nextLabel:_})]})}exports.DataTable=G;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("react/jsx-runtime"),xe=require("../../../vendor/clsx/dist/clsx.cjs"),h=require("react");;/* empty css */const ge=require("../../primitives/Search/Search.cjs"),o=require("../../primitives/Table/Table.cjs"),fe=require("../../icons/IconChevronDown.cjs"),pe=require("../../icons/IconChevronRight.cjs"),we=require("../../primitives/Pagination/Pagination.cjs"),je=require("../../primitives/PermissionGate/PermissionGate.cjs"),me=require("../../layout/Flex/Flex.cjs"),Se=require("../../primitives/IconButton/IconButton.cjs"),Ce=new Intl.Collator(void 0,{numeric:!0,sensitivity:"base"});function ve(s,n){return s==null||n==null?s==null?n==null?0:1:-1:s instanceof Date&&n instanceof Date?s.getTime()-n.getTime():typeof s=="number"&&typeof n=="number"?s-n:Ce.compare(String(s),String(n))}function Ne(s,n,d){const i=n.sortValue??(b=>b[n.key]),m=d==="descending"?-1:1;return[...s].sort((b,x)=>ve(i(b),i(x))*m)}function Te({action:s,item:n}){const d=s.isAllowed!==!1,i=a.jsx(Se.IconButton,{variant:"neutral",size:"small","aria-label":s.label,isDisabled:!d,onPress:d?()=>s.onPress(n):void 0,children:s.icon});return d?i:a.jsx(je.PermissionGate,{isAllowed:!1,noAccessLabel:s.noAccessLabel??"",children:i})}function G({columns:s,data:n,actions:d,rowActions:i,rowActionsLabel:m="",selectable:b=!1,selectionType:x="checkbox",selectedKeys:O,onSelectionChange:V,defaultSortDescriptor:$,sortDescriptor:z,onSortChange:S,ariaLabel:Q,dense:J,striped:U,maxHeight:q,searchPlaceholder:W="Search...",searchKeys:C=[],isLoading:X=!1,loadingMessage:k="Loading...",emptyMessage:Y="No records found",previousLabel:Z="Previous",nextLabel:_="Next",pageSize:g=10,nestedColumns:D,getNestedData:I,nestedLoadingMessage:A="Loading...",nestedEmptyMessage:K="No records found",nestedSearchKeys:ee,nestedSearchPlaceholder:ae,nestedActions:v,nestedPageSize:te}){const[N,se]=h.useState(""),[ne,T]=h.useState(1),[le,re]=h.useState($),u=z??le,[L,oe]=h.useState(new Set),[E,f]=h.useState(new Map),y=!!I&&!!D,R=!!i;function B(e,t){oe(r=>{const c=new Set(r);return t?c.add(e):c.delete(e),c})}function ie(e){const t=e.id,r=!L.has(t);if(B(t,r),!r||E.has(t))return;const c=I(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}),B(t,!1)})):f(l=>new Map(l).set(t,{status:"loaded",data:c}))}const p=C.length>0,ce=s.some(e=>e.isRowHeader),de=p||!!d,w=h.useMemo(()=>{if(!N.trim()||!p)return n;const e=N.toLowerCase();return n.filter(t=>C.some(r=>String(t[r]??"").toLowerCase().includes(e)))},[n,N,C,p]),M=s.find(e=>e.sortable&&String(e.key)===String(u==null?void 0:u.column)),H=h.useMemo(()=>M&&u?Ne(w,M,u.direction):w,[w,M,u]);function ue(e){re(e),T(1),S==null||S(e)}const F=Math.max(1,Math.ceil(H.length/g)),P=Math.min(ne,F),he=H.slice((P-1)*g,P*g);function be(e,t){return t.render?t.render(e):String(e[t.key]??"")}return a.jsxs(me.Flex,{direction:"column",gap:"300",className:xe.clsx("data-table",q!==void 0&&"data-table--fill"),children:[de&&a.jsxs("div",{className:"data-table-toolbar",children:[p&&a.jsx(ge.Search,{placeholder:W,onSearch:e=>{se(e),T(1)},className:"data-table-search"}),d&&a.jsx("div",{className:"data-table-actions",children:d})]}),X?a.jsx("div",{role:"status","aria-live":"polite","aria-label":k,className:"data-table-status",children:k}):w.length===0?a.jsx("div",{role:"status",className:"data-table-status data-table-empty",children:Y}):a.jsxs(o.Table,{"aria-label":Q,dense:J,striped:U,maxHeight:q,selectionMode:b?x==="radio"?"single":"multiple":"none",selectionType:x,selectedKeys:O,onSelectionChange:V,sortDescriptor:u,onSortChange:ue,children:[a.jsxs(o.TableHead,{children:[y&&a.jsx(o.TableColumn,{className:"data-table-expand-col"}),s.map((e,t)=>a.jsx(o.TableColumn,{id:String(e.key),align:e.align,allowsSorting:e.sortable,isRowHeader:ce?e.isRowHeader:t===0,children:e.label},String(e.key))),R&&a.jsx(o.TableColumn,{align:"right",className:"data-table-row-actions-col",children:m})]}),a.jsx(o.TableBody,{children:he.flatMap(e=>{const t=L.has(e.id),r=E.get(e.id),c=[a.jsxs(o.TableRow,{id:e.id,children:[y&&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:()=>ie(e),children:t?a.jsx(fe.IconChevronDown,{size:"16"}):a.jsx(pe.IconChevronRight,{size:"16"})})}),s.map(l=>a.jsx(o.TableCell,{align:l.align,children:be(e,l)},String(l.key))),R&&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(Te,{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:s.length+(y?1:0)+(b?1:0)+(R?1:0),className:"data-table-nested-cell",children:a.jsx(G,{columns:D,data:(r==null?void 0:r.data)??[],isLoading:!r||r.status==="loading",loadingMessage:A,emptyMessage:K,searchKeys:ee,searchPlaceholder:ae,actions:v==null?void 0:v(e),pageSize:te??g})})},`${e.id}-nested`)),c})})]}),a.jsx(we.Pagination,{page:P,totalPages:F,onPageChange:T,previousLabel:Z,nextLabel:_})]})}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 clsx from \"clsx\";\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 /** Marks the column that names the row for assistive technology. Defaults to the first column when no column sets it. */\n isRowHeader?: boolean;\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 /** Accessible name of the table. */\n ariaLabel?: string;\n /** Compact row height. Off by default. */\n dense?: boolean;\n /** Alternating row background. Off by default. */\n striped?: boolean;\n /**\n * Caps the height of the table so its rows scroll inside it with a sticky header, keeping the\n * pagination in view. A percentage needs a parent with a defined height. Off by default.\n */\n maxHeight?: number | string;\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 ariaLabel,\n dense,\n striped,\n maxHeight,\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 hasExplicitRowHeader = columns.some((col) => col.isRowHeader);\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\n direction=\"column\"\n gap=\"300\"\n className={clsx(\"data-table\", maxHeight !== undefined && \"data-table--fill\")}\n >\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 aria-label={ariaLabel}\n dense={dense}\n striped={striped}\n maxHeight={maxHeight}\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={hasExplicitRowHeader ? col.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","ariaLabel","dense","striped","maxHeight","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","hasExplicitRowHeader","col","hasToolbar","filtered","useMemo","lower","k","sortColumn","sorted","handleSortChange","descriptor","totalPages","currentPage","pageData","getCell","jsxs","Flex","clsx","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 IconButton,\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 clsx from \"clsx\";\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 /** Marks the column that names the row for assistive technology. Defaults to the first column when no column sets it. */\n isRowHeader?: boolean;\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 <IconButton\n variant=\"neutral\"\n size=\"small\"\n aria-label={action.label}\n isDisabled={!allowed}\n onPress={allowed ? () => action.onPress(item) : undefined}\n >\n {action.icon}\n </IconButton>\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 /** Accessible name of the table. */\n ariaLabel?: string;\n /** Compact row height. Off by default. */\n dense?: boolean;\n /** Alternating row background. Off by default. */\n striped?: boolean;\n /**\n * Caps the height of the table so its rows scroll inside it with a sticky header, keeping the\n * pagination in view. A percentage needs a parent with a defined height. Off by default.\n */\n maxHeight?: number | string;\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 ariaLabel,\n dense,\n striped,\n maxHeight,\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 hasExplicitRowHeader = columns.some((col) => col.isRowHeader);\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\n direction=\"column\"\n gap=\"300\"\n className={clsx(\"data-table\", maxHeight !== undefined && \"data-table--fill\")}\n >\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 aria-label={ariaLabel}\n dense={dense}\n striped={striped}\n maxHeight={maxHeight}\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={hasExplicitRowHeader ? col.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","IconButton","PermissionGate","DataTable","columns","data","actions","rowActions","rowActionsLabel","selectable","selectionType","selectedKeys","onSelectionChange","defaultSortDescriptor","controlledSortDescriptor","onSortChange","ariaLabel","dense","striped","maxHeight","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","hasExplicitRowHeader","col","hasToolbar","filtered","useMemo","lower","k","sortColumn","sorted","handleSortChange","descriptor","totalPages","currentPage","pageData","getCell","jsxs","Flex","clsx","Search","v","Table","TableHead","TableColumn","idx","TableBody","cached","TableRow","TableCell","IconChevronDown","IconChevronRight","Pagination"],"mappings":"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"}
@@ -1,66 +1,67 @@
1
1
  import { jsxs as h, jsx as t } from "react/jsx-runtime";
2
- import { clsx as ge } from "../../../vendor/clsx/dist/clsx.js";
3
- import { useState as p, useMemo as G } from "react";
2
+ import { clsx as be } from "../../../vendor/clsx/dist/clsx.js";
3
+ import { useState as f, useMemo as z } from "react";
4
4
  /* empty css */
5
5
  import { Search as we } from "../../primitives/Search/Search.js";
6
- import { Table as xe, TableHead as Ne, TableColumn as D, TableBody as Se, TableRow as O, TableCell as N } from "../../primitives/Table/Table.js";
7
- import { IconChevronDown as ye } from "../../icons/IconChevronDown.js";
8
- import { IconChevronRight as ve } from "../../icons/IconChevronRight.js";
6
+ import { Table as xe, TableHead as Ne, TableColumn as L, TableBody as Se, TableRow as G, TableCell as N } from "../../primitives/Table/Table.js";
7
+ import { IconChevronDown as ve } from "../../icons/IconChevronDown.js";
8
+ import { IconChevronRight as ye } from "../../icons/IconChevronRight.js";
9
9
  import { Pagination as Ce } from "../../primitives/Pagination/Pagination.js";
10
10
  import { PermissionGate as Me } from "../../primitives/PermissionGate/PermissionGate.js";
11
- import { Flex as Re } from "../../layout/Flex/Flex.js";
11
+ import { Flex as Pe } from "../../layout/Flex/Flex.js";
12
+ import { IconButton as Re } from "../../primitives/IconButton/IconButton.js";
12
13
  const ke = new Intl.Collator(void 0, { numeric: !0, sensitivity: "base" });
13
- function Pe(n, r) {
14
+ function Te(n, r) {
14
15
  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 : ke.compare(String(n), String(r));
15
16
  }
16
- function Te(n, r, d) {
17
+ function De(n, r, d) {
17
18
  const o = r.sortValue ?? ((u) => u[r.key]), S = d === "descending" ? -1 : 1;
18
- return [...n].sort((u, f) => Pe(o(u), o(f)) * S);
19
+ return [...n].sort((u, p) => Te(o(u), o(p)) * S);
19
20
  }
20
21
  function Le({
21
22
  action: n,
22
23
  item: r
23
24
  }) {
24
25
  const d = n.isAllowed !== !1, o = /* @__PURE__ */ t(
25
- "button",
26
+ Re,
26
27
  {
27
- type: "button",
28
- className: "data-table-row-action-btn",
28
+ variant: "neutral",
29
+ size: "small",
29
30
  "aria-label": n.label,
30
- disabled: !d,
31
- onClick: d ? () => n.onPress(r) : void 0,
31
+ isDisabled: !d,
32
+ onPress: d ? () => n.onPress(r) : void 0,
32
33
  children: n.icon
33
34
  }
34
35
  );
35
36
  return d ? o : /* @__PURE__ */ t(Me, { isAllowed: !1, noAccessLabel: n.noAccessLabel ?? "", children: o });
36
37
  }
37
- function De({
38
+ function Ee({
38
39
  columns: n,
39
40
  data: r,
40
41
  actions: d,
41
42
  rowActions: o,
42
43
  rowActionsLabel: S = "",
43
44
  selectable: u = !1,
44
- selectionType: f = "checkbox",
45
- selectedKeys: Q,
46
- onSelectionChange: z,
45
+ selectionType: p = "checkbox",
46
+ selectedKeys: O,
47
+ onSelectionChange: Q,
47
48
  defaultSortDescriptor: J,
48
49
  sortDescriptor: U,
49
- onSortChange: y,
50
+ onSortChange: v,
50
51
  ariaLabel: W,
51
52
  dense: X,
52
53
  striped: Y,
53
54
  maxHeight: E,
54
55
  searchPlaceholder: Z = "Search...",
55
- searchKeys: v = [],
56
+ searchKeys: y = [],
56
57
  isLoading: _ = !1,
57
- loadingMessage: H = "Loading...",
58
+ loadingMessage: I = "Loading...",
58
59
  emptyMessage: A = "No records found",
59
60
  previousLabel: K = "Previous",
60
61
  nextLabel: ee = "Next",
61
62
  pageSize: m = 10,
62
- nestedColumns: I,
63
- getNestedData: j,
63
+ nestedColumns: H,
64
+ getNestedData: B,
64
65
  nestedLoadingMessage: ae = "Loading...",
65
66
  nestedEmptyMessage: te = "No records found",
66
67
  nestedSearchKeys: ne,
@@ -68,7 +69,7 @@ function De({
68
69
  nestedActions: C,
69
70
  nestedPageSize: le
70
71
  }) {
71
- const [M, se] = p(""), [oe, R] = p(1), [ie, de] = p(J), c = U ?? ie, [B, ce] = p(/* @__PURE__ */ new Set()), [F, b] = p(/* @__PURE__ */ new Map()), k = !!j && !!I, P = !!o;
72
+ const [M, se] = f(""), [oe, P] = f(1), [ie, de] = f(J), c = U ?? ie, [j, ce] = f(/* @__PURE__ */ new Set()), [F, g] = f(/* @__PURE__ */ new Map()), R = !!B && !!H, k = !!o;
72
73
  function V(e, a) {
73
74
  ce((s) => {
74
75
  const i = new Set(s);
@@ -76,57 +77,57 @@ function De({
76
77
  });
77
78
  }
78
79
  function ue(e) {
79
- const a = e.id, s = !B.has(a);
80
+ const a = e.id, s = !j.has(a);
80
81
  if (V(a, s), !s || F.has(a)) return;
81
- const i = j(e);
82
- i instanceof Promise ? (b((l) => new Map(l).set(a, { status: "loading", data: [] })), i.then(
82
+ const i = B(e);
83
+ i instanceof Promise ? (g((l) => new Map(l).set(a, { status: "loading", data: [] })), i.then(
83
84
  (l) => {
84
- b((x) => new Map(x).set(a, { status: "loaded", data: l }));
85
+ g((x) => new Map(x).set(a, { status: "loaded", data: l }));
85
86
  },
86
87
  () => {
87
- b((l) => {
88
+ g((l) => {
88
89
  const x = new Map(l);
89
90
  return x.delete(a), x;
90
91
  }), V(a, !1);
91
92
  }
92
- )) : b((l) => new Map(l).set(a, { status: "loaded", data: i }));
93
+ )) : g((l) => new Map(l).set(a, { status: "loaded", data: i }));
93
94
  }
94
- const g = v.length > 0, he = n.some((e) => e.isRowHeader), pe = g || !!d, w = G(() => {
95
- if (!M.trim() || !g) return r;
95
+ const b = y.length > 0, he = n.some((e) => e.isRowHeader), fe = b || !!d, w = z(() => {
96
+ if (!M.trim() || !b) return r;
96
97
  const e = M.toLowerCase();
97
98
  return r.filter(
98
- (a) => v.some(
99
+ (a) => y.some(
99
100
  (s) => String(a[s] ?? "").toLowerCase().includes(e)
100
101
  )
101
102
  );
102
- }, [r, M, v, g]), T = n.find((e) => e.sortable && String(e.key) === String(c == null ? void 0 : c.column)), $ = G(
103
- () => T && c ? Te(w, T, c.direction) : w,
103
+ }, [r, M, y, b]), T = n.find((e) => e.sortable && String(e.key) === String(c == null ? void 0 : c.column)), $ = z(
104
+ () => T && c ? De(w, T, c.direction) : w,
104
105
  [w, T, c]
105
106
  );
106
- function fe(e) {
107
- de(e), R(1), y == null || y(e);
107
+ function pe(e) {
108
+ de(e), P(1), v == null || v(e);
108
109
  }
109
- const q = Math.max(1, Math.ceil($.length / m)), L = Math.min(oe, q), me = $.slice(
110
- (L - 1) * m,
111
- L * m
110
+ const q = Math.max(1, Math.ceil($.length / m)), D = Math.min(oe, q), me = $.slice(
111
+ (D - 1) * m,
112
+ D * m
112
113
  );
113
- function be(e, a) {
114
+ function ge(e, a) {
114
115
  return a.render ? a.render(e) : String(e[a.key] ?? "");
115
116
  }
116
117
  return /* @__PURE__ */ h(
117
- Re,
118
+ Pe,
118
119
  {
119
120
  direction: "column",
120
121
  gap: "300",
121
- className: ge("data-table", E !== void 0 && "data-table--fill"),
122
+ className: be("data-table", E !== void 0 && "data-table--fill"),
122
123
  children: [
123
- pe && /* @__PURE__ */ h("div", { className: "data-table-toolbar", children: [
124
- g && /* @__PURE__ */ t(
124
+ fe && /* @__PURE__ */ h("div", { className: "data-table-toolbar", children: [
125
+ b && /* @__PURE__ */ t(
125
126
  we,
126
127
  {
127
128
  placeholder: Z,
128
129
  onSearch: (e) => {
129
- se(e), R(1);
130
+ se(e), P(1);
130
131
  },
131
132
  className: "data-table-search"
132
133
  }
@@ -138,9 +139,9 @@ function De({
138
139
  {
139
140
  role: "status",
140
141
  "aria-live": "polite",
141
- "aria-label": H,
142
+ "aria-label": I,
142
143
  className: "data-table-status",
143
- children: H
144
+ children: I
144
145
  }
145
146
  ) : w.length === 0 ? /* @__PURE__ */ t("div", { role: "status", className: "data-table-status data-table-empty", children: A }) : /* @__PURE__ */ h(
146
147
  xe,
@@ -149,17 +150,17 @@ function De({
149
150
  dense: X,
150
151
  striped: Y,
151
152
  maxHeight: E,
152
- selectionMode: u ? f === "radio" ? "single" : "multiple" : "none",
153
- selectionType: f,
154
- selectedKeys: Q,
155
- onSelectionChange: z,
153
+ selectionMode: u ? p === "radio" ? "single" : "multiple" : "none",
154
+ selectionType: p,
155
+ selectedKeys: O,
156
+ onSelectionChange: Q,
156
157
  sortDescriptor: c,
157
- onSortChange: fe,
158
+ onSortChange: pe,
158
159
  children: [
159
160
  /* @__PURE__ */ h(Ne, { children: [
160
- k && /* @__PURE__ */ t(D, { className: "data-table-expand-col" }),
161
+ R && /* @__PURE__ */ t(L, { className: "data-table-expand-col" }),
161
162
  n.map((e, a) => /* @__PURE__ */ t(
162
- D,
163
+ L,
163
164
  {
164
165
  id: String(e.key),
165
166
  align: e.align,
@@ -169,12 +170,12 @@ function De({
169
170
  },
170
171
  String(e.key)
171
172
  )),
172
- P && /* @__PURE__ */ t(D, { align: "right", className: "data-table-row-actions-col", children: S })
173
+ k && /* @__PURE__ */ t(L, { align: "right", className: "data-table-row-actions-col", children: S })
173
174
  ] }),
174
175
  /* @__PURE__ */ t(Se, { children: me.flatMap((e) => {
175
- const a = B.has(e.id), s = F.get(e.id), i = [
176
- /* @__PURE__ */ h(O, { id: e.id, children: [
177
- k && /* @__PURE__ */ t(N, { className: "data-table-expand-cell", children: /* @__PURE__ */ t(
176
+ const a = j.has(e.id), s = F.get(e.id), i = [
177
+ /* @__PURE__ */ h(G, { id: e.id, children: [
178
+ R && /* @__PURE__ */ t(N, { className: "data-table-expand-cell", children: /* @__PURE__ */ t(
178
179
  "button",
179
180
  {
180
181
  type: "button",
@@ -182,23 +183,23 @@ function De({
182
183
  "aria-label": a ? "Collapse row" : "Expand row",
183
184
  "aria-expanded": a,
184
185
  onClick: () => ue(e),
185
- children: a ? /* @__PURE__ */ t(ye, { size: "16" }) : /* @__PURE__ */ t(ve, { size: "16" })
186
+ children: a ? /* @__PURE__ */ t(ve, { size: "16" }) : /* @__PURE__ */ t(ye, { size: "16" })
186
187
  }
187
188
  ) }),
188
- n.map((l) => /* @__PURE__ */ t(N, { align: l.align, children: be(e, l) }, String(l.key))),
189
- P && /* @__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(Le, { action: l, item: e }, l.key)) }) })
189
+ n.map((l) => /* @__PURE__ */ t(N, { align: l.align, children: ge(e, l) }, String(l.key))),
190
+ k && /* @__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(Le, { action: l, item: e }, l.key)) }) })
190
191
  ] }, e.id)
191
192
  ];
192
193
  return a && i.push(
193
- /* @__PURE__ */ t(O, { id: `${e.id}-nested`, className: "data-table-nested-row", children: /* @__PURE__ */ t(
194
+ /* @__PURE__ */ t(G, { id: `${e.id}-nested`, className: "data-table-nested-row", children: /* @__PURE__ */ t(
194
195
  N,
195
196
  {
196
- colSpan: n.length + (k ? 1 : 0) + (u ? 1 : 0) + (P ? 1 : 0),
197
+ colSpan: n.length + (R ? 1 : 0) + (u ? 1 : 0) + (k ? 1 : 0),
197
198
  className: "data-table-nested-cell",
198
199
  children: /* @__PURE__ */ t(
199
- De,
200
+ Ee,
200
201
  {
201
- columns: I,
202
+ columns: H,
202
203
  data: (s == null ? void 0 : s.data) ?? [],
203
204
  isLoading: !s || s.status === "loading",
204
205
  loadingMessage: ae,
@@ -219,9 +220,9 @@ function De({
219
220
  /* @__PURE__ */ t(
220
221
  Ce,
221
222
  {
222
- page: L,
223
+ page: D,
223
224
  totalPages: q,
224
- onPageChange: R,
225
+ onPageChange: P,
225
226
  previousLabel: K,
226
227
  nextLabel: ee
227
228
  }
@@ -231,6 +232,6 @@ function De({
231
232
  );
232
233
  }
233
234
  export {
234
- De as DataTable
235
+ Ee as DataTable
235
236
  };
236
237
  //# 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 clsx from \"clsx\";\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 /** Marks the column that names the row for assistive technology. Defaults to the first column when no column sets it. */\n isRowHeader?: boolean;\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 /** Accessible name of the table. */\n ariaLabel?: string;\n /** Compact row height. Off by default. */\n dense?: boolean;\n /** Alternating row background. Off by default. */\n striped?: boolean;\n /**\n * Caps the height of the table so its rows scroll inside it with a sticky header, keeping the\n * pagination in view. A percentage needs a parent with a defined height. Off by default.\n */\n maxHeight?: number | string;\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 ariaLabel,\n dense,\n striped,\n maxHeight,\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 hasExplicitRowHeader = columns.some((col) => col.isRowHeader);\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\n direction=\"column\"\n gap=\"300\"\n className={clsx(\"data-table\", maxHeight !== undefined && \"data-table--fill\")}\n >\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 aria-label={ariaLabel}\n dense={dense}\n striped={striped}\n maxHeight={maxHeight}\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={hasExplicitRowHeader ? col.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","ariaLabel","dense","striped","maxHeight","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","hasExplicitRowHeader","col","hasToolbar","filtered","useMemo","lower","k","sortColumn","sorted","handleSortChange","descriptor","totalPages","currentPage","pageData","getCell","jsxs","Flex","clsx","Search","v","Table","TableHead","TableColumn","idx","TableBody","cached","TableRow","TableCell","IconChevronDown","IconChevronRight","Pagination"],"mappings":";;;;;;;;;;;AAkCA,MAAMA,KAAe,IAAI,KAAK,SAAS,QAAW,EAAE,SAAS,IAAM,aAAa,QAAQ;AAExF,SAASC,GAAsBC,GAAkBC,GAA0B;AACzE,SAAID,KAAK,QAAQC,KAAK,OAAaD,KAAK,OAAQC,KAAK,OAAO,IAAI,IAAK,KACjED,aAAa,QAAQC,aAAa,OAAaD,EAAE,QAAA,IAAYC,EAAE,QAAA,IAC/D,OAAOD,KAAM,YAAY,OAAOC,KAAM,WAAiBD,IAAIC,IACxDH,GAAa,QAAQ,OAAOE,CAAC,GAAG,OAAOC,CAAC,CAAC;AAClD;AAEA,SAASC,GAAYC,GAAWC,GAAmBC,GAA6C;AAC9F,QAAMC,IAAUF,EAAO,cAAc,CAACG,MAAaA,EAAiCH,EAAO,GAAa,IAClGI,IAAkBH,MAAc,eAAe,KAAK;AAC1D,SAAO,CAAC,GAAGF,CAAI,EAAE,KAAK,CAACH,GAAGC,MAAMF,GAAsBO,EAAQN,CAAC,GAAGM,EAAQL,CAAC,CAAC,IAAIO,CAAe;AACjG;AAiBA,SAASC,GAAmB;AAAA,EAC1B,QAAAC;AAAA,EACA,MAAAH;AACF,GAGG;AACD,QAAMI,IAAUD,EAAO,cAAc,IAC/BE,IACJ,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,WAAU;AAAA,MACV,cAAYH,EAAO;AAAA,MACnB,UAAU,CAACC;AAAA,MACX,SAASA,IAAU,MAAMD,EAAO,QAAQH,CAAI,IAAI;AAAA,MAE/C,UAAAG,EAAO;AAAA,IAAA;AAAA,EAAA;AAGZ,SAAIC,IAAgBC,IAElB,gBAAAC,EAACC,MAAe,WAAW,IAAO,eAAeJ,EAAO,iBAAiB,IACtE,UAAAE,EAAA,CACH;AAEJ;AAoEO,SAASG,GAAoC;AAAA,EAClD,SAAAC;AAAA,EACA,MAAAC;AAAA,EACA,SAAAC;AAAA,EACA,YAAAC;AAAA,EACA,iBAAAC,IAAkB;AAAA,EAClB,YAAAC,IAAa;AAAA,EACb,eAAAC,IAAgB;AAAA,EAChB,cAAAC;AAAA,EACA,mBAAAC;AAAA,EACA,uBAAAC;AAAA,EACA,gBAAgBC;AAAA,EAChB,cAAAC;AAAA,EACA,WAAAC;AAAA,EACA,OAAAC;AAAA,EACA,SAAAC;AAAA,EACA,WAAAC;AAAA,EACA,mBAAAC,IAAoB;AAAA,EACpB,YAAAC,IAAa,CAAA;AAAA,EACb,WAAAC,IAAY;AAAA,EACZ,gBAAAC,IAAiB;AAAA,EACjB,cAAAC,IAAe;AAAA,EACf,eAAAC,IAAgB;AAAA,EAChB,WAAAC,KAAY;AAAA,EACZ,UAAAC,IAAW;AAAA,EACX,eAAAC;AAAA,EACA,eAAAC;AAAA,EACA,sBAAAC,KAAuB;AAAA,EACvB,oBAAAC,KAAqB;AAAA,EACrB,kBAAAC;AAAA,EACA,yBAAAC;AAAA,EACA,eAAAC;AAAA,EACA,gBAAAC;AACF,GAAsB;AACpB,QAAM,CAACC,GAAOC,EAAQ,IAAIC,EAAS,EAAE,GAC/B,CAACC,IAAMC,CAAO,IAAIF,EAAS,CAAC,GAC5B,CAACG,IAAwBC,EAAyB,IAAIJ,EAASzB,CAAqB,GACpF8B,IAAiB7B,KAA4B2B,IAC7C,CAACG,GAAUC,EAAW,IAAIP,EAAsB,oBAAI,KAAK,GACzD,CAACQ,GAAaC,CAAc,IAAIT,EAAoC,oBAAI,KAAK,GAE7EU,IAAY,CAAC,CAACnB,KAAiB,CAAC,CAACD,GACjCqB,IAAgB,CAAC,CAAC1C;AAExB,WAAS2C,EAAeC,GAAYC,GAAqB;AACvD,IAAAP,GAAY,CAACQ,MAAS;AACpB,YAAMC,IAAO,IAAI,IAAID,CAAI;AACzB,aAAID,IAAYE,EAAK,IAAIH,CAAE,IACtBG,EAAK,OAAOH,CAAE,GACZG;AAAA,IACT,CAAC;AAAA,EACH;AAIA,WAASC,GAAU5D,GAAS;AAC1B,UAAMwD,IAAKxD,EAAK,IACV6D,IAAa,CAACZ,EAAS,IAAIO,CAAE;AAEnC,QADAD,EAAeC,GAAIK,CAAU,GACzB,CAACA,KAAcV,EAAY,IAAIK,CAAE,EAAG;AAExC,UAAMM,IAAS5B,EAAelC,CAAI;AAClC,IAAI8D,aAAkB,WACpBV,EAAe,CAACW,MAAM,IAAI,IAAIA,CAAC,EAAE,IAAIP,GAAI,EAAE,QAAQ,WAAW,MAAM,CAAA,EAAC,CAAG,CAAC,GACzEM,EAAO;AAAA,MACL,CAAClE,MAAS;AACR,QAAAwD,EAAe,CAACW,MAAM,IAAI,IAAIA,CAAC,EAAE,IAAIP,GAAI,EAAE,QAAQ,UAAU,MAAM5D,EAAA,CAAM,CAAC;AAAA,MAC5E;AAAA,MACA,MAAM;AAGJ,QAAAwD,EAAe,CAACW,MAAM;AACpB,gBAAMJ,IAAO,IAAI,IAAII,CAAC;AACtB,iBAAAJ,EAAK,OAAOH,CAAE,GACPG;AAAA,QACT,CAAC,GACDJ,EAAeC,GAAI,EAAK;AAAA,MAC1B;AAAA,IAAA,KAGFJ,EAAe,CAACW,MAAM,IAAI,IAAIA,CAAC,EAAE,IAAIP,GAAI,EAAE,QAAQ,UAAU,MAAMM,EAAA,CAAQ,CAAC;AAAA,EAEhF;AAEA,QAAME,IAAYtC,EAAW,SAAS,GAChCuC,KAAuBxD,EAAQ,KAAK,CAACyD,MAAQA,EAAI,WAAW,GAC5DC,KAAaH,KAAa,CAAC,CAACrD,GAE5ByD,IAAWC,EAAQ,MAAM;AAC7B,QAAI,CAAC5B,EAAM,KAAA,KAAU,CAACuB,EAAW,QAAOtD;AACxC,UAAM4D,IAAQ7B,EAAM,YAAA;AACpB,WAAO/B,EAAK;AAAA,MAAO,CAACV,MAClB0B,EAAW;AAAA,QAAK,CAAC6C,MACf,OAAOvE,EAAKuE,CAAC,KAAK,EAAE,EACjB,cACA,SAASD,CAAK;AAAA,MAAA;AAAA,IACnB;AAAA,EAEJ,GAAG,CAAC5D,GAAM+B,GAAOf,GAAYsC,CAAS,CAAC,GAEjCQ,IAAa/D,EAAQ,KAAK,CAACyD,MAAQA,EAAI,YAAY,OAAOA,EAAI,GAAG,MAAM,OAAOlB,KAAA,gBAAAA,EAAgB,MAAM,CAAC,GAErGyB,IAASJ;AAAA,IACb,MAAOG,KAAcxB,IAAiBrD,GAASyE,GAAUI,GAAYxB,EAAe,SAAS,IAAIoB;AAAA,IACjG,CAACA,GAAUI,GAAYxB,CAAc;AAAA,EAAA;AAGvC,WAAS0B,GAAiBC,GAA4B;AACpD,IAAA5B,GAA0B4B,CAAU,GACpC9B,EAAQ,CAAC,GACTzB,KAAA,QAAAA,EAAeuD;AAAA,EACjB;AAEA,QAAMC,IAAa,KAAK,IAAI,GAAG,KAAK,KAAKH,EAAO,SAASzC,CAAQ,CAAC,GAC5D6C,IAAc,KAAK,IAAIjC,IAAMgC,CAAU,GACvCE,KAAWL,EAAO;AAAA,KACrBI,IAAc,KAAK7C;AAAA,IACpB6C,IAAc7C;AAAA,EAAA;AAGhB,WAAS+C,GAAQ/E,GAASkE,GAA2B;AACnD,WAAIA,EAAI,SAAeA,EAAI,OAAOlE,CAAI,IAC/B,OAAQA,EAAiCkE,EAAI,GAAa,KAAK,EAAE;AAAA,EAC1E;AAEA,SACE,gBAAAc;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,KAAI;AAAA,MACJ,WAAWC,GAAK,cAAc1D,MAAc,UAAa,kBAAkB;AAAA,MAE1E,UAAA;AAAA,QAAA2C,MACC,gBAAAa,EAAC,OAAA,EAAI,WAAU,sBACZ,UAAA;AAAA,UAAAhB,KACC,gBAAA1D;AAAA,YAAC6E;AAAA,YAAA;AAAA,cACC,aAAa1D;AAAA,cACb,UAAU,CAAC2D,MAAM;AACf,gBAAA1C,GAAS0C,CAAC,GACVvC,EAAQ,CAAC;AAAA,cACX;AAAA,cACA,WAAU;AAAA,YAAA;AAAA,UAAA;AAAA,UAGblC,KAAW,gBAAAL,EAAC,OAAA,EAAI,WAAU,sBAAsB,UAAAK,EAAA,CAAQ;AAAA,QAAA,GAC3D;AAAA,QAGDgB,IACC,gBAAArB;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,aAAU;AAAA,YACV,cAAYsB;AAAA,YACZ,WAAU;AAAA,YAET,UAAAA;AAAA,UAAA;AAAA,QAAA,IAEDwC,EAAS,WAAW,IACtB,gBAAA9D,EAAC,OAAA,EAAI,MAAK,UAAS,WAAU,sCAC1B,UAAAuB,EAAA,CACH,IAEA,gBAAAmD;AAAA,UAACK;AAAA,UAAA;AAAA,YACC,cAAYhE;AAAA,YACZ,OAAAC;AAAA,YACA,SAAAC;AAAA,YACA,WAAAC;AAAA,YACA,eAAeV,IAAcC,MAAkB,UAAU,WAAW,aAAc;AAAA,YAClF,eAAAA;AAAA,YACA,cAAAC;AAAA,YACA,mBAAAC;AAAA,YACA,gBAAA+B;AAAA,YACA,cAAc0B;AAAA,YAEd,UAAA;AAAA,cAAA,gBAAAM,EAACM,IAAA,EACE,UAAA;AAAA,gBAAAjC,KAAa,gBAAA/C,EAACiF,GAAA,EAAY,WAAU,wBAAA,CAAwB;AAAA,gBAC5D9E,EAAQ,IAAI,CAACyD,GAAKsB,MACjB,gBAAAlF;AAAA,kBAACiF;AAAA,kBAAA;AAAA,oBAEC,IAAI,OAAOrB,EAAI,GAAG;AAAA,oBAClB,OAAOA,EAAI;AAAA,oBACX,eAAeA,EAAI;AAAA,oBACnB,aAAaD,KAAuBC,EAAI,cAAcsB,MAAQ;AAAA,oBAE7D,UAAAtB,EAAI;AAAA,kBAAA;AAAA,kBANA,OAAOA,EAAI,GAAG;AAAA,gBAAA,CAQtB;AAAA,gBACAZ,KACC,gBAAAhD,EAACiF,GAAA,EAAY,OAAM,SAAQ,WAAU,8BAClC,UAAA1E,EAAA,CACH;AAAA,cAAA,GAEJ;AAAA,cACA,gBAAAP,EAACmF,IAAA,EACE,UAAAX,GAAS,QAAQ,CAAC9E,MAAS;AAC1B,sBAAMyD,IAAaR,EAAS,IAAIjD,EAAK,EAAE,GACjC0F,IAASvC,EAAY,IAAInD,EAAK,EAAE,GAChCJ,IAAoB;AAAA,kBACxB,gBAAAoF,EAACW,GAAA,EAAuB,IAAI3F,EAAK,IAC9B,UAAA;AAAA,oBAAAqD,KACC,gBAAA/C,EAACsF,GAAA,EAAU,WAAU,0BACnB,UAAA,gBAAAtF;AAAA,sBAAC;AAAA,sBAAA;AAAA,wBACC,MAAK;AAAA,wBACL,WAAU;AAAA,wBACV,cAAYmD,IAAa,iBAAiB;AAAA,wBAC1C,iBAAeA;AAAA,wBACf,SAAS,MAAMG,GAAU5D,CAAI;AAAA,wBAE5B,UAAAyD,sBACEoC,IAAA,EAAgB,MAAK,MAAK,IAE3B,gBAAAvF,EAACwF,IAAA,EAAiB,MAAK,KAAA,CAAK;AAAA,sBAAA;AAAA,oBAAA,GAGlC;AAAA,oBAEDrF,EAAQ,IAAI,CAACyD,MACZ,gBAAA5D,EAACsF,KAAgC,OAAO1B,EAAI,OACzC,UAAAa,GAAQ/E,GAAMkE,CAAG,EAAA,GADJ,OAAOA,EAAI,GAAG,CAE9B,CACD;AAAA,oBACAZ,KACC,gBAAAhD,EAACsF,GAAA,EAAU,OAAM,SAAQ,WAAU,+BACjC,UAAA,gBAAAtF,EAAC,OAAA,EAAI,WAAU,0BACX,WAAA,OAAOM,KAAe,aACpBA,EAAWZ,CAAI,IACfY,GACF,IAAI,CAACT,MACL,gBAAAG,EAACJ,IAAA,EAAiC,QAAAC,GAAgB,MAAAH,EAAA,GAA5BG,EAAO,GAAiC,CAC/D,GACH,EAAA,CACF;AAAA,kBAAA,EAAA,GAjCWH,EAAK,EAmCpB;AAAA,gBAAA;AAEF,uBAAIyD,KACF7D,EAAK;AAAA,kBACH,gBAAAU,EAACqF,KAAmC,IAAI,GAAG3F,EAAK,EAAE,WAAW,WAAU,yBACrE,UAAA,gBAAAM;AAAA,oBAACsF;AAAA,oBAAA;AAAA,sBACC,SACEnF,EAAQ,UACP4C,IAAY,IAAI,MAChBvC,IAAa,IAAI,MACjBwC,IAAgB,IAAI;AAAA,sBAEvB,WAAU;AAAA,sBAEV,UAAA,gBAAAhD;AAAA,wBAACE;AAAA,wBAAA;AAAA,0BACC,SAASyB;AAAA,0BACT,OAAMyD,KAAA,gBAAAA,EAAQ,SAAQ,CAAA;AAAA,0BACtB,WAAW,CAACA,KAAUA,EAAO,WAAW;AAAA,0BACxC,gBAAgBvD;AAAA,0BAChB,cAAcC;AAAA,0BACd,YAAYC;AAAA,0BACZ,mBAAmBC;AAAA,0BACnB,SAASC,KAAA,gBAAAA,EAAgBvC;AAAA,0BACzB,UAAUwC,MAAkBR;AAAA,wBAAA;AAAA,sBAAA;AAAA,oBAC9B;AAAA,kBAAA,EACF,GArBa,GAAGhC,EAAK,EAAE,SAsBzB;AAAA,gBAAA,GAGGJ;AAAA,cACT,CAAC,EAAA,CACH;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAIJ,gBAAAU;AAAA,UAACyF;AAAA,UAAA;AAAA,YACC,MAAMlB;AAAA,YACN,YAAAD;AAAA,YACA,cAAc/B;AAAA,YACd,eAAAf;AAAA,YACA,WAAAC;AAAA,UAAA;AAAA,QAAA;AAAA,MACF;AAAA,IAAA;AAAA,EAAA;AAGN;"}
1
+ {"version":3,"file":"DataTable.js","sources":["../../../../../src/ui/components/DataTable/DataTable.tsx"],"sourcesContent":["import {\n IconButton,\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 clsx from \"clsx\";\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 /** Marks the column that names the row for assistive technology. Defaults to the first column when no column sets it. */\n isRowHeader?: boolean;\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 <IconButton\n variant=\"neutral\"\n size=\"small\"\n aria-label={action.label}\n isDisabled={!allowed}\n onPress={allowed ? () => action.onPress(item) : undefined}\n >\n {action.icon}\n </IconButton>\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 /** Accessible name of the table. */\n ariaLabel?: string;\n /** Compact row height. Off by default. */\n dense?: boolean;\n /** Alternating row background. Off by default. */\n striped?: boolean;\n /**\n * Caps the height of the table so its rows scroll inside it with a sticky header, keeping the\n * pagination in view. A percentage needs a parent with a defined height. Off by default.\n */\n maxHeight?: number | string;\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 ariaLabel,\n dense,\n striped,\n maxHeight,\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 hasExplicitRowHeader = columns.some((col) => col.isRowHeader);\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\n direction=\"column\"\n gap=\"300\"\n className={clsx(\"data-table\", maxHeight !== undefined && \"data-table--fill\")}\n >\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 aria-label={ariaLabel}\n dense={dense}\n striped={striped}\n maxHeight={maxHeight}\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={hasExplicitRowHeader ? col.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","IconButton","PermissionGate","DataTable","columns","data","actions","rowActions","rowActionsLabel","selectable","selectionType","selectedKeys","onSelectionChange","defaultSortDescriptor","controlledSortDescriptor","onSortChange","ariaLabel","dense","striped","maxHeight","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","hasExplicitRowHeader","col","hasToolbar","filtered","useMemo","lower","k","sortColumn","sorted","handleSortChange","descriptor","totalPages","currentPage","pageData","getCell","jsxs","Flex","clsx","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 e=require("react/jsx-runtime"),j=require("../../../vendor/clsx/dist/clsx.cjs");;/* empty css */const r=require("../../primitives/Dialog/Dialog.cjs"),n=require("../../layout/Flex/Flex.cjs"),a=require("../../primitives/Button/Button.cjs");function f({isOpen:o,title:s,submitLabel:t="Save",cancelLabel:c="Cancel",isLoading:l=!1,isSubmitDisabled:d=!1,size:u="medium",onSubmit:m,onClose:i,children:x}){return o?e.jsx(r.DialogModal,{isOpen:o,onOpenChange:g=>!g&&i(),children:e.jsxs(r.Dialog,{className:j.clsx("form-modal",`form-modal--${u}`),children:[e.jsxs(n.Flex,{direction:"row",alignPrimary:"space-between",alignSecondary:"center",children:[e.jsx(r.DialogTitle,{children:s}),e.jsx(r.DialogClose,{onPress:i})]}),e.jsx(r.DialogBody,{children:e.jsx(n.Flex,{direction:"column",gap:"300",children:x})}),e.jsxs(n.Flex,{direction:"row",gap:"200",alignPrimary:"end",className:"form-modal-footer",children:[e.jsx(a.Button,{variant:"neutral",onPress:i,isDisabled:l,children:c}),e.jsx(a.Button,{variant:"primary",onPress:m,isDisabled:d||l,children:l?"...":t})]})]})}):null}exports.FormModal=f;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime");;/* empty css */const r=require("../../primitives/Dialog/Dialog.cjs"),n=require("../../layout/Flex/Flex.cjs"),o=require("../../primitives/Button/Button.cjs");function j({isOpen:a,title:s,submitLabel:t="Save",cancelLabel:c="Cancel",isLoading:i=!1,isSubmitDisabled:d=!1,size:u="medium",onSubmit:m,onClose:l,children:x}){return a?e.jsx(r.DialogModal,{isOpen:a,onOpenChange:g=>!g&&l(),children:e.jsxs(r.Dialog,{className:"form-modal",size:u,children:[e.jsxs(n.Flex,{direction:"row",alignPrimary:"space-between",alignSecondary:"center",children:[e.jsx(r.DialogTitle,{children:s}),e.jsx(r.DialogClose,{onPress:l})]}),e.jsx(r.DialogBody,{children:e.jsx(n.Flex,{direction:"column",gap:"300",children:x})}),e.jsxs(n.Flex,{direction:"row",gap:"200",alignPrimary:"end",className:"form-modal-footer",children:[e.jsx(o.Button,{variant:"neutral",onPress:l,isDisabled:i,children:c}),e.jsx(o.Button,{variant:"primary",onPress:m,isDisabled:d||i,children:i?"...":t})]})]})}):null}exports.FormModal=j;
2
2
  //# sourceMappingURL=FormModal.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"FormModal.cjs","sources":["../../../../../src/ui/components/FormModal/FormModal.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport {\n Button,\n Dialog,\n DialogBody,\n DialogClose,\n DialogModal,\n DialogTitle,\n} from \"primitives\";\nimport { Flex } from \"layout\";\nimport type { ReactNode } from \"react\";\nimport \"./formmodal.css\";\n\nexport type FormModalSize = \"medium\" | \"large\" | \"xlarge\";\n\nexport interface FormModalProps {\n isOpen: boolean;\n title: string;\n submitLabel?: string;\n cancelLabel?: string;\n isLoading?: boolean;\n isSubmitDisabled?: boolean;\n /**\n * Maximum width of the dialog. Defaults to `\"medium\"`, which preserves the\n * previous fixed width. Use `\"large\"`/`\"xlarge\"` for forms that embed wide\n * content such as tables.\n */\n size?: FormModalSize;\n onSubmit: () => void;\n onClose: () => void;\n children: ReactNode;\n}\n\nexport function FormModal({\n isOpen,\n title,\n submitLabel = \"Save\",\n cancelLabel = \"Cancel\",\n isLoading = false,\n isSubmitDisabled = false,\n size = \"medium\",\n onSubmit,\n onClose,\n children,\n}: FormModalProps) {\n if (!isOpen) return null;\n\n return (\n <DialogModal isOpen={isOpen} onOpenChange={(open) => !open && onClose()}>\n <Dialog className={clsx(\"form-modal\", `form-modal--${size}`)}>\n <Flex direction=\"row\" alignPrimary=\"space-between\" alignSecondary=\"center\">\n <DialogTitle>{title}</DialogTitle>\n <DialogClose onPress={onClose} />\n </Flex>\n <DialogBody>\n <Flex direction=\"column\" gap=\"300\">\n {children}\n </Flex>\n </DialogBody>\n <Flex\n direction=\"row\"\n gap=\"200\"\n alignPrimary=\"end\"\n className=\"form-modal-footer\"\n >\n <Button variant=\"neutral\" onPress={onClose} isDisabled={isLoading}>\n {cancelLabel}\n </Button>\n <Button\n variant=\"primary\"\n onPress={onSubmit}\n isDisabled={isSubmitDisabled || isLoading}\n >\n {isLoading ? \"...\" : submitLabel}\n </Button>\n </Flex>\n </Dialog>\n </DialogModal>\n );\n}\n"],"names":["FormModal","isOpen","title","submitLabel","cancelLabel","isLoading","isSubmitDisabled","size","onSubmit","onClose","children","DialogModal","open","jsxs","Dialog","clsx","Flex","jsx","DialogTitle","DialogClose","DialogBody","Button"],"mappings":"kVAiCO,SAASA,EAAU,CACxB,OAAAC,EACA,MAAAC,EACA,YAAAC,EAAc,OACd,YAAAC,EAAc,SACd,UAAAC,EAAY,GACZ,iBAAAC,EAAmB,GACnB,KAAAC,EAAO,SACP,SAAAC,EACA,QAAAC,EACA,SAAAC,CACF,EAAmB,CACjB,OAAKT,QAGFU,cAAA,CAAY,OAAAV,EAAgB,aAAeW,GAAS,CAACA,GAAQH,IAC5D,SAAAI,EAAAA,KAACC,EAAAA,QAAO,UAAWC,OAAK,aAAc,eAAeR,CAAI,EAAE,EACzD,SAAA,CAAAM,OAACG,EAAAA,MAAK,UAAU,MAAM,aAAa,gBAAgB,eAAe,SAChE,SAAA,CAAAC,EAAAA,IAACC,EAAAA,aAAa,SAAAhB,CAAA,CAAM,EACpBe,EAAAA,IAACE,EAAAA,YAAA,CAAY,QAASV,CAAA,CAAS,CAAA,EACjC,EACAQ,EAAAA,IAACG,EAAAA,YACC,SAAAH,EAAAA,IAACD,EAAAA,KAAA,CAAK,UAAU,SAAS,IAAI,MAC1B,SAAAN,CAAA,CACH,CAAA,CACF,EACAG,EAAAA,KAACG,EAAAA,KAAA,CACC,UAAU,MACV,IAAI,MACJ,aAAa,MACb,UAAU,oBAEV,SAAA,CAAAC,EAAAA,IAACI,EAAAA,QAAO,QAAQ,UAAU,QAASZ,EAAS,WAAYJ,EACrD,SAAAD,CAAA,CACH,EACAa,EAAAA,IAACI,EAAAA,OAAA,CACC,QAAQ,UACR,QAASb,EACT,WAAYF,GAAoBD,EAE/B,WAAY,MAAQF,CAAA,CAAA,CACvB,CAAA,CAAA,CACF,CAAA,CACF,CAAA,CACF,EAhCkB,IAkCtB"}
1
+ {"version":3,"file":"FormModal.cjs","sources":["../../../../../src/ui/components/FormModal/FormModal.tsx"],"sourcesContent":["import {\n Button,\n Dialog,\n DialogBody,\n DialogClose,\n DialogModal,\n DialogTitle,\n type DialogSize,\n} from \"primitives\";\nimport { Flex } from \"layout\";\nimport type { ReactNode } from \"react\";\nimport \"./formmodal.css\";\n\nexport type FormModalSize = DialogSize;\n\nexport interface FormModalProps {\n isOpen: boolean;\n title: string;\n submitLabel?: string;\n cancelLabel?: string;\n isLoading?: boolean;\n isSubmitDisabled?: boolean;\n /**\n * Maximum width of the dialog. Defaults to `\"medium\"`, which preserves the\n * previous fixed width. Use `\"large\"`/`\"xlarge\"` for forms that embed wide\n * content such as tables.\n */\n size?: FormModalSize;\n onSubmit: () => void;\n onClose: () => void;\n children: ReactNode;\n}\n\nexport function FormModal({\n isOpen,\n title,\n submitLabel = \"Save\",\n cancelLabel = \"Cancel\",\n isLoading = false,\n isSubmitDisabled = false,\n size = \"medium\",\n onSubmit,\n onClose,\n children,\n}: FormModalProps) {\n if (!isOpen) return null;\n\n return (\n <DialogModal isOpen={isOpen} onOpenChange={(open) => !open && onClose()}>\n <Dialog className=\"form-modal\" size={size}>\n <Flex direction=\"row\" alignPrimary=\"space-between\" alignSecondary=\"center\">\n <DialogTitle>{title}</DialogTitle>\n <DialogClose onPress={onClose} />\n </Flex>\n <DialogBody>\n <Flex direction=\"column\" gap=\"300\">\n {children}\n </Flex>\n </DialogBody>\n <Flex\n direction=\"row\"\n gap=\"200\"\n alignPrimary=\"end\"\n className=\"form-modal-footer\"\n >\n <Button variant=\"neutral\" onPress={onClose} isDisabled={isLoading}>\n {cancelLabel}\n </Button>\n <Button\n variant=\"primary\"\n onPress={onSubmit}\n isDisabled={isSubmitDisabled || isLoading}\n >\n {isLoading ? \"...\" : submitLabel}\n </Button>\n </Flex>\n </Dialog>\n </DialogModal>\n );\n}\n"],"names":["FormModal","isOpen","title","submitLabel","cancelLabel","isLoading","isSubmitDisabled","size","onSubmit","onClose","children","jsx","DialogModal","open","jsxs","Dialog","Flex","DialogTitle","DialogClose","DialogBody","Button"],"mappings":"kSAiCO,SAASA,EAAU,CACxB,OAAAC,EACA,MAAAC,EACA,YAAAC,EAAc,OACd,YAAAC,EAAc,SACd,UAAAC,EAAY,GACZ,iBAAAC,EAAmB,GACnB,KAAAC,EAAO,SACP,SAAAC,EACA,QAAAC,EACA,SAAAC,CACF,EAAmB,CACjB,OAAKT,EAGHU,EAAAA,IAACC,EAAAA,YAAA,CAAY,OAAAX,EAAgB,aAAeY,GAAS,CAACA,GAAQJ,EAAA,EAC5D,SAAAK,EAAAA,KAACC,EAAAA,OAAA,CAAO,UAAU,aAAa,KAAAR,EAC7B,SAAA,CAAAO,OAACE,EAAAA,MAAK,UAAU,MAAM,aAAa,gBAAgB,eAAe,SAChE,SAAA,CAAAL,EAAAA,IAACM,EAAAA,aAAa,SAAAf,CAAA,CAAM,EACpBS,EAAAA,IAACO,EAAAA,YAAA,CAAY,QAAST,CAAA,CAAS,CAAA,EACjC,EACAE,EAAAA,IAACQ,EAAAA,YACC,SAAAR,EAAAA,IAACK,EAAAA,KAAA,CAAK,UAAU,SAAS,IAAI,MAC1B,SAAAN,CAAA,CACH,CAAA,CACF,EACAI,EAAAA,KAACE,EAAAA,KAAA,CACC,UAAU,MACV,IAAI,MACJ,aAAa,MACb,UAAU,oBAEV,SAAA,CAAAL,EAAAA,IAACS,EAAAA,QAAO,QAAQ,UAAU,QAASX,EAAS,WAAYJ,EACrD,SAAAD,CAAA,CACH,EACAO,EAAAA,IAACS,EAAAA,OAAA,CACC,QAAQ,UACR,QAASZ,EACT,WAAYF,GAAoBD,EAE/B,WAAY,MAAQF,CAAA,CAAA,CACvB,CAAA,CAAA,CACF,CAAA,CACF,CAAA,CACF,EAhCkB,IAkCtB"}