@carto/ps-react-ui 4.20.1 → 4.20.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/widgets/table.js +13 -16
- package/dist/widgets/table.js.map +1 -1
- package/dist/widgets-v2/pie.js +7 -7
- package/dist/widgets-v2/pie.js.map +1 -1
- package/package.json +3 -3
- package/src/widgets/table/components/pagination-actions.tsx +4 -4
- package/src/widgets-v2/pie/options.test.ts +67 -0
- package/src/widgets-v2/pie/options.ts +27 -4
- package/src/widgets-v2/selection-summary/selection-summary.test.tsx +1 -1
- package/src/widgets-v2/toolbox/toolbox.test.tsx +1 -1
package/dist/widgets/table.js
CHANGED
|
@@ -6,11 +6,8 @@ import { c as a } from "react/compiler-runtime";
|
|
|
6
6
|
import "react";
|
|
7
7
|
import { Box as o, Checkbox as s, IconButton as c, Link as l, Paper as u, Skeleton as d, Table as f, TableBody as p, TableCell as m, TableContainer as h, TableHead as g, TablePagination as _, TableRow as v, TableSortLabel as y, Typography as b } from "@mui/material";
|
|
8
8
|
import { jsx as x, jsxs as S } from "react/jsx-runtime";
|
|
9
|
-
import C from "
|
|
10
|
-
import
|
|
11
|
-
import T from "@mui/icons-material/KeyboardArrowLeft";
|
|
12
|
-
import E from "@mui/icons-material/KeyboardArrowRight";
|
|
13
|
-
import D from "@mui/icons-material/LastPage";
|
|
9
|
+
import { FirstPage as C, KeyboardArrowLeft as w, KeyboardArrowRight as T, LastPage as E } from "@mui/icons-material";
|
|
10
|
+
import D from "react-markdown";
|
|
14
11
|
//#region src/widgets/table/components/cell-header.tsx
|
|
15
12
|
function O(e) {
|
|
16
13
|
let t = a(26), { column: n, sortState: r, onSort: i, isSelectAll: o, isAllSelected: c, isIndeterminate: l, onSelectAll: u } = e;
|
|
@@ -127,7 +124,7 @@ function F(e) {
|
|
|
127
124
|
}
|
|
128
125
|
if (typeof i == "string") {
|
|
129
126
|
let e;
|
|
130
|
-
t[7] === i ? e = t[8] : (e = /* @__PURE__ */ x(
|
|
127
|
+
t[7] === i ? e = t[8] : (e = /* @__PURE__ */ x(D, {
|
|
131
128
|
components: P,
|
|
132
129
|
children: i
|
|
133
130
|
}), t[7] = i, t[8] = e);
|
|
@@ -220,16 +217,16 @@ function L(e) {
|
|
|
220
217
|
ml: 2.5
|
|
221
218
|
}, t[11] = v) : v = t[11];
|
|
222
219
|
let y = r === 0, b;
|
|
223
|
-
t[12] === Symbol.for("react.memo_cache_sentinel") ? (b = /* @__PURE__ */ x(
|
|
224
|
-
let
|
|
225
|
-
t[13] !== d || t[14] !== y ? (
|
|
220
|
+
t[12] === Symbol.for("react.memo_cache_sentinel") ? (b = /* @__PURE__ */ x(C, {}), t[12] = b) : b = t[12];
|
|
221
|
+
let D;
|
|
222
|
+
t[13] !== d || t[14] !== y ? (D = /* @__PURE__ */ x(c, {
|
|
226
223
|
onClick: d,
|
|
227
224
|
disabled: y,
|
|
228
225
|
"aria-label": "first page",
|
|
229
226
|
children: b
|
|
230
|
-
}), t[13] = d, t[14] = y, t[15] =
|
|
227
|
+
}), t[13] = d, t[14] = y, t[15] = D) : D = t[15];
|
|
231
228
|
let O = r === 0, k;
|
|
232
|
-
t[16] === Symbol.for("react.memo_cache_sentinel") ? (k = /* @__PURE__ */ x(
|
|
229
|
+
t[16] === Symbol.for("react.memo_cache_sentinel") ? (k = /* @__PURE__ */ x(w, {}), t[16] = k) : k = t[16];
|
|
233
230
|
let A;
|
|
234
231
|
t[17] !== p || t[18] !== O ? (A = /* @__PURE__ */ x(c, {
|
|
235
232
|
onClick: p,
|
|
@@ -238,7 +235,7 @@ function L(e) {
|
|
|
238
235
|
children: k
|
|
239
236
|
}), t[17] = p, t[18] = O, t[19] = A) : A = t[19];
|
|
240
237
|
let j = r >= l, M;
|
|
241
|
-
t[20] === Symbol.for("react.memo_cache_sentinel") ? (M = /* @__PURE__ */ x(
|
|
238
|
+
t[20] === Symbol.for("react.memo_cache_sentinel") ? (M = /* @__PURE__ */ x(T, {}), t[20] = M) : M = t[20];
|
|
242
239
|
let N;
|
|
243
240
|
t[21] !== h || t[22] !== j ? (N = /* @__PURE__ */ x(c, {
|
|
244
241
|
onClick: h,
|
|
@@ -247,7 +244,7 @@ function L(e) {
|
|
|
247
244
|
children: M
|
|
248
245
|
}), t[21] = h, t[22] = j, t[23] = N) : N = t[23];
|
|
249
246
|
let P = r >= l, F;
|
|
250
|
-
t[24] === Symbol.for("react.memo_cache_sentinel") ? (F = /* @__PURE__ */ x(
|
|
247
|
+
t[24] === Symbol.for("react.memo_cache_sentinel") ? (F = /* @__PURE__ */ x(E, {}), t[24] = F) : F = t[24];
|
|
251
248
|
let I;
|
|
252
249
|
t[25] !== _ || t[26] !== P ? (I = /* @__PURE__ */ x(c, {
|
|
253
250
|
onClick: _,
|
|
@@ -256,15 +253,15 @@ function L(e) {
|
|
|
256
253
|
children: F
|
|
257
254
|
}), t[25] = _, t[26] = P, t[27] = I) : I = t[27];
|
|
258
255
|
let L;
|
|
259
|
-
return t[28] !== A || t[29] !== N || t[30] !== I || t[31] !==
|
|
256
|
+
return t[28] !== A || t[29] !== N || t[30] !== I || t[31] !== D ? (L = /* @__PURE__ */ S(o, {
|
|
260
257
|
sx: v,
|
|
261
258
|
children: [
|
|
262
|
-
|
|
259
|
+
D,
|
|
263
260
|
A,
|
|
264
261
|
N,
|
|
265
262
|
I
|
|
266
263
|
]
|
|
267
|
-
}), t[28] = A, t[29] = N, t[30] = I, t[31] =
|
|
264
|
+
}), t[28] = A, t[29] = N, t[30] = I, t[31] = D, t[32] = L) : L = t[32], L;
|
|
268
265
|
}
|
|
269
266
|
//#endregion
|
|
270
267
|
//#region src/widgets/table/components/pagination.tsx
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"table.js","names":["TableCell","TableSortLabel","Checkbox","CellHeaderProps","CellHeader","t0","$","_c","column","sortState","onSort","isSelectAll","isAllSelected","isIndeterminate","onSelectAll","t1","Symbol","for","t2","isSorted","columnId","id","sortDirection","direction","undefined","sortable","width","t3","t4","label","t5","align","ReactNode","getCellValue","cellValue","T","undefined","Array","isArray","formatted","map","item","String","join","JSON","stringify","compareValues","a","b","direction","comparison","localeCompare","strA","strB","sortData","Record","data","columnId","sort","paginateData","page","rowsPerPage","start","end","slice","TableCell","MuiTableCell","Link","Typography","ReactMarkdown","Components","TableColumn","TableRow","getCellValue","ReactNode","CellProps","column","row","value","DEFAULT_P","t0","$","_c","children","t1","CELL_MARKDOWN_COMPONENTS","h1","h2","h3","p","a","href","isExternal","startsWith","undefined","img","ul","ol","li","Cell","formatter","align","t2","t3","TableRow","MuiTableRow","TableCell","Checkbox","RowProps","Cell","Row","t0","$","_c","row","columns","isSelected","t1","selectable","t2","onClick","onSelect","onMouseEnter","onMouseLeave","undefined","t3","handleClick","t4","event","stopPropagation","handleCheckboxClick","t5","handleMouseEnter","t6","handleMouseLeave","t7","t8","t9","cursor","t10","id","t11","t12","column","map","Box","IconButton","FirstPageIcon","KeyboardArrowLeft","KeyboardArrowRight","LastPageIcon","PaginationActionsProps","PaginationActions","t0","$","_c","count","page","rowsPerPage","onPageChange","lastPage","Math","max","ceil","t1","event","handleFirstPage","t2","event_0","handlePreviousPage","t3","event_1","handleNextPage","t4","event_2","handleLastPage","t5","Symbol","for","flexShrink","ml","t6","t7","t8","t9","t10","t11","t12","t13","t14","t15","t16","t17","t18","TablePagination","MuiTablePagination","PaginationProps","PaginationActions","Pagination","t0","$","_c","page","rowsPerPage","total","rowsPerPageOptions","t1","onPageChange","onRowsPerPageChange","t2","undefined","t3","_event","newPage","handlePageChange","t4","event","parseInt","target","value","handleRowsPerPageChange","t5","Table","MuiTable","TableBody","TableCell","TableHead","TableContainer","MuiTableContainer","Paper","TableProps","MuiTableProps","Ref","CellHeader","Row","Pagination","PaginationActions","useWidgetRef","TableUIProps","TableComponentProps","ref","HTMLTableElement","t0","$","_c","children","props","t1","stickyHeader","undefined","t2","Head","Body","Cell","Container","id","downloadToCSV","downloadToPNG","ConfigProps","TableDownloadConfig","TableWidgetConfig","TableColumn","Mode","SortDirection","DEFAULT_MODE","DEFAULT_PAGE","DEFAULT_ROWS_PER_PAGE","DEFAULT_ROWS_PER_PAGE_OPTIONS","DEFAULT_COLUMN_ID","DEFAULT_DIRECTION","tableDownloadConfig","refUI","modifier","data","length","firstRow","headers","Object","keys","filter","key","rows","map","row","header","value","undefined","JSON","stringify","tableConfig","columns","selectable","mode","useCallback","useMemo","TableRow","TableWidgetState","paginateData","widgetStoreActions","useWidgetSelector","DEFAULT_PAGE","DEFAULT_ROWS_PER_PAGE","DEFAULT_ROWS_PER_PAGE_OPTIONS","UsePaginationResult","paginationEnabled","page","rowsPerPage","total","rowsPerPageOptions","paginatedData","T","setPage","setRowsPerPage","goToFirstPage","goToLastPage","goToNextPage","goToPreviousPage","usePagination","widgetId","data","$","_c","t0","length","w","widget","pagination","mode","maxPage","Math","max","ceil","t1","newPage","widget_0","getWidget","currentTotal","currentRowsPerPage","currentMaxPage","boundedPage","min","setWidget","t2","newRowsPerPage","widget_1","t3","t4","t5","t6","t7","bb0","t8","useCallback","useMemo","TableRow","SortDirection","SortState","TableWidgetState","sortData","widgetStoreActions","useWidgetSelector","DEFAULT_COLUMN_ID","DEFAULT_DIRECTION","UseSortResult","sortEnabled","columnId","direction","sortedData","T","toggleSort","setSort","clearSort","useSort","widgetId","data","$","_c","mode","_temp","t0","toggleColumnId","widget_0","getWidget","currentColumnId","widget","sort","currentDirection","newDirection","setWidget","t1","newColumnId","newDirection_0","t2","widget_1","t3","bb0","t4","w","useCallback","useMemo","TableRow","TableWidgetState","widgetStoreActions","useWidgetSelector","UseSelectionOptions","onSelectionChange","selectedIds","UseSelectionResult","isSelected","id","isAllSelected","rows","isIndeterminate","toggleRow","toggleAll","selectRows","ids","deselectRows","clearSelection","useSelection","widgetId","options","$","_c","t0","selected","_temp","t1","t2","includes","t3","length","every","row","t4","rows_0","selectedCount","filter","row_0","t5","id_0","widget","getWidget","currentSelected","newSelected","s","setWidget","t6","rows_1","widget_0","currentSelected_0","rowIds","map","_temp2","allSelected","id_1","newSelected_0","id_2","Set","t7","widget_1","currentSelected_1","newSelected_1","t8","ids_0","widget_2","currentSelected_2","newSelected_2","id_3","t9","newSelected_3","t10","row_1","w","Box","Skeleton","Table","TableBody","TableCell","TableHead","TableRow","TableSkeletonProps","columns","rows","TableSkeleton","t0","$","_c","t1","t2","undefined","t3","Array","from","length","map","_temp","t4","t5","__0","rowIndex","_temp2","t6","__1","colIndex","_","index","TableRow","TableWidgetData","sanitizeTableRow","row","sanitized","id","key","value","Object","entries","Array","isArray","JSON","stringify","undefined","sanitizeTableData","data","map","SxProps","Theme","styles","container","width","overflow","table","minWidth","headerCell","fontWeight","backgroundColor","theme","palette","background","paper","row","border","rowHover","action","hover","rowSelected","selected","pagination","borderTop","divider","Record"],"sources":["../../src/widgets/table/components/cell-header.tsx","../../src/widgets/table/helpers.ts","../../src/widgets/table/components/cell.tsx","../../src/widgets/table/components/row.tsx","../../src/widgets/table/components/pagination-actions.tsx","../../src/widgets/table/components/pagination.tsx","../../src/widgets/table/table-ui.tsx","../../src/widgets/table/config.ts","../../src/widgets/table/hooks/use-pagination.ts","../../src/widgets/table/hooks/use-sort.ts","../../src/widgets/table/hooks/use-selection.ts","../../src/widgets/table/skeleton.tsx","../../src/widgets/table/serializer.ts","../../src/widgets/table/style.ts"],"sourcesContent":["import { TableCell, TableSortLabel, Checkbox } from '@mui/material'\nimport type { CellHeaderProps } from '../types'\n\n/**\n * Table cell header component with optional sorting and select-all checkbox\n */\nexport function CellHeader({\n column,\n sortState,\n onSort,\n isSelectAll,\n isAllSelected,\n isIndeterminate,\n onSelectAll,\n}: CellHeaderProps) {\n // Render select-all checkbox\n if (isSelectAll) {\n return (\n <TableCell padding='checkbox'>\n <Checkbox\n checked={isAllSelected}\n indeterminate={isIndeterminate}\n onChange={onSelectAll}\n inputProps={{ 'aria-label': 'select all rows' }}\n />\n </TableCell>\n )\n }\n\n const isSorted = sortState?.columnId === column.id\n const sortDirection = isSorted ? sortState.direction : undefined\n\n // Render sortable column header\n if (column.sortable && onSort) {\n return (\n <TableCell\n align={column.align}\n style={{ width: column.width }}\n sortDirection={sortDirection}\n >\n <TableSortLabel\n active={isSorted}\n direction={sortDirection ?? 'asc'}\n onClick={() => onSort(column.id)}\n >\n {column.label}\n </TableSortLabel>\n </TableCell>\n )\n }\n\n // Render non-sortable column header\n return (\n <TableCell align={column.align} style={{ width: column.width }}>\n {column.label}\n </TableCell>\n )\n}\n","import type { ReactNode } from 'react'\n\n/**\n * Get formatted cell value for display\n * Handles primitives, arrays, objects, and custom formatters\n *\n * @param cellValue - Raw cell value\n * @param formatter - Optional formatter function\n * @returns Formatted value for display\n */\nexport function getCellValue<T>(cellValue: T): ReactNode {\n // Handle null/undefined\n if (cellValue === null || cellValue === undefined) {\n return ''\n }\n\n // Handle arrays - format as [item1, item2, ...]\n if (Array.isArray(cellValue)) {\n const formatted = cellValue\n .map((item) => (typeof item === 'string' ? `\"${item}\"` : String(item)))\n .join(', ')\n return `[${formatted}]`\n }\n\n // Handle objects - stringify to JSON\n if (typeof cellValue === 'object') {\n return JSON.stringify(cellValue)\n }\n\n // Return primitives as-is (string, number, boolean)\n return cellValue as ReactNode\n}\n\n/**\n * Compare two values for sorting\n * Handles strings, numbers, and other types\n *\n * @param a - First value\n * @param b - Second value\n * @param direction - Sort direction\n * @returns Comparison result (-1, 0, 1)\n */\nexport function compareValues(\n a: unknown,\n b: unknown,\n direction: 'asc' | 'desc',\n): number {\n // Handle null/undefined - always sort to end\n if (a === null || a === undefined) return 1\n if (b === null || b === undefined) return -1\n\n let comparison = 0\n\n if (typeof a === 'string' && typeof b === 'string') {\n comparison = a.localeCompare(b)\n } else if (typeof a === 'number' && typeof b === 'number') {\n comparison = a - b\n } else if (typeof a === 'boolean' && typeof b === 'boolean') {\n comparison = a === b ? 0 : a ? 1 : -1\n } else if (typeof a === 'object' || typeof b === 'object') {\n // Compare objects/arrays as JSON strings\n const strA = JSON.stringify(a)\n const strB = JSON.stringify(b)\n comparison = strA.localeCompare(strB)\n } else {\n // Fallback for other primitives (bigint, symbol, etc.)\n comparison = 0\n }\n\n return direction === 'asc' ? comparison : -comparison\n}\n\n/**\n * Sort data array by column\n *\n * @param data - Data array to sort\n * @param columnId - Column ID to sort by\n * @param direction - Sort direction\n * @returns Sorted data array (new array, does not mutate original)\n */\nexport function sortData<T extends Record<string, unknown>>(\n data: T[],\n columnId: string,\n direction: 'asc' | 'desc',\n): T[] {\n return [...data].sort((a, b) =>\n compareValues(a[columnId], b[columnId], direction),\n )\n}\n\n/**\n * Paginate data array\n *\n * @param data - Data array to paginate\n * @param page - Current page (0-indexed)\n * @param rowsPerPage - Number of rows per page\n * @returns Paginated data slice\n */\nexport function paginateData<T>(\n data: T[],\n page: number,\n rowsPerPage: number,\n): T[] {\n const start = page * rowsPerPage\n const end = start + rowsPerPage\n return data.slice(start, end)\n}\n","import { TableCell as MuiTableCell, Link, Typography } from '@mui/material'\nimport ReactMarkdown, { type Components } from 'react-markdown'\nimport type { TableColumn, TableRow } from '../types'\nimport { getCellValue } from '../helpers'\nimport type { ReactNode } from 'react'\n\n/**\n * Props for Cell component\n */\nexport interface CellProps {\n /** Column definition */\n column: TableColumn\n /** Full table row for context */\n row: TableRow\n /** Cell value */\n value: unknown\n}\n\nconst DEFAULT_P = ({ children }: { children?: ReactNode }) => (\n <Typography component='span' variant='body2' color='inherit'>\n {children}\n </Typography>\n)\n\n/**\n * Markdown components for cell content\n * Uses compact styling suitable for table cells (reusing Note widget pattern)\n */\nconst CELL_MARKDOWN_COMPONENTS: Components = {\n h1: DEFAULT_P,\n h2: DEFAULT_P,\n h3: DEFAULT_P,\n p: DEFAULT_P,\n a: ({ children, href }) => {\n const isExternal = href?.startsWith('http')\n return (\n <Link\n href={href}\n target={isExternal ? '_blank' : undefined}\n rel={isExternal ? 'noopener noreferrer' : undefined}\n color='text.primary'\n underline='always'\n >\n {children}\n </Link>\n )\n },\n img: () => null,\n ul: DEFAULT_P,\n ol: DEFAULT_P,\n li: DEFAULT_P,\n}\n\n/**\n * Table cell component with automatic markdown support for string values\n * Markdown is rendered when the raw value is a string and no formatter is defined.\n * If a formatter is used, its output is rendered directly without markdown parsing.\n */\nexport function Cell({ column, row, value }: CellProps) {\n // If formatter is defined, use it directly without markdown\n if (column.formatter) {\n return (\n <MuiTableCell align={column.align}>\n {column.formatter(value, row)}\n </MuiTableCell>\n )\n }\n\n // For string values without formatter, render as markdown\n if (typeof value === 'string') {\n return (\n <MuiTableCell align={column.align}>\n <ReactMarkdown components={CELL_MARKDOWN_COMPONENTS}>\n {value}\n </ReactMarkdown>\n </MuiTableCell>\n )\n }\n\n // For non-string values, render directly\n return <MuiTableCell align={column.align}>{getCellValue(value)}</MuiTableCell>\n}\n","import { TableRow as MuiTableRow, TableCell, Checkbox } from '@mui/material'\nimport type { RowProps } from '../types'\nimport { Cell } from './cell'\n\n/**\n * Table row component with selection and hover support\n */\nexport function Row({\n row,\n columns,\n isSelected = false,\n selectable = false,\n onClick,\n onSelect,\n onMouseEnter,\n onMouseLeave,\n}: RowProps) {\n const handleClick = () => {\n onClick?.(row)\n }\n\n const handleCheckboxClick = (event: React.MouseEvent) => {\n event.stopPropagation()\n onSelect?.(row)\n }\n\n const handleMouseEnter = () => {\n onMouseEnter?.(row)\n }\n\n const handleMouseLeave = () => {\n onMouseLeave?.()\n }\n\n return (\n <MuiTableRow\n hover={!!onMouseEnter || !!onMouseLeave || !!onClick}\n selected={isSelected}\n onClick={handleClick}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n sx={{\n cursor: onClick ? 'pointer' : 'default',\n }}\n >\n {selectable && (\n <TableCell padding='checkbox'>\n <Checkbox\n checked={isSelected}\n onClick={handleCheckboxClick}\n inputProps={{ 'aria-label': `select row ${row.id}` }}\n />\n </TableCell>\n )}\n {columns.map((column) => (\n <Cell\n key={column.id}\n row={row}\n column={column}\n value={row[column.id]}\n />\n ))}\n </MuiTableRow>\n )\n}\n","import { Box, IconButton } from '@mui/material'\nimport FirstPageIcon from '@mui/icons-material/FirstPage'\nimport KeyboardArrowLeft from '@mui/icons-material/KeyboardArrowLeft'\nimport KeyboardArrowRight from '@mui/icons-material/KeyboardArrowRight'\nimport LastPageIcon from '@mui/icons-material/LastPage'\nimport type { PaginationActionsProps } from '../types'\n\n/**\n * Custom pagination actions with first/prev/next/last buttons\n */\nexport function PaginationActions({\n count,\n page,\n rowsPerPage,\n onPageChange,\n}: PaginationActionsProps) {\n const lastPage = Math.max(0, Math.ceil(count / rowsPerPage) - 1)\n\n const handleFirstPage = (event: React.MouseEvent<HTMLButtonElement>) => {\n onPageChange(event, 0)\n }\n\n const handlePreviousPage = (event: React.MouseEvent<HTMLButtonElement>) => {\n onPageChange(event, page - 1)\n }\n\n const handleNextPage = (event: React.MouseEvent<HTMLButtonElement>) => {\n onPageChange(event, page + 1)\n }\n\n const handleLastPage = (event: React.MouseEvent<HTMLButtonElement>) => {\n onPageChange(event, lastPage)\n }\n\n return (\n <Box sx={{ flexShrink: 0, ml: 2.5 }}>\n <IconButton\n onClick={handleFirstPage}\n disabled={page === 0}\n aria-label='first page'\n >\n <FirstPageIcon />\n </IconButton>\n <IconButton\n onClick={handlePreviousPage}\n disabled={page === 0}\n aria-label='previous page'\n >\n <KeyboardArrowLeft />\n </IconButton>\n <IconButton\n onClick={handleNextPage}\n disabled={page >= lastPage}\n aria-label='next page'\n >\n <KeyboardArrowRight />\n </IconButton>\n <IconButton\n onClick={handleLastPage}\n disabled={page >= lastPage}\n aria-label='last page'\n >\n <LastPageIcon />\n </IconButton>\n </Box>\n )\n}\n","import { TablePagination as MuiTablePagination } from '@mui/material'\nimport type { PaginationProps } from '../types'\nimport { PaginationActions } from './pagination-actions'\n\n/**\n * Table pagination component\n */\nexport function Pagination({\n page,\n rowsPerPage,\n total,\n rowsPerPageOptions = [5, 10, 25, 50],\n onPageChange,\n onRowsPerPageChange,\n}: PaginationProps) {\n const handlePageChange = (\n _event: React.MouseEvent<HTMLButtonElement> | null,\n newPage: number,\n ) => {\n onPageChange(newPage)\n }\n\n const handleRowsPerPageChange = (\n event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,\n ) => {\n onRowsPerPageChange(parseInt(event.target.value, 10))\n }\n\n return (\n <MuiTablePagination\n component='div'\n count={total}\n page={page}\n rowsPerPage={rowsPerPage}\n rowsPerPageOptions={rowsPerPageOptions}\n onPageChange={handlePageChange}\n onRowsPerPageChange={handleRowsPerPageChange}\n ActionsComponent={PaginationActions}\n />\n )\n}\n","import {\n Table as MuiTable,\n TableBody,\n TableCell,\n TableHead,\n TableContainer as MuiTableContainer,\n Paper,\n type TableProps as MuiTableProps,\n} from '@mui/material'\nimport type { Ref } from 'react'\nimport { CellHeader } from './components/cell-header'\nimport { Row } from './components/row'\nimport { Pagination } from './components/pagination'\nimport { PaginationActions } from './components/pagination-actions'\nimport { useWidgetRef } from '../../hooks'\nimport type { TableUIProps } from './types'\n\n/**\n * Props for the base Table component\n */\ninterface TableComponentProps extends MuiTableProps {\n /** Table element ref */\n ref?: Ref<HTMLTableElement>\n}\n\n/**\n * Base Table component with compound component pattern\n * Provides Table.Head, Table.Body, Table.Row, Table.Cell, Table.CellHeader, Table.Pagination\n */\nfunction Table({\n children,\n ref,\n stickyHeader = true,\n ...props\n}: TableComponentProps) {\n return (\n <MuiTable stickyHeader={stickyHeader} ref={ref} {...props}>\n {children}\n </MuiTable>\n )\n}\n\n// Attach sub-components as static properties\nTable.Head = TableHead\nTable.CellHeader = CellHeader\nTable.Body = TableBody\nTable.Row = Row\nTable.Cell = TableCell\nTable.Container = TableContainer\nTable.Paper = Paper\nTable.Pagination = Pagination\nTable.PaginationActions = PaginationActions\n\nexport { Table }\n\n/**\n * TableContainer widget component\n * Integrates with widget store and provides ref registration using custom hook\n */\nfunction TableContainer(props: TableUIProps) {\n const { ref } = useWidgetRef<HTMLDivElement>(props.id)\n\n return <MuiTableContainer ref={ref}>{props.children}</MuiTableContainer>\n}\n","import { downloadToCSV, downloadToPNG } from '../actions'\nimport type { ConfigProps } from '../loader/types'\nimport type {\n TableDownloadConfig,\n TableWidgetConfig,\n TableColumn,\n Mode,\n SortDirection,\n} from './types'\n\nconst DEFAULT_MODE: Mode = 'local'\nexport const DEFAULT_PAGE = 0\nexport const DEFAULT_ROWS_PER_PAGE = 10\nexport const DEFAULT_ROWS_PER_PAGE_OPTIONS = [5, 10, 25, 50]\n\nexport const DEFAULT_COLUMN_ID = null\nexport const DEFAULT_DIRECTION: SortDirection = 'asc'\n\n/**\n * Creates download configuration for table widgets, supporting PNG (screenshot) and CSV (data) exports. CSV output uses column keys as headers and filters out `id` fields.\n *\n * @param props - Configuration with `refUI` reference for PNG export.\n * @returns Array of download items for use with the Download action.\n */\nexport function tableDownloadConfig({\n refUI,\n}: ConfigProps): TableDownloadConfig {\n return [\n {\n ...downloadToPNG,\n modifier: () => downloadToPNG.modifier(refUI),\n },\n {\n ...downloadToCSV,\n modifier: async (data) => {\n if (!data?.length) {\n return downloadToCSV.modifier([])\n }\n\n // Convert table data to CSV format\n // First row contains headers (column keys)\n const firstRow = data[0]\n if (!firstRow) {\n return downloadToCSV.modifier([])\n }\n\n const headers = Object.keys(firstRow).filter((key) => key !== 'id')\n const rows = data.map((row) =>\n headers.map((header) => {\n const value = row[header]\n if (value === null || value === undefined) return ''\n if (typeof value === 'object') return JSON.stringify(value)\n return value\n }),\n )\n\n return downloadToCSV.modifier([headers, ...rows])\n },\n },\n ]\n}\n\n/**\n * Returns the default configuration for table widgets with pagination and sorting, including column definitions and local data mode.\n *\n * @param columns - Array of column definitions for the table.\n * @returns Default table widget config.\n */\nexport function tableConfig(columns: TableColumn[] = []): TableWidgetConfig {\n return {\n columns,\n selectable: false,\n mode: DEFAULT_MODE,\n }\n}\n","import { useCallback, useMemo } from 'react'\nimport type { TableRow, TableWidgetState } from '../types'\nimport { paginateData } from '../helpers'\nimport { widgetStoreActions } from '../../stores/widget-store'\nimport { useWidgetSelector } from '../../stores/use-widget-selector'\nimport {\n DEFAULT_PAGE,\n DEFAULT_ROWS_PER_PAGE,\n DEFAULT_ROWS_PER_PAGE_OPTIONS,\n} from '../config'\n\nexport interface UsePaginationResult<T> {\n /** Whether pagination is enabled */\n paginationEnabled: boolean\n /** Current page (0-indexed) */\n page: number\n /** Rows per page */\n rowsPerPage: number\n /** Total row count */\n total: number\n /** Available rows per page options */\n rowsPerPageOptions: number[]\n /** Paginated data (for local mode) */\n paginatedData: T[]\n /** Set current page */\n setPage: (page: number) => void\n /** Set rows per page */\n setRowsPerPage: (rowsPerPage: number) => void\n /** Go to first page */\n goToFirstPage: () => void\n /** Go to last page */\n goToLastPage: () => void\n /** Go to next page */\n goToNextPage: () => void\n /** Go to previous page */\n goToPreviousPage: () => void\n}\n\n/**\n * Hook for managing table pagination with support for both local (client-side) and remote (server-side) modes.\n * State is persisted in the widget store for the given widget ID.\n *\n * @param widgetId - The widget ID to persist pagination state under.\n * @param data - The full data array (used for local pagination and total count fallback).\n * @returns Pagination state and navigation helpers.\n *\n * @example\n * ```tsx\n * const { page, setPage, paginatedData, totalPages } = usePagination(widgetId, data)\n * ```\n */\nexport function usePagination<T extends TableRow>(\n widgetId: string,\n data: T[],\n): UsePaginationResult<T> {\n // Get store state\n const {\n paginationEnabled,\n page,\n rowsPerPage,\n rowsPerPageOptions,\n total,\n mode,\n } = useWidgetSelector(widgetId, (w) => {\n const widget = w as TableWidgetState | undefined\n return {\n paginationEnabled: !!widget?.pagination,\n page: widget?.pagination?.page ?? DEFAULT_PAGE,\n rowsPerPage: widget?.pagination?.rowsPerPage ?? DEFAULT_ROWS_PER_PAGE,\n rowsPerPageOptions:\n widget?.pagination?.rowsPerPageOptions ?? DEFAULT_ROWS_PER_PAGE_OPTIONS,\n total: widget?.pagination?.total ?? data.length,\n mode: widget?.mode,\n }\n })\n\n // Calculate max page\n const maxPage = Math.max(0, Math.ceil(total / (rowsPerPage ?? 1)) - 1)\n\n // Set page with bounds checking\n const setPage = useCallback(\n (newPage: number) => {\n // Read current state directly from store to avoid stale closures\n const widget = widgetStoreActions.getWidget<TableWidgetState>(widgetId)\n const currentTotal = widget?.pagination?.total ?? data.length\n const currentRowsPerPage =\n widget?.pagination?.rowsPerPage ?? DEFAULT_ROWS_PER_PAGE\n const currentMaxPage = Math.max(\n 0,\n Math.ceil(currentTotal / currentRowsPerPage) - 1,\n )\n const boundedPage = Math.max(0, Math.min(newPage, currentMaxPage))\n\n widgetStoreActions.setWidget<TableWidgetState>(widgetId, {\n pagination: {\n ...widget?.pagination,\n page: boundedPage,\n },\n })\n },\n [data.length, widgetId],\n )\n\n // Set rows per page and reset to first page\n const setRowsPerPage = useCallback(\n (newRowsPerPage: number) => {\n const widget = widgetStoreActions.getWidget<TableWidgetState>(widgetId)\n widgetStoreActions.setWidget<TableWidgetState>(widgetId, {\n pagination: {\n ...widget?.pagination,\n rowsPerPage: newRowsPerPage,\n page: 0, // Reset to first page when changing rows per page\n },\n })\n },\n [widgetId],\n )\n\n // Navigation helpers\n const goToFirstPage = useCallback(() => setPage(0), [setPage])\n const goToLastPage = useCallback(() => setPage(maxPage), [setPage, maxPage])\n const goToNextPage = useCallback(() => setPage(page + 1), [setPage, page])\n const goToPreviousPage = useCallback(() => setPage(page - 1), [setPage, page])\n\n // Paginated data for local mode\n const paginatedData = useMemo(() => {\n if (mode === 'remote' || !paginationEnabled) {\n // For remote mode, data is already paginated from server\n return data\n }\n return paginateData(data, page, rowsPerPage)\n }, [data, mode, page, paginationEnabled, rowsPerPage])\n\n return {\n paginationEnabled,\n page,\n rowsPerPage,\n rowsPerPageOptions,\n total,\n paginatedData,\n setPage,\n setRowsPerPage,\n goToFirstPage,\n goToLastPage,\n goToNextPage,\n goToPreviousPage,\n }\n}\n","import { useCallback, useMemo } from 'react'\nimport type {\n TableRow,\n SortDirection,\n SortState,\n TableWidgetState,\n} from '../types'\nimport { sortData } from '../helpers'\nimport { widgetStoreActions } from '../../stores/widget-store'\nimport { useWidgetSelector } from '../../stores/use-widget-selector'\nimport { DEFAULT_COLUMN_ID, DEFAULT_DIRECTION } from '../config'\n\nexport interface UseSortResult<T> extends SortState {\n /** Whether sorting is enabled */\n sortEnabled: boolean\n /** Current sort state */\n columnId: string | null\n direction: SortDirection\n /** Sorted data (for local mode) */\n sortedData: T[]\n /** Toggle sort on a column */\n toggleSort: (columnId: string) => void\n /** Set sort state directly */\n setSort: (columnId: string | null, direction: SortDirection) => void\n /** Clear sort */\n clearSort: () => void\n}\n\n/**\n * Hook for managing table sorting with support for both local (client-side) and remote (server-side) modes.\n * State is persisted in the widget store for the given widget ID.\n *\n * @param widgetId - The widget ID to persist sort state under.\n * @param data - The data array to sort (for local mode).\n * @returns Sort state, sorted data, and sort control functions.\n *\n * @example\n * ```tsx\n * const { sortedData, sortField, sortDirection, handleSort } = useSort(widgetId, data)\n * ```\n */\nexport function useSort<T extends TableRow>(\n widgetId: string,\n data: T[],\n): UseSortResult<T> {\n // Get store state\n const { sortEnabled, columnId, direction, mode } = useWidgetSelector(\n widgetId,\n (w) => {\n const widget = w as TableWidgetState | undefined\n return {\n sortEnabled: !!widget?.sort,\n columnId: widget?.sort?.columnId ?? DEFAULT_COLUMN_ID,\n direction: widget?.sort?.direction ?? DEFAULT_DIRECTION,\n mode: widget?.mode,\n }\n },\n )\n\n // Toggle sort on a column\n const toggleSort = useCallback(\n (toggleColumnId: string) => {\n // Read current state directly from store to avoid stale closures\n const widget = widgetStoreActions.getWidget<TableWidgetState>(widgetId)\n const currentColumnId = widget?.sort?.columnId ?? DEFAULT_COLUMN_ID\n const currentDirection = widget?.sort?.direction ?? DEFAULT_DIRECTION\n\n let newDirection: SortDirection = 'asc'\n\n if (currentColumnId === toggleColumnId) {\n // Same column - toggle direction\n newDirection = currentDirection === 'asc' ? 'desc' : 'asc'\n }\n\n widgetStoreActions.setWidget<TableWidgetState>(widgetId, {\n sort: {\n columnId: toggleColumnId,\n direction: newDirection,\n },\n })\n },\n [widgetId],\n )\n\n // Set sort state directly\n const setSort = useCallback(\n (newColumnId: string | null, newDirection: SortDirection) => {\n widgetStoreActions.setWidget<TableWidgetState>(widgetId, {\n sort: {\n columnId: newColumnId,\n direction: newDirection,\n },\n })\n },\n [widgetId],\n )\n\n // Clear sort\n const clearSort = useCallback(() => {\n const widget = widgetStoreActions.getWidget<TableWidgetState>(widgetId)\n if (!widget?.sort) return\n\n widgetStoreActions.setWidget<TableWidgetState>(widgetId, {\n sort: {\n ...widget.sort,\n columnId: null,\n direction: 'asc',\n },\n })\n }, [widgetId])\n\n // Sorted data for local mode\n const sortedData = useMemo(() => {\n if (mode === 'remote' || !columnId || !sortEnabled) {\n // For remote mode, data is already sorted from server\n // If no sort column, return original data\n return data\n }\n return sortData(data, columnId, direction)\n }, [data, mode, columnId, direction, sortEnabled])\n\n return {\n sortEnabled,\n columnId,\n direction,\n sortedData,\n toggleSort,\n setSort,\n clearSort,\n }\n}\n","import { useCallback, useMemo } from 'react'\nimport type { TableRow, TableWidgetState } from '../types'\nimport { widgetStoreActions } from '../../stores/widget-store'\nimport { useWidgetSelector } from '../../stores/use-widget-selector'\n\nexport interface UseSelectionOptions {\n /** Callback when selection changes */\n onSelectionChange?: (selectedIds: (string | number)[]) => void\n}\n\nexport interface UseSelectionResult {\n /** Array of selected row IDs */\n selectedIds: (string | number)[]\n /** Check if a row is selected */\n isSelected: (id: string | number) => boolean\n /** Check if all provided rows are selected */\n isAllSelected: (rows: TableRow[]) => boolean\n /** Check if some but not all rows are selected (for indeterminate state) */\n isIndeterminate: (rows: TableRow[]) => boolean\n /** Toggle selection of a single row */\n toggleRow: (id: string | number) => void\n /** Toggle selection of all provided rows */\n toggleAll: (rows: TableRow[]) => void\n /** Select specific rows */\n selectRows: (ids: (string | number)[]) => void\n /** Deselect specific rows */\n deselectRows: (ids: (string | number)[]) => void\n /** Clear all selections */\n clearSelection: () => void\n}\n\n/**\n * Hook for managing table row selection with persistence across pagination.\n * Selection state is stored in the widget store for the given widget ID.\n *\n * @param widgetId - The widget ID to persist selection state under.\n * @param options - Optional configuration including an `onSelectionChange` callback.\n * @returns Selection state and control functions (toggle, select, deselect, clear).\n *\n * @example\n * ```tsx\n * const { selectedIds, isAllSelected, handleSelectRow, clearSelection } = useSelection(widgetId)\n * ```\n */\nexport function useSelection(\n widgetId: string,\n options?: UseSelectionOptions,\n): UseSelectionResult {\n const { onSelectionChange } = options ?? {}\n\n // Get store state\n const selected = useWidgetSelector(\n widgetId,\n (w) => (w as TableWidgetState | undefined)?.selected,\n )\n\n // Use store values with fallback to empty array\n const selectedIds = useMemo(() => selected ?? [], [selected])\n\n // Check if a row is selected\n const isSelected = useCallback(\n (id: string | number) => selectedIds.includes(id),\n [selectedIds],\n )\n\n // Check if all provided rows are selected\n const isAllSelected = useCallback(\n (rows: TableRow[]) => {\n if (rows.length === 0) return false\n return rows.every((row) => selectedIds.includes(row.id))\n },\n [selectedIds],\n )\n\n // Check if some but not all rows are selected\n const isIndeterminate = useCallback(\n (rows: TableRow[]) => {\n if (rows.length === 0) return false\n const selectedCount = rows.filter((row) =>\n selectedIds.includes(row.id),\n ).length\n return selectedCount > 0 && selectedCount < rows.length\n },\n [selectedIds],\n )\n\n // Toggle selection of a single row\n const toggleRow = useCallback(\n (id: string | number) => {\n const widget = widgetStoreActions.getWidget<TableWidgetState>(widgetId)\n const currentSelected = widget?.selected ?? []\n\n const newSelected = currentSelected.includes(id)\n ? currentSelected.filter((s) => s !== id)\n : [...currentSelected, id]\n\n widgetStoreActions.setWidget<TableWidgetState>(widgetId, {\n selected: newSelected,\n })\n\n if (onSelectionChange) {\n onSelectionChange(newSelected)\n }\n },\n [widgetId, onSelectionChange],\n )\n\n // Toggle selection of all provided rows\n const toggleAll = useCallback(\n (rows: TableRow[]) => {\n const widget = widgetStoreActions.getWidget<TableWidgetState>(widgetId)\n const currentSelected = widget?.selected ?? []\n\n const rowIds = rows.map((row) => row.id)\n const allSelected = rowIds.every((id) => currentSelected.includes(id))\n\n const newSelected = allSelected\n ? currentSelected.filter((id) => !rowIds.includes(id))\n : [...new Set([...currentSelected, ...rowIds])]\n\n widgetStoreActions.setWidget<TableWidgetState>(widgetId, {\n selected: newSelected,\n })\n\n if (onSelectionChange) {\n onSelectionChange(newSelected)\n }\n },\n [widgetId, onSelectionChange],\n )\n\n // Select specific rows\n const selectRows = useCallback(\n (ids: (string | number)[]) => {\n const widget = widgetStoreActions.getWidget<TableWidgetState>(widgetId)\n const currentSelected = widget?.selected ?? []\n\n const newSelected = [...new Set([...currentSelected, ...ids])]\n\n widgetStoreActions.setWidget<TableWidgetState>(widgetId, {\n selected: newSelected,\n })\n\n if (onSelectionChange) {\n onSelectionChange(newSelected)\n }\n },\n [widgetId, onSelectionChange],\n )\n\n // Deselect specific rows\n const deselectRows = useCallback(\n (ids: (string | number)[]) => {\n const widget = widgetStoreActions.getWidget<TableWidgetState>(widgetId)\n const currentSelected = widget?.selected ?? []\n\n const newSelected = currentSelected.filter((id) => !ids.includes(id))\n\n widgetStoreActions.setWidget<TableWidgetState>(widgetId, {\n selected: newSelected,\n })\n\n if (onSelectionChange) {\n onSelectionChange(newSelected)\n }\n },\n [widgetId, onSelectionChange],\n )\n\n // Clear all selections\n const clearSelection = useCallback(() => {\n const newSelected: (string | number)[] = []\n\n widgetStoreActions.setWidget<TableWidgetState>(widgetId, {\n selected: newSelected,\n })\n\n if (onSelectionChange) {\n onSelectionChange(newSelected)\n }\n }, [widgetId, onSelectionChange])\n\n return {\n selectedIds,\n isSelected,\n isAllSelected,\n isIndeterminate,\n toggleRow,\n toggleAll,\n selectRows,\n deselectRows,\n clearSelection,\n }\n}\n","import {\n Box,\n Skeleton,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableRow,\n} from '@mui/material'\n\nexport interface TableSkeletonProps {\n /** Number of columns to display */\n columns?: number\n /** Number of rows to display */\n rows?: number\n}\n\n/**\n * Table skeleton loader component\n */\nexport function TableSkeleton({ columns = 4, rows = 5 }: TableSkeletonProps) {\n return (\n <Box aria-label='Table skeleton'>\n <Table>\n <TableHead>\n <TableRow>\n {Array.from({ length: columns }).map((_, index) => (\n <TableCell key={index}>\n <Skeleton width='80%' height={24} />\n </TableCell>\n ))}\n </TableRow>\n </TableHead>\n <TableBody>\n {Array.from({ length: rows }).map((_, rowIndex) => (\n <TableRow key={rowIndex}>\n {Array.from({ length: columns }).map((_, colIndex) => (\n <TableCell key={colIndex}>\n <Skeleton width='70%' height={20} />\n </TableCell>\n ))}\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </Box>\n )\n}\n","import type { TableRow, TableWidgetData } from './types'\n\n/**\n * Sanitizes a table row by ensuring all values are serializable.\n * Converts ReactNode and function values to undefined.\n *\n * @param row - The table row to sanitize\n * @returns A sanitized table row\n */\nexport function sanitizeTableRow(row: TableRow): TableRow {\n const sanitized: TableRow = { id: row.id }\n\n for (const [key, value] of Object.entries(row)) {\n if (key === 'id') continue\n\n // Keep primitive values\n if (\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean' ||\n value === null\n ) {\n sanitized[key] = value\n }\n // Serialize arrays and plain objects\n else if (Array.isArray(value) || typeof value === 'object') {\n try {\n // Attempt to serialize - if it fails, the value contains non-serializable content\n JSON.stringify(value)\n sanitized[key] = value\n } catch {\n sanitized[key] = undefined\n }\n }\n // Skip functions and other non-serializable values\n else {\n sanitized[key] = undefined\n }\n }\n\n return sanitized\n}\n\n/**\n * Sanitizes table widget data by ensuring all rows are serializable.\n *\n * @param data - The table data to sanitize\n * @returns Sanitized table data\n */\nexport function sanitizeTableData(\n data: TableWidgetData | undefined,\n): TableWidgetData | undefined {\n return data?.map(sanitizeTableRow)\n}\n","import type { SxProps, Theme } from '@mui/material'\n\nexport const styles = {\n container: {\n width: '100%',\n overflow: 'auto',\n },\n table: {\n minWidth: 650,\n },\n headerCell: {\n fontWeight: 600,\n backgroundColor: (theme: Theme) => theme.palette.background.paper,\n },\n row: {\n '&:last-child td, &:last-child th': {\n border: 0,\n },\n },\n rowHover: {\n '&:hover': {\n backgroundColor: (theme: Theme) => theme.palette.action.hover,\n },\n },\n rowSelected: {\n backgroundColor: (theme: Theme) => theme.palette.action.selected,\n '&:hover': {\n backgroundColor: (theme: Theme) => theme.palette.action.selected,\n },\n },\n pagination: {\n borderTop: (theme: Theme) => `1px solid ${theme.palette.divider}`,\n },\n} satisfies Record<string, SxProps<Theme>>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"table.js","names":["TableCell","TableSortLabel","Checkbox","CellHeaderProps","CellHeader","t0","$","_c","column","sortState","onSort","isSelectAll","isAllSelected","isIndeterminate","onSelectAll","t1","Symbol","for","t2","isSorted","columnId","id","sortDirection","direction","undefined","sortable","width","t3","t4","label","t5","align","ReactNode","getCellValue","cellValue","T","undefined","Array","isArray","formatted","map","item","String","join","JSON","stringify","compareValues","a","b","direction","comparison","localeCompare","strA","strB","sortData","Record","data","columnId","sort","paginateData","page","rowsPerPage","start","end","slice","TableCell","MuiTableCell","Link","Typography","ReactMarkdown","Components","TableColumn","TableRow","getCellValue","ReactNode","CellProps","column","row","value","DEFAULT_P","t0","$","_c","children","t1","CELL_MARKDOWN_COMPONENTS","h1","h2","h3","p","a","href","isExternal","startsWith","undefined","img","ul","ol","li","Cell","formatter","align","t2","t3","TableRow","MuiTableRow","TableCell","Checkbox","RowProps","Cell","Row","t0","$","_c","row","columns","isSelected","t1","selectable","t2","onClick","onSelect","onMouseEnter","onMouseLeave","undefined","t3","handleClick","t4","event","stopPropagation","handleCheckboxClick","t5","handleMouseEnter","t6","handleMouseLeave","t7","t8","t9","cursor","t10","id","t11","t12","column","map","Box","IconButton","FirstPage","FirstPageIcon","KeyboardArrowLeft","KeyboardArrowRight","LastPage","LastPageIcon","PaginationActionsProps","PaginationActions","t0","$","_c","count","page","rowsPerPage","onPageChange","lastPage","Math","max","ceil","t1","event","handleFirstPage","t2","event_0","handlePreviousPage","t3","event_1","handleNextPage","t4","event_2","handleLastPage","t5","Symbol","for","flexShrink","ml","t6","t7","t8","t9","t10","t11","t12","t13","t14","t15","t16","t17","t18","TablePagination","MuiTablePagination","PaginationProps","PaginationActions","Pagination","t0","$","_c","page","rowsPerPage","total","rowsPerPageOptions","t1","onPageChange","onRowsPerPageChange","t2","undefined","t3","_event","newPage","handlePageChange","t4","event","parseInt","target","value","handleRowsPerPageChange","t5","Table","MuiTable","TableBody","TableCell","TableHead","TableContainer","MuiTableContainer","Paper","TableProps","MuiTableProps","Ref","CellHeader","Row","Pagination","PaginationActions","useWidgetRef","TableUIProps","TableComponentProps","ref","HTMLTableElement","t0","$","_c","children","props","t1","stickyHeader","undefined","t2","Head","Body","Cell","Container","id","downloadToCSV","downloadToPNG","ConfigProps","TableDownloadConfig","TableWidgetConfig","TableColumn","Mode","SortDirection","DEFAULT_MODE","DEFAULT_PAGE","DEFAULT_ROWS_PER_PAGE","DEFAULT_ROWS_PER_PAGE_OPTIONS","DEFAULT_COLUMN_ID","DEFAULT_DIRECTION","tableDownloadConfig","refUI","modifier","data","length","firstRow","headers","Object","keys","filter","key","rows","map","row","header","value","undefined","JSON","stringify","tableConfig","columns","selectable","mode","useCallback","useMemo","TableRow","TableWidgetState","paginateData","widgetStoreActions","useWidgetSelector","DEFAULT_PAGE","DEFAULT_ROWS_PER_PAGE","DEFAULT_ROWS_PER_PAGE_OPTIONS","UsePaginationResult","paginationEnabled","page","rowsPerPage","total","rowsPerPageOptions","paginatedData","T","setPage","setRowsPerPage","goToFirstPage","goToLastPage","goToNextPage","goToPreviousPage","usePagination","widgetId","data","$","_c","t0","length","w","widget","pagination","mode","maxPage","Math","max","ceil","t1","newPage","widget_0","getWidget","currentTotal","currentRowsPerPage","currentMaxPage","boundedPage","min","setWidget","t2","newRowsPerPage","widget_1","t3","t4","t5","t6","t7","bb0","t8","useCallback","useMemo","TableRow","SortDirection","SortState","TableWidgetState","sortData","widgetStoreActions","useWidgetSelector","DEFAULT_COLUMN_ID","DEFAULT_DIRECTION","UseSortResult","sortEnabled","columnId","direction","sortedData","T","toggleSort","setSort","clearSort","useSort","widgetId","data","$","_c","mode","_temp","t0","toggleColumnId","widget_0","getWidget","currentColumnId","widget","sort","currentDirection","newDirection","setWidget","t1","newColumnId","newDirection_0","t2","widget_1","t3","bb0","t4","w","useCallback","useMemo","TableRow","TableWidgetState","widgetStoreActions","useWidgetSelector","UseSelectionOptions","onSelectionChange","selectedIds","UseSelectionResult","isSelected","id","isAllSelected","rows","isIndeterminate","toggleRow","toggleAll","selectRows","ids","deselectRows","clearSelection","useSelection","widgetId","options","$","_c","t0","selected","_temp","t1","t2","includes","t3","length","every","row","t4","rows_0","selectedCount","filter","row_0","t5","id_0","widget","getWidget","currentSelected","newSelected","s","setWidget","t6","rows_1","widget_0","currentSelected_0","rowIds","map","_temp2","allSelected","id_1","newSelected_0","id_2","Set","t7","widget_1","currentSelected_1","newSelected_1","t8","ids_0","widget_2","currentSelected_2","newSelected_2","id_3","t9","newSelected_3","t10","row_1","w","Box","Skeleton","Table","TableBody","TableCell","TableHead","TableRow","TableSkeletonProps","columns","rows","TableSkeleton","t0","$","_c","t1","t2","undefined","t3","Array","from","length","map","_temp","t4","t5","__0","rowIndex","_temp2","t6","__1","colIndex","_","index","TableRow","TableWidgetData","sanitizeTableRow","row","sanitized","id","key","value","Object","entries","Array","isArray","JSON","stringify","undefined","sanitizeTableData","data","map","SxProps","Theme","styles","container","width","overflow","table","minWidth","headerCell","fontWeight","backgroundColor","theme","palette","background","paper","row","border","rowHover","action","hover","rowSelected","selected","pagination","borderTop","divider","Record"],"sources":["../../src/widgets/table/components/cell-header.tsx","../../src/widgets/table/helpers.ts","../../src/widgets/table/components/cell.tsx","../../src/widgets/table/components/row.tsx","../../src/widgets/table/components/pagination-actions.tsx","../../src/widgets/table/components/pagination.tsx","../../src/widgets/table/table-ui.tsx","../../src/widgets/table/config.ts","../../src/widgets/table/hooks/use-pagination.ts","../../src/widgets/table/hooks/use-sort.ts","../../src/widgets/table/hooks/use-selection.ts","../../src/widgets/table/skeleton.tsx","../../src/widgets/table/serializer.ts","../../src/widgets/table/style.ts"],"sourcesContent":["import { TableCell, TableSortLabel, Checkbox } from '@mui/material'\nimport type { CellHeaderProps } from '../types'\n\n/**\n * Table cell header component with optional sorting and select-all checkbox\n */\nexport function CellHeader({\n column,\n sortState,\n onSort,\n isSelectAll,\n isAllSelected,\n isIndeterminate,\n onSelectAll,\n}: CellHeaderProps) {\n // Render select-all checkbox\n if (isSelectAll) {\n return (\n <TableCell padding='checkbox'>\n <Checkbox\n checked={isAllSelected}\n indeterminate={isIndeterminate}\n onChange={onSelectAll}\n inputProps={{ 'aria-label': 'select all rows' }}\n />\n </TableCell>\n )\n }\n\n const isSorted = sortState?.columnId === column.id\n const sortDirection = isSorted ? sortState.direction : undefined\n\n // Render sortable column header\n if (column.sortable && onSort) {\n return (\n <TableCell\n align={column.align}\n style={{ width: column.width }}\n sortDirection={sortDirection}\n >\n <TableSortLabel\n active={isSorted}\n direction={sortDirection ?? 'asc'}\n onClick={() => onSort(column.id)}\n >\n {column.label}\n </TableSortLabel>\n </TableCell>\n )\n }\n\n // Render non-sortable column header\n return (\n <TableCell align={column.align} style={{ width: column.width }}>\n {column.label}\n </TableCell>\n )\n}\n","import type { ReactNode } from 'react'\n\n/**\n * Get formatted cell value for display\n * Handles primitives, arrays, objects, and custom formatters\n *\n * @param cellValue - Raw cell value\n * @param formatter - Optional formatter function\n * @returns Formatted value for display\n */\nexport function getCellValue<T>(cellValue: T): ReactNode {\n // Handle null/undefined\n if (cellValue === null || cellValue === undefined) {\n return ''\n }\n\n // Handle arrays - format as [item1, item2, ...]\n if (Array.isArray(cellValue)) {\n const formatted = cellValue\n .map((item) => (typeof item === 'string' ? `\"${item}\"` : String(item)))\n .join(', ')\n return `[${formatted}]`\n }\n\n // Handle objects - stringify to JSON\n if (typeof cellValue === 'object') {\n return JSON.stringify(cellValue)\n }\n\n // Return primitives as-is (string, number, boolean)\n return cellValue as ReactNode\n}\n\n/**\n * Compare two values for sorting\n * Handles strings, numbers, and other types\n *\n * @param a - First value\n * @param b - Second value\n * @param direction - Sort direction\n * @returns Comparison result (-1, 0, 1)\n */\nexport function compareValues(\n a: unknown,\n b: unknown,\n direction: 'asc' | 'desc',\n): number {\n // Handle null/undefined - always sort to end\n if (a === null || a === undefined) return 1\n if (b === null || b === undefined) return -1\n\n let comparison = 0\n\n if (typeof a === 'string' && typeof b === 'string') {\n comparison = a.localeCompare(b)\n } else if (typeof a === 'number' && typeof b === 'number') {\n comparison = a - b\n } else if (typeof a === 'boolean' && typeof b === 'boolean') {\n comparison = a === b ? 0 : a ? 1 : -1\n } else if (typeof a === 'object' || typeof b === 'object') {\n // Compare objects/arrays as JSON strings\n const strA = JSON.stringify(a)\n const strB = JSON.stringify(b)\n comparison = strA.localeCompare(strB)\n } else {\n // Fallback for other primitives (bigint, symbol, etc.)\n comparison = 0\n }\n\n return direction === 'asc' ? comparison : -comparison\n}\n\n/**\n * Sort data array by column\n *\n * @param data - Data array to sort\n * @param columnId - Column ID to sort by\n * @param direction - Sort direction\n * @returns Sorted data array (new array, does not mutate original)\n */\nexport function sortData<T extends Record<string, unknown>>(\n data: T[],\n columnId: string,\n direction: 'asc' | 'desc',\n): T[] {\n return [...data].sort((a, b) =>\n compareValues(a[columnId], b[columnId], direction),\n )\n}\n\n/**\n * Paginate data array\n *\n * @param data - Data array to paginate\n * @param page - Current page (0-indexed)\n * @param rowsPerPage - Number of rows per page\n * @returns Paginated data slice\n */\nexport function paginateData<T>(\n data: T[],\n page: number,\n rowsPerPage: number,\n): T[] {\n const start = page * rowsPerPage\n const end = start + rowsPerPage\n return data.slice(start, end)\n}\n","import { TableCell as MuiTableCell, Link, Typography } from '@mui/material'\nimport ReactMarkdown, { type Components } from 'react-markdown'\nimport type { TableColumn, TableRow } from '../types'\nimport { getCellValue } from '../helpers'\nimport type { ReactNode } from 'react'\n\n/**\n * Props for Cell component\n */\nexport interface CellProps {\n /** Column definition */\n column: TableColumn\n /** Full table row for context */\n row: TableRow\n /** Cell value */\n value: unknown\n}\n\nconst DEFAULT_P = ({ children }: { children?: ReactNode }) => (\n <Typography component='span' variant='body2' color='inherit'>\n {children}\n </Typography>\n)\n\n/**\n * Markdown components for cell content\n * Uses compact styling suitable for table cells (reusing Note widget pattern)\n */\nconst CELL_MARKDOWN_COMPONENTS: Components = {\n h1: DEFAULT_P,\n h2: DEFAULT_P,\n h3: DEFAULT_P,\n p: DEFAULT_P,\n a: ({ children, href }) => {\n const isExternal = href?.startsWith('http')\n return (\n <Link\n href={href}\n target={isExternal ? '_blank' : undefined}\n rel={isExternal ? 'noopener noreferrer' : undefined}\n color='text.primary'\n underline='always'\n >\n {children}\n </Link>\n )\n },\n img: () => null,\n ul: DEFAULT_P,\n ol: DEFAULT_P,\n li: DEFAULT_P,\n}\n\n/**\n * Table cell component with automatic markdown support for string values\n * Markdown is rendered when the raw value is a string and no formatter is defined.\n * If a formatter is used, its output is rendered directly without markdown parsing.\n */\nexport function Cell({ column, row, value }: CellProps) {\n // If formatter is defined, use it directly without markdown\n if (column.formatter) {\n return (\n <MuiTableCell align={column.align}>\n {column.formatter(value, row)}\n </MuiTableCell>\n )\n }\n\n // For string values without formatter, render as markdown\n if (typeof value === 'string') {\n return (\n <MuiTableCell align={column.align}>\n <ReactMarkdown components={CELL_MARKDOWN_COMPONENTS}>\n {value}\n </ReactMarkdown>\n </MuiTableCell>\n )\n }\n\n // For non-string values, render directly\n return <MuiTableCell align={column.align}>{getCellValue(value)}</MuiTableCell>\n}\n","import { TableRow as MuiTableRow, TableCell, Checkbox } from '@mui/material'\nimport type { RowProps } from '../types'\nimport { Cell } from './cell'\n\n/**\n * Table row component with selection and hover support\n */\nexport function Row({\n row,\n columns,\n isSelected = false,\n selectable = false,\n onClick,\n onSelect,\n onMouseEnter,\n onMouseLeave,\n}: RowProps) {\n const handleClick = () => {\n onClick?.(row)\n }\n\n const handleCheckboxClick = (event: React.MouseEvent) => {\n event.stopPropagation()\n onSelect?.(row)\n }\n\n const handleMouseEnter = () => {\n onMouseEnter?.(row)\n }\n\n const handleMouseLeave = () => {\n onMouseLeave?.()\n }\n\n return (\n <MuiTableRow\n hover={!!onMouseEnter || !!onMouseLeave || !!onClick}\n selected={isSelected}\n onClick={handleClick}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n sx={{\n cursor: onClick ? 'pointer' : 'default',\n }}\n >\n {selectable && (\n <TableCell padding='checkbox'>\n <Checkbox\n checked={isSelected}\n onClick={handleCheckboxClick}\n inputProps={{ 'aria-label': `select row ${row.id}` }}\n />\n </TableCell>\n )}\n {columns.map((column) => (\n <Cell\n key={column.id}\n row={row}\n column={column}\n value={row[column.id]}\n />\n ))}\n </MuiTableRow>\n )\n}\n","import { Box, IconButton } from '@mui/material'\nimport { FirstPage as FirstPageIcon } from '@mui/icons-material'\nimport { KeyboardArrowLeft } from '@mui/icons-material'\nimport { KeyboardArrowRight } from '@mui/icons-material'\nimport { LastPage as LastPageIcon } from '@mui/icons-material'\nimport type { PaginationActionsProps } from '../types'\n\n/**\n * Custom pagination actions with first/prev/next/last buttons\n */\nexport function PaginationActions({\n count,\n page,\n rowsPerPage,\n onPageChange,\n}: PaginationActionsProps) {\n const lastPage = Math.max(0, Math.ceil(count / rowsPerPage) - 1)\n\n const handleFirstPage = (event: React.MouseEvent<HTMLButtonElement>) => {\n onPageChange(event, 0)\n }\n\n const handlePreviousPage = (event: React.MouseEvent<HTMLButtonElement>) => {\n onPageChange(event, page - 1)\n }\n\n const handleNextPage = (event: React.MouseEvent<HTMLButtonElement>) => {\n onPageChange(event, page + 1)\n }\n\n const handleLastPage = (event: React.MouseEvent<HTMLButtonElement>) => {\n onPageChange(event, lastPage)\n }\n\n return (\n <Box sx={{ flexShrink: 0, ml: 2.5 }}>\n <IconButton\n onClick={handleFirstPage}\n disabled={page === 0}\n aria-label='first page'\n >\n <FirstPageIcon />\n </IconButton>\n <IconButton\n onClick={handlePreviousPage}\n disabled={page === 0}\n aria-label='previous page'\n >\n <KeyboardArrowLeft />\n </IconButton>\n <IconButton\n onClick={handleNextPage}\n disabled={page >= lastPage}\n aria-label='next page'\n >\n <KeyboardArrowRight />\n </IconButton>\n <IconButton\n onClick={handleLastPage}\n disabled={page >= lastPage}\n aria-label='last page'\n >\n <LastPageIcon />\n </IconButton>\n </Box>\n )\n}\n","import { TablePagination as MuiTablePagination } from '@mui/material'\nimport type { PaginationProps } from '../types'\nimport { PaginationActions } from './pagination-actions'\n\n/**\n * Table pagination component\n */\nexport function Pagination({\n page,\n rowsPerPage,\n total,\n rowsPerPageOptions = [5, 10, 25, 50],\n onPageChange,\n onRowsPerPageChange,\n}: PaginationProps) {\n const handlePageChange = (\n _event: React.MouseEvent<HTMLButtonElement> | null,\n newPage: number,\n ) => {\n onPageChange(newPage)\n }\n\n const handleRowsPerPageChange = (\n event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,\n ) => {\n onRowsPerPageChange(parseInt(event.target.value, 10))\n }\n\n return (\n <MuiTablePagination\n component='div'\n count={total}\n page={page}\n rowsPerPage={rowsPerPage}\n rowsPerPageOptions={rowsPerPageOptions}\n onPageChange={handlePageChange}\n onRowsPerPageChange={handleRowsPerPageChange}\n ActionsComponent={PaginationActions}\n />\n )\n}\n","import {\n Table as MuiTable,\n TableBody,\n TableCell,\n TableHead,\n TableContainer as MuiTableContainer,\n Paper,\n type TableProps as MuiTableProps,\n} from '@mui/material'\nimport type { Ref } from 'react'\nimport { CellHeader } from './components/cell-header'\nimport { Row } from './components/row'\nimport { Pagination } from './components/pagination'\nimport { PaginationActions } from './components/pagination-actions'\nimport { useWidgetRef } from '../../hooks'\nimport type { TableUIProps } from './types'\n\n/**\n * Props for the base Table component\n */\ninterface TableComponentProps extends MuiTableProps {\n /** Table element ref */\n ref?: Ref<HTMLTableElement>\n}\n\n/**\n * Base Table component with compound component pattern\n * Provides Table.Head, Table.Body, Table.Row, Table.Cell, Table.CellHeader, Table.Pagination\n */\nfunction Table({\n children,\n ref,\n stickyHeader = true,\n ...props\n}: TableComponentProps) {\n return (\n <MuiTable stickyHeader={stickyHeader} ref={ref} {...props}>\n {children}\n </MuiTable>\n )\n}\n\n// Attach sub-components as static properties\nTable.Head = TableHead\nTable.CellHeader = CellHeader\nTable.Body = TableBody\nTable.Row = Row\nTable.Cell = TableCell\nTable.Container = TableContainer\nTable.Paper = Paper\nTable.Pagination = Pagination\nTable.PaginationActions = PaginationActions\n\nexport { Table }\n\n/**\n * TableContainer widget component\n * Integrates with widget store and provides ref registration using custom hook\n */\nfunction TableContainer(props: TableUIProps) {\n const { ref } = useWidgetRef<HTMLDivElement>(props.id)\n\n return <MuiTableContainer ref={ref}>{props.children}</MuiTableContainer>\n}\n","import { downloadToCSV, downloadToPNG } from '../actions'\nimport type { ConfigProps } from '../loader/types'\nimport type {\n TableDownloadConfig,\n TableWidgetConfig,\n TableColumn,\n Mode,\n SortDirection,\n} from './types'\n\nconst DEFAULT_MODE: Mode = 'local'\nexport const DEFAULT_PAGE = 0\nexport const DEFAULT_ROWS_PER_PAGE = 10\nexport const DEFAULT_ROWS_PER_PAGE_OPTIONS = [5, 10, 25, 50]\n\nexport const DEFAULT_COLUMN_ID = null\nexport const DEFAULT_DIRECTION: SortDirection = 'asc'\n\n/**\n * Creates download configuration for table widgets, supporting PNG (screenshot) and CSV (data) exports. CSV output uses column keys as headers and filters out `id` fields.\n *\n * @param props - Configuration with `refUI` reference for PNG export.\n * @returns Array of download items for use with the Download action.\n */\nexport function tableDownloadConfig({\n refUI,\n}: ConfigProps): TableDownloadConfig {\n return [\n {\n ...downloadToPNG,\n modifier: () => downloadToPNG.modifier(refUI),\n },\n {\n ...downloadToCSV,\n modifier: async (data) => {\n if (!data?.length) {\n return downloadToCSV.modifier([])\n }\n\n // Convert table data to CSV format\n // First row contains headers (column keys)\n const firstRow = data[0]\n if (!firstRow) {\n return downloadToCSV.modifier([])\n }\n\n const headers = Object.keys(firstRow).filter((key) => key !== 'id')\n const rows = data.map((row) =>\n headers.map((header) => {\n const value = row[header]\n if (value === null || value === undefined) return ''\n if (typeof value === 'object') return JSON.stringify(value)\n return value\n }),\n )\n\n return downloadToCSV.modifier([headers, ...rows])\n },\n },\n ]\n}\n\n/**\n * Returns the default configuration for table widgets with pagination and sorting, including column definitions and local data mode.\n *\n * @param columns - Array of column definitions for the table.\n * @returns Default table widget config.\n */\nexport function tableConfig(columns: TableColumn[] = []): TableWidgetConfig {\n return {\n columns,\n selectable: false,\n mode: DEFAULT_MODE,\n }\n}\n","import { useCallback, useMemo } from 'react'\nimport type { TableRow, TableWidgetState } from '../types'\nimport { paginateData } from '../helpers'\nimport { widgetStoreActions } from '../../stores/widget-store'\nimport { useWidgetSelector } from '../../stores/use-widget-selector'\nimport {\n DEFAULT_PAGE,\n DEFAULT_ROWS_PER_PAGE,\n DEFAULT_ROWS_PER_PAGE_OPTIONS,\n} from '../config'\n\nexport interface UsePaginationResult<T> {\n /** Whether pagination is enabled */\n paginationEnabled: boolean\n /** Current page (0-indexed) */\n page: number\n /** Rows per page */\n rowsPerPage: number\n /** Total row count */\n total: number\n /** Available rows per page options */\n rowsPerPageOptions: number[]\n /** Paginated data (for local mode) */\n paginatedData: T[]\n /** Set current page */\n setPage: (page: number) => void\n /** Set rows per page */\n setRowsPerPage: (rowsPerPage: number) => void\n /** Go to first page */\n goToFirstPage: () => void\n /** Go to last page */\n goToLastPage: () => void\n /** Go to next page */\n goToNextPage: () => void\n /** Go to previous page */\n goToPreviousPage: () => void\n}\n\n/**\n * Hook for managing table pagination with support for both local (client-side) and remote (server-side) modes.\n * State is persisted in the widget store for the given widget ID.\n *\n * @param widgetId - The widget ID to persist pagination state under.\n * @param data - The full data array (used for local pagination and total count fallback).\n * @returns Pagination state and navigation helpers.\n *\n * @example\n * ```tsx\n * const { page, setPage, paginatedData, totalPages } = usePagination(widgetId, data)\n * ```\n */\nexport function usePagination<T extends TableRow>(\n widgetId: string,\n data: T[],\n): UsePaginationResult<T> {\n // Get store state\n const {\n paginationEnabled,\n page,\n rowsPerPage,\n rowsPerPageOptions,\n total,\n mode,\n } = useWidgetSelector(widgetId, (w) => {\n const widget = w as TableWidgetState | undefined\n return {\n paginationEnabled: !!widget?.pagination,\n page: widget?.pagination?.page ?? DEFAULT_PAGE,\n rowsPerPage: widget?.pagination?.rowsPerPage ?? DEFAULT_ROWS_PER_PAGE,\n rowsPerPageOptions:\n widget?.pagination?.rowsPerPageOptions ?? DEFAULT_ROWS_PER_PAGE_OPTIONS,\n total: widget?.pagination?.total ?? data.length,\n mode: widget?.mode,\n }\n })\n\n // Calculate max page\n const maxPage = Math.max(0, Math.ceil(total / (rowsPerPage ?? 1)) - 1)\n\n // Set page with bounds checking\n const setPage = useCallback(\n (newPage: number) => {\n // Read current state directly from store to avoid stale closures\n const widget = widgetStoreActions.getWidget<TableWidgetState>(widgetId)\n const currentTotal = widget?.pagination?.total ?? data.length\n const currentRowsPerPage =\n widget?.pagination?.rowsPerPage ?? DEFAULT_ROWS_PER_PAGE\n const currentMaxPage = Math.max(\n 0,\n Math.ceil(currentTotal / currentRowsPerPage) - 1,\n )\n const boundedPage = Math.max(0, Math.min(newPage, currentMaxPage))\n\n widgetStoreActions.setWidget<TableWidgetState>(widgetId, {\n pagination: {\n ...widget?.pagination,\n page: boundedPage,\n },\n })\n },\n [data.length, widgetId],\n )\n\n // Set rows per page and reset to first page\n const setRowsPerPage = useCallback(\n (newRowsPerPage: number) => {\n const widget = widgetStoreActions.getWidget<TableWidgetState>(widgetId)\n widgetStoreActions.setWidget<TableWidgetState>(widgetId, {\n pagination: {\n ...widget?.pagination,\n rowsPerPage: newRowsPerPage,\n page: 0, // Reset to first page when changing rows per page\n },\n })\n },\n [widgetId],\n )\n\n // Navigation helpers\n const goToFirstPage = useCallback(() => setPage(0), [setPage])\n const goToLastPage = useCallback(() => setPage(maxPage), [setPage, maxPage])\n const goToNextPage = useCallback(() => setPage(page + 1), [setPage, page])\n const goToPreviousPage = useCallback(() => setPage(page - 1), [setPage, page])\n\n // Paginated data for local mode\n const paginatedData = useMemo(() => {\n if (mode === 'remote' || !paginationEnabled) {\n // For remote mode, data is already paginated from server\n return data\n }\n return paginateData(data, page, rowsPerPage)\n }, [data, mode, page, paginationEnabled, rowsPerPage])\n\n return {\n paginationEnabled,\n page,\n rowsPerPage,\n rowsPerPageOptions,\n total,\n paginatedData,\n setPage,\n setRowsPerPage,\n goToFirstPage,\n goToLastPage,\n goToNextPage,\n goToPreviousPage,\n }\n}\n","import { useCallback, useMemo } from 'react'\nimport type {\n TableRow,\n SortDirection,\n SortState,\n TableWidgetState,\n} from '../types'\nimport { sortData } from '../helpers'\nimport { widgetStoreActions } from '../../stores/widget-store'\nimport { useWidgetSelector } from '../../stores/use-widget-selector'\nimport { DEFAULT_COLUMN_ID, DEFAULT_DIRECTION } from '../config'\n\nexport interface UseSortResult<T> extends SortState {\n /** Whether sorting is enabled */\n sortEnabled: boolean\n /** Current sort state */\n columnId: string | null\n direction: SortDirection\n /** Sorted data (for local mode) */\n sortedData: T[]\n /** Toggle sort on a column */\n toggleSort: (columnId: string) => void\n /** Set sort state directly */\n setSort: (columnId: string | null, direction: SortDirection) => void\n /** Clear sort */\n clearSort: () => void\n}\n\n/**\n * Hook for managing table sorting with support for both local (client-side) and remote (server-side) modes.\n * State is persisted in the widget store for the given widget ID.\n *\n * @param widgetId - The widget ID to persist sort state under.\n * @param data - The data array to sort (for local mode).\n * @returns Sort state, sorted data, and sort control functions.\n *\n * @example\n * ```tsx\n * const { sortedData, sortField, sortDirection, handleSort } = useSort(widgetId, data)\n * ```\n */\nexport function useSort<T extends TableRow>(\n widgetId: string,\n data: T[],\n): UseSortResult<T> {\n // Get store state\n const { sortEnabled, columnId, direction, mode } = useWidgetSelector(\n widgetId,\n (w) => {\n const widget = w as TableWidgetState | undefined\n return {\n sortEnabled: !!widget?.sort,\n columnId: widget?.sort?.columnId ?? DEFAULT_COLUMN_ID,\n direction: widget?.sort?.direction ?? DEFAULT_DIRECTION,\n mode: widget?.mode,\n }\n },\n )\n\n // Toggle sort on a column\n const toggleSort = useCallback(\n (toggleColumnId: string) => {\n // Read current state directly from store to avoid stale closures\n const widget = widgetStoreActions.getWidget<TableWidgetState>(widgetId)\n const currentColumnId = widget?.sort?.columnId ?? DEFAULT_COLUMN_ID\n const currentDirection = widget?.sort?.direction ?? DEFAULT_DIRECTION\n\n let newDirection: SortDirection = 'asc'\n\n if (currentColumnId === toggleColumnId) {\n // Same column - toggle direction\n newDirection = currentDirection === 'asc' ? 'desc' : 'asc'\n }\n\n widgetStoreActions.setWidget<TableWidgetState>(widgetId, {\n sort: {\n columnId: toggleColumnId,\n direction: newDirection,\n },\n })\n },\n [widgetId],\n )\n\n // Set sort state directly\n const setSort = useCallback(\n (newColumnId: string | null, newDirection: SortDirection) => {\n widgetStoreActions.setWidget<TableWidgetState>(widgetId, {\n sort: {\n columnId: newColumnId,\n direction: newDirection,\n },\n })\n },\n [widgetId],\n )\n\n // Clear sort\n const clearSort = useCallback(() => {\n const widget = widgetStoreActions.getWidget<TableWidgetState>(widgetId)\n if (!widget?.sort) return\n\n widgetStoreActions.setWidget<TableWidgetState>(widgetId, {\n sort: {\n ...widget.sort,\n columnId: null,\n direction: 'asc',\n },\n })\n }, [widgetId])\n\n // Sorted data for local mode\n const sortedData = useMemo(() => {\n if (mode === 'remote' || !columnId || !sortEnabled) {\n // For remote mode, data is already sorted from server\n // If no sort column, return original data\n return data\n }\n return sortData(data, columnId, direction)\n }, [data, mode, columnId, direction, sortEnabled])\n\n return {\n sortEnabled,\n columnId,\n direction,\n sortedData,\n toggleSort,\n setSort,\n clearSort,\n }\n}\n","import { useCallback, useMemo } from 'react'\nimport type { TableRow, TableWidgetState } from '../types'\nimport { widgetStoreActions } from '../../stores/widget-store'\nimport { useWidgetSelector } from '../../stores/use-widget-selector'\n\nexport interface UseSelectionOptions {\n /** Callback when selection changes */\n onSelectionChange?: (selectedIds: (string | number)[]) => void\n}\n\nexport interface UseSelectionResult {\n /** Array of selected row IDs */\n selectedIds: (string | number)[]\n /** Check if a row is selected */\n isSelected: (id: string | number) => boolean\n /** Check if all provided rows are selected */\n isAllSelected: (rows: TableRow[]) => boolean\n /** Check if some but not all rows are selected (for indeterminate state) */\n isIndeterminate: (rows: TableRow[]) => boolean\n /** Toggle selection of a single row */\n toggleRow: (id: string | number) => void\n /** Toggle selection of all provided rows */\n toggleAll: (rows: TableRow[]) => void\n /** Select specific rows */\n selectRows: (ids: (string | number)[]) => void\n /** Deselect specific rows */\n deselectRows: (ids: (string | number)[]) => void\n /** Clear all selections */\n clearSelection: () => void\n}\n\n/**\n * Hook for managing table row selection with persistence across pagination.\n * Selection state is stored in the widget store for the given widget ID.\n *\n * @param widgetId - The widget ID to persist selection state under.\n * @param options - Optional configuration including an `onSelectionChange` callback.\n * @returns Selection state and control functions (toggle, select, deselect, clear).\n *\n * @example\n * ```tsx\n * const { selectedIds, isAllSelected, handleSelectRow, clearSelection } = useSelection(widgetId)\n * ```\n */\nexport function useSelection(\n widgetId: string,\n options?: UseSelectionOptions,\n): UseSelectionResult {\n const { onSelectionChange } = options ?? {}\n\n // Get store state\n const selected = useWidgetSelector(\n widgetId,\n (w) => (w as TableWidgetState | undefined)?.selected,\n )\n\n // Use store values with fallback to empty array\n const selectedIds = useMemo(() => selected ?? [], [selected])\n\n // Check if a row is selected\n const isSelected = useCallback(\n (id: string | number) => selectedIds.includes(id),\n [selectedIds],\n )\n\n // Check if all provided rows are selected\n const isAllSelected = useCallback(\n (rows: TableRow[]) => {\n if (rows.length === 0) return false\n return rows.every((row) => selectedIds.includes(row.id))\n },\n [selectedIds],\n )\n\n // Check if some but not all rows are selected\n const isIndeterminate = useCallback(\n (rows: TableRow[]) => {\n if (rows.length === 0) return false\n const selectedCount = rows.filter((row) =>\n selectedIds.includes(row.id),\n ).length\n return selectedCount > 0 && selectedCount < rows.length\n },\n [selectedIds],\n )\n\n // Toggle selection of a single row\n const toggleRow = useCallback(\n (id: string | number) => {\n const widget = widgetStoreActions.getWidget<TableWidgetState>(widgetId)\n const currentSelected = widget?.selected ?? []\n\n const newSelected = currentSelected.includes(id)\n ? currentSelected.filter((s) => s !== id)\n : [...currentSelected, id]\n\n widgetStoreActions.setWidget<TableWidgetState>(widgetId, {\n selected: newSelected,\n })\n\n if (onSelectionChange) {\n onSelectionChange(newSelected)\n }\n },\n [widgetId, onSelectionChange],\n )\n\n // Toggle selection of all provided rows\n const toggleAll = useCallback(\n (rows: TableRow[]) => {\n const widget = widgetStoreActions.getWidget<TableWidgetState>(widgetId)\n const currentSelected = widget?.selected ?? []\n\n const rowIds = rows.map((row) => row.id)\n const allSelected = rowIds.every((id) => currentSelected.includes(id))\n\n const newSelected = allSelected\n ? currentSelected.filter((id) => !rowIds.includes(id))\n : [...new Set([...currentSelected, ...rowIds])]\n\n widgetStoreActions.setWidget<TableWidgetState>(widgetId, {\n selected: newSelected,\n })\n\n if (onSelectionChange) {\n onSelectionChange(newSelected)\n }\n },\n [widgetId, onSelectionChange],\n )\n\n // Select specific rows\n const selectRows = useCallback(\n (ids: (string | number)[]) => {\n const widget = widgetStoreActions.getWidget<TableWidgetState>(widgetId)\n const currentSelected = widget?.selected ?? []\n\n const newSelected = [...new Set([...currentSelected, ...ids])]\n\n widgetStoreActions.setWidget<TableWidgetState>(widgetId, {\n selected: newSelected,\n })\n\n if (onSelectionChange) {\n onSelectionChange(newSelected)\n }\n },\n [widgetId, onSelectionChange],\n )\n\n // Deselect specific rows\n const deselectRows = useCallback(\n (ids: (string | number)[]) => {\n const widget = widgetStoreActions.getWidget<TableWidgetState>(widgetId)\n const currentSelected = widget?.selected ?? []\n\n const newSelected = currentSelected.filter((id) => !ids.includes(id))\n\n widgetStoreActions.setWidget<TableWidgetState>(widgetId, {\n selected: newSelected,\n })\n\n if (onSelectionChange) {\n onSelectionChange(newSelected)\n }\n },\n [widgetId, onSelectionChange],\n )\n\n // Clear all selections\n const clearSelection = useCallback(() => {\n const newSelected: (string | number)[] = []\n\n widgetStoreActions.setWidget<TableWidgetState>(widgetId, {\n selected: newSelected,\n })\n\n if (onSelectionChange) {\n onSelectionChange(newSelected)\n }\n }, [widgetId, onSelectionChange])\n\n return {\n selectedIds,\n isSelected,\n isAllSelected,\n isIndeterminate,\n toggleRow,\n toggleAll,\n selectRows,\n deselectRows,\n clearSelection,\n }\n}\n","import {\n Box,\n Skeleton,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableRow,\n} from '@mui/material'\n\nexport interface TableSkeletonProps {\n /** Number of columns to display */\n columns?: number\n /** Number of rows to display */\n rows?: number\n}\n\n/**\n * Table skeleton loader component\n */\nexport function TableSkeleton({ columns = 4, rows = 5 }: TableSkeletonProps) {\n return (\n <Box aria-label='Table skeleton'>\n <Table>\n <TableHead>\n <TableRow>\n {Array.from({ length: columns }).map((_, index) => (\n <TableCell key={index}>\n <Skeleton width='80%' height={24} />\n </TableCell>\n ))}\n </TableRow>\n </TableHead>\n <TableBody>\n {Array.from({ length: rows }).map((_, rowIndex) => (\n <TableRow key={rowIndex}>\n {Array.from({ length: columns }).map((_, colIndex) => (\n <TableCell key={colIndex}>\n <Skeleton width='70%' height={20} />\n </TableCell>\n ))}\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </Box>\n )\n}\n","import type { TableRow, TableWidgetData } from './types'\n\n/**\n * Sanitizes a table row by ensuring all values are serializable.\n * Converts ReactNode and function values to undefined.\n *\n * @param row - The table row to sanitize\n * @returns A sanitized table row\n */\nexport function sanitizeTableRow(row: TableRow): TableRow {\n const sanitized: TableRow = { id: row.id }\n\n for (const [key, value] of Object.entries(row)) {\n if (key === 'id') continue\n\n // Keep primitive values\n if (\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean' ||\n value === null\n ) {\n sanitized[key] = value\n }\n // Serialize arrays and plain objects\n else if (Array.isArray(value) || typeof value === 'object') {\n try {\n // Attempt to serialize - if it fails, the value contains non-serializable content\n JSON.stringify(value)\n sanitized[key] = value\n } catch {\n sanitized[key] = undefined\n }\n }\n // Skip functions and other non-serializable values\n else {\n sanitized[key] = undefined\n }\n }\n\n return sanitized\n}\n\n/**\n * Sanitizes table widget data by ensuring all rows are serializable.\n *\n * @param data - The table data to sanitize\n * @returns Sanitized table data\n */\nexport function sanitizeTableData(\n data: TableWidgetData | undefined,\n): TableWidgetData | undefined {\n return data?.map(sanitizeTableRow)\n}\n","import type { SxProps, Theme } from '@mui/material'\n\nexport const styles = {\n container: {\n width: '100%',\n overflow: 'auto',\n },\n table: {\n minWidth: 650,\n },\n headerCell: {\n fontWeight: 600,\n backgroundColor: (theme: Theme) => theme.palette.background.paper,\n },\n row: {\n '&:last-child td, &:last-child th': {\n border: 0,\n },\n },\n rowHover: {\n '&:hover': {\n backgroundColor: (theme: Theme) => theme.palette.action.hover,\n },\n },\n rowSelected: {\n backgroundColor: (theme: Theme) => theme.palette.action.selected,\n '&:hover': {\n backgroundColor: (theme: Theme) => theme.palette.action.selected,\n },\n },\n pagination: {\n borderTop: (theme: Theme) => `1px solid ${theme.palette.divider}`,\n },\n} satisfies Record<string, SxProps<Theme>>\n"],"mappings":"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"}
|
package/dist/widgets-v2/pie.js
CHANGED
|
@@ -88,15 +88,15 @@ function y(e, t, n, r, i, a) {
|
|
|
88
88
|
if (!a) return t;
|
|
89
89
|
let n = e.value?.name ?? e.name;
|
|
90
90
|
return n != null && a.has(n) ? t : h.color.modifyAlpha(t, .15);
|
|
91
|
-
}, g = t[0] ?? [],
|
|
92
|
-
for (let e of
|
|
93
|
-
let
|
|
91
|
+
}, g = s.label?.position, _ = g === void 0 || g === "center", v = t[0] ?? [], y, b = -Infinity;
|
|
92
|
+
for (let e of v) a && !a.has(e.name) || typeof e.value == "number" && e.value > b && (b = e.value, y = e.name);
|
|
93
|
+
let x = (e) => {
|
|
94
94
|
let { name: t } = e;
|
|
95
|
-
if (t == null || t !==
|
|
95
|
+
if (t == null || _ && t !== y) return "";
|
|
96
96
|
let n = e.encode?.value?.[0];
|
|
97
97
|
if (n === void 0) return "";
|
|
98
|
-
let r = Object.values(e.data ?? {}).at(n);
|
|
99
|
-
return `{c|${
|
|
98
|
+
let r = Object.values(e.data ?? {}).at(n), i = typeof r == "number" ? u ? u(r) : String(r) : typeof r == "string" ? r : "", a = String(d ? d(t ?? "") : t ?? "");
|
|
99
|
+
return `{c|${i}}${_ ? "\n\n" : "\n"}{b|${a}}`;
|
|
100
100
|
};
|
|
101
101
|
return {
|
|
102
102
|
...e,
|
|
@@ -117,7 +117,7 @@ function y(e, t, n, r, i, a) {
|
|
|
117
117
|
},
|
|
118
118
|
label: {
|
|
119
119
|
...c,
|
|
120
|
-
formatter:
|
|
120
|
+
formatter: x
|
|
121
121
|
},
|
|
122
122
|
itemStyle: {
|
|
123
123
|
...l,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pie.js","names":["Theme","EChartsOption","echarts","CallbackDataParams","buildGridConfig","buildLegendConfig","buildSeriesLabelConfig","createTooltipFormatter","createTooltipPositioner","niceNum","OptionFactory","OptionFactoryContext","mergeOptions","resolveThemeColor","WidgetSeries","PieEChartsOption","PieOptionFactoryInput","PieOptionsInput","PieWidgetData","DEFAULT_RADIUS","pieOptions","theme","formatter","labelFormatter","legend","hasLegend","left","type","itemGap","selectedMode","tooltip","trigger","backgroundColor","palette","grey","borderWidth","padding","parseInt","spacing","textStyle","color","common","white","fontSize","fontFamily","typography","caption","position","buildPieTooltipFormatter","Object","values","qualitative","bold","Record","series","colorBy","avoidLabelOverlap","selectedOffset","legendHoverLink","emphasis","disabled","itemStyle","borderColor","background","paper","label","show","rich","b","fontWeight","lineHeight","c","createPieOptionFactory","options","optionsOverride","radius","selection","selectionSet","undefined","length","Set","option","data","ctx","structural","Partial","seriesArr","Array","isArray","dataset","buildMultiSeriesBarFusion","buildSingleSeriesPieFusion","seriesTemplates","broadcastTemplate","baseTooltip","baseLegend","resolvePaletteColor","params","swatch","dataIndex","colorFn","base","datum","value","name","has","modifyAlpha","centerData","centerMaxName","centerMaxValue","Infinity","d","labelTextFormatter","encodeIndex","encode","at","formattedValue","String","formattedName","map","s","source","_","i","template","templateObj","templateLabel","templateItemStyle","const","datasetIndex","center","itemName","selected","fromEntries","baseGrid","grid","niceMinVal","niceMaxVal","computeNiceBounds","barColorFn","seriesIdx","seriesIndex","seriesSwatch","right","containLabel","overrideColor","barMaxWidth","focus","xAxis","min","max","axisLine","axisTick","splitLine","lineStyle","black","divider","axisLabel","overlineDelicate","margin","showMaxLabel","showMinLabel","yAxis","buildHorizontalBarTooltipFormatter","item","x","dimName","dimensionNames","row","raw","marker","seriesName","Number","isFinite","Box","Skeleton","SxProps","Theme","OUTER_SIZE","HOLE_SIZE","styles","root","display","flexDirection","alignItems","justifyContent","minHeight","py","gap","spacing","donut","position","ring","width","height","hole","zIndex","borderRadius","bgcolor","label","legend","legendItem","Record","PieSkeletonProps","count","PieSkeleton","t0","$","_c","t1","t2","Symbol","for","t3","t4","map","_temp","i","buildCsvDownloadItem","buildPngDownloadItem","DownloadItem","PieWidgetData","createPieDownloadConfig","args","filename","getData","seriesNames","getCaptureEl","HTMLElement","pngPixelRatio","pngBackgroundColor","items","push","pixelRatio","backgroundColor","getRows","data","rows","i","series","entries","seriesName","slice","name","value"],"sources":["../../src/widgets-v2/pie/options.ts","../../src/widgets-v2/pie/skeleton.tsx","../../src/widgets-v2/pie/download.ts"],"sourcesContent":["import type { Theme } from '@mui/material'\nimport type { EChartsOption } from 'echarts'\nimport * as echarts from 'echarts'\nimport type { CallbackDataParams } from 'echarts/types/dist/shared'\nimport {\n buildGridConfig,\n buildLegendConfig,\n buildSeriesLabelConfig,\n createTooltipFormatter,\n createTooltipPositioner,\n niceNum,\n} from '../../widgets/utils/chart-config'\nimport type { OptionFactory, OptionFactoryContext } from '../echart'\nimport { mergeOptions, resolveThemeColor } from '../utils'\nimport type { WidgetSeries } from '../types'\nimport type {\n PieEChartsOption,\n PieOptionFactoryInput,\n PieOptionsInput,\n PieWidgetData,\n} from './types'\n\nconst DEFAULT_RADIUS: readonly [string, string] = ['58%', '74%']\n\n/**\n * Builds the **structural** ECharts option for a pie / donut widget.\n * Mirrors v1's pie look-and-feel: themed legend (`buildLegendConfig`),\n * themed tooltip via `createTooltipPositioner` / `createTooltipFormatter`,\n * `qualitative.bold` color palette, slice borders against the paper\n * background, hover-emphasis disabled, and a centered rich-text label.\n *\n * Layered like Bar / Histogram:\n * - **Theme-aware bits** live here on a series template (slice border,\n * center-label rich style sizes, emphasis-disabled).\n * - **Reactive bits** (tooltip value formatter, center-label text,\n * selection-driven dim) are re-emitted by\n * {@link createPieOptionFactory} at fusion time so RelativeData's\n * percent override flows through.\n */\nexport function pieOptions({\n theme,\n formatter,\n labelFormatter,\n}: PieOptionsInput): PieEChartsOption {\n return {\n legend: {\n ...buildLegendConfig({ hasLegend: true, labelFormatter }),\n // Pie reads better with a centered legend (the donut is radially\n // symmetric — left-aligning the legend below it visually unbalances\n // the chart). Override `buildLegendConfig`'s `type: 'scroll'` with\n // `'plain'` so long category lists wrap to multiple rows instead\n // of clipping the last visible item against the chart container.\n // The wider `itemGap` gives chips breathing room in the typical\n // 3–6 category case.\n left: 'center',\n type: 'scroll',\n itemGap: 16,\n // The legend is presentational only here — the pie has its own\n // click-to-select affordance on the slices themselves, so legend\n // clicks toggling series visibility would be a second, redundant/\n // conflicting interaction model. Hover-highlight is disabled per\n // series via `legendHoverLink` (ECharts has no legend-level knob\n // for it).\n selectedMode: false,\n },\n tooltip: {\n // Pie uses item-trigger (no axis); the rest of the styling mirrors\n // bar/histogram so the dashboard reads consistently — dark\n // grey[900] bg, white caption-font text, padded, with the shared\n // overflow-aware positioner.\n trigger: 'item',\n backgroundColor: theme.palette.grey[900],\n borderWidth: 0,\n padding: [parseInt(theme.spacing(1)), parseInt(theme.spacing(1))],\n textStyle: {\n color: theme.palette.common.white,\n fontSize: 11,\n fontFamily: theme.typography.caption.fontFamily,\n },\n position: createTooltipPositioner(theme),\n formatter: buildPieTooltipFormatter(formatter, labelFormatter),\n },\n // V1 used `qualitative.bold` only (no `secondary.main` prefix) because\n // pie slices are categorical — each slice deserves a distinct palette\n // entry from the start, not a primary highlight.\n color: Object.values(\n (theme.palette as { qualitative?: { bold?: Record<string, string> } })\n .qualitative?.bold ?? {},\n ),\n // Pie template. The merger spreads this into each per-data series it\n // emits — borderColor / borderWidth / emphasis-disabled / label rich\n // sizes all survive through.\n series: [\n {\n type: 'pie',\n colorBy: 'data',\n avoidLabelOverlap: true,\n selectedOffset: 0,\n legendHoverLink: false,\n emphasis: { disabled: true },\n itemStyle: {\n borderColor: theme.palette.background.paper,\n borderWidth: 1,\n },\n label: {\n show: true,\n position: 'center',\n rich: {\n b: { fontSize: 16, fontWeight: 'normal', lineHeight: 20 },\n c: { fontSize: 28, fontWeight: 'bold', lineHeight: 27 },\n },\n },\n },\n ],\n }\n}\n\n/**\n * Returns the pie widget's {@link OptionFactory} — one closure that owns\n * BOTH phases of option construction:\n *\n * - **Structural phase** (`option == null`) — builds the theme-aware\n * structural option via {@link pieOptions}, optionally merging the\n * consumer-supplied `optionsOverride` on top. Called once by Provider\n * to seed `rawOptions` in the store.\n * - **Merge phase** (`option != null`) — fuses post-pipeline `state.data`\n * (`PieWidgetData`) into the option via the dataset API. Single-series\n * → donut (one dataset, `series[i].encode = { itemName: 'name', value: 'value' }`).\n * Multi-series → horizontal-bar fallback (mirrors v1 pie). Reactive\n * formatters from `ctx` drive the tooltip + center label at fusion\n * time so RelativeData's percent formatter flows through without a\n * structural rebuild.\n */\nexport function createPieOptionFactory(\n options: PieOptionFactoryInput,\n): OptionFactory {\n const { theme, formatter, labelFormatter, optionsOverride, series } = options\n const radius = options.radius ?? DEFAULT_RADIUS\n const selection = options.selection\n // An explicit `[]` (deselected down to zero via chart clicks) is treated\n // the same as no selection: the pie has no bar/histogram-style \"nothing\n // selected\" affordance, so dimming every slice would just look broken —\n // it renders fully active, same as the no-interaction state.\n const selectionSet =\n selection === undefined || selection === null || selection.length === 0\n ? null\n : new Set<string | number>(selection)\n return (option, data, ctx) => {\n if (option == null) {\n const structural = pieOptions({ theme, formatter, labelFormatter })\n return optionsOverride\n ? (mergeOptions(\n structural as unknown as Record<string, unknown>,\n optionsOverride as Partial<Record<string, unknown>>,\n ) as EChartsOption)\n : structural\n }\n\n const seriesArr = Array.isArray(data) ? (data as PieWidgetData) : []\n if (seriesArr.length === 0) {\n return { ...option, dataset: [], series: [] }\n }\n if (seriesArr.length > 1) {\n return buildMultiSeriesBarFusion(\n option,\n seriesArr,\n theme,\n series,\n ctx,\n selectionSet,\n )\n }\n return buildSingleSeriesPieFusion(\n option,\n seriesArr,\n radius,\n series,\n ctx,\n selectionSet,\n )\n }\n}\n\n/**\n * Single-series donut fusion. Spreads the structural pie series template\n * into per-data series with center/radius/encoding, wires the reactive\n * center-label / tooltip formatters and the per-data palette-aware\n * selection-dim callback.\n */\nfunction buildSingleSeriesPieFusion(\n option: EChartsOption,\n seriesArr: PieWidgetData,\n radius: readonly [string, string],\n series: readonly WidgetSeries[] | undefined,\n ctx: OptionFactoryContext | undefined,\n selectionSet: Set<string | number> | null,\n): EChartsOption {\n const seriesTemplates = Array.isArray(option.series) ? option.series : []\n const broadcastTemplate = seriesTemplates[0] ?? {}\n const baseTooltip =\n typeof option.tooltip === 'object' && !Array.isArray(option.tooltip)\n ? option.tooltip\n : {}\n const baseLegend =\n typeof option.legend === 'object' && !Array.isArray(option.legend)\n ? option.legend\n : {}\n const formatter = ctx?.formatter\n const labelFormatter = ctx?.labelFormatter\n\n // Pie wants `colorBy: 'data'` — each slice draws from the option's\n // `color` palette by data index. But installing an `itemStyle.color`\n // callback disables ECharts' automatic per-data cycling, and\n // `params.color` collapses to the series color (so every slice goes\n // the same color). We re-implement the per-data palette resolution\n // here so the multicolor look survives selection-driven dimming.\n const palette = Array.isArray(option.color)\n ? (option.color as readonly (string | undefined)[])\n : []\n const resolvePaletteColor = (params: CallbackDataParams): string => {\n const swatch =\n palette.length > 0\n ? palette[params.dataIndex % palette.length]\n : undefined\n return swatch ?? (params.color as string)\n }\n\n // Always emit `itemStyle.color` (passthrough when nothing is selected),\n // not conditionally — same anti-stale-callback rationale as bar /\n // histogram. The slice border + width come from the structural\n // template's `itemStyle` and survive via the spread below.\n //\n // `selectionSet` is the *included* set, same direct semantics as\n // bar/histogram/timeseries (no ADR-014 exclusion inversion). Dim a slice\n // when its name is NOT in the set. `selectionSet` is never a non-null\n // empty Set — the collapse above (`selection.length === 0 → null`) rules\n // that out — so there's no \"dim everything\" case here, unlike a widget\n // that gives `[]` its own \"selected down to nothing\" meaning.\n const colorFn = (params: CallbackDataParams): string => {\n const base = resolvePaletteColor(params)\n if (!selectionSet) return base\n const datum = params.value as { name?: string | number } | undefined\n const name = datum?.name ?? params.name\n return name != null && selectionSet.has(name)\n ? base\n : echarts.color.modifyAlpha(base, 0.15)\n }\n\n // Which slice renders the centre value+name: the greatest value among\n // the *included* slices (all of them when there's no active\n // selection), computed locally — no query round-trip. Only that one\n // slice's formatter call returns text; every other slice returns ''\n // so exactly one label ever renders at the shared centre anchor. Only\n // `typeof value === 'number'` participates — if every included slice's\n // value is non-numeric, `centerMaxName` stays `undefined` and no slice\n // matches it in `labelTextFormatter` below, so the chart renders with no\n // centre label at all (graceful no-op, not a crash).\n const centerData = seriesArr[0] ?? []\n let centerMaxName: string | number | undefined\n let centerMaxValue = -Infinity\n for (const d of centerData) {\n if (selectionSet && !selectionSet.has(d.name)) continue\n if (typeof d.value === 'number' && d.value > centerMaxValue) {\n centerMaxValue = d.value\n centerMaxName = d.name\n }\n }\n\n // Center label formatter — lives in the merger because it reads\n // reactive `formatter` / `labelFormatter` from ctx. The rich tags\n // `{c|…}` and `{b|…}` reference the rich styles baked into the\n // structural label template.\n const labelTextFormatter = (params: CallbackDataParams): string => {\n const { name } = params\n if (name == null || name !== centerMaxName) return ''\n const encodeIndex = params.encode?.value?.[0]\n if (encodeIndex === undefined) return ''\n const value = (Object.values(params.data ?? {}) as unknown[]).at(\n encodeIndex,\n )\n // `value` here is the resolved dataset cell — for pie data it's a\n // `string | number` primitive. Anything else is a misuse we won't\n // dress up with `String(...)` (would render \"[object Object]\").\n const formattedValue =\n typeof value === 'number'\n ? formatter\n ? formatter(value)\n : String(value)\n : typeof value === 'string'\n ? value\n : ''\n const formattedName = labelFormatter\n ? String(labelFormatter(name ?? ''))\n : String(name ?? '')\n return `{c|${formattedValue}}\\n\\n{b|${formattedName}}`\n }\n\n return {\n ...option,\n dataset: seriesArr.map((s) => ({ source: s as readonly object[] })),\n series: seriesArr.map((_, i) => {\n const template =\n (seriesTemplates[i] as object | undefined) ??\n (broadcastTemplate as object)\n const templateObj = typeof template === 'object' ? template : {}\n const templateLabel = (templateObj as { label?: object }).label ?? {}\n const templateItemStyle =\n (templateObj as { itemStyle?: object }).itemStyle ?? {}\n return {\n ...templateObj,\n type: 'pie' as const,\n legendHoverLink: false,\n datasetIndex: i,\n name: series?.[i]?.name ?? `Series ${i + 1}`,\n radius: [...radius],\n // Lift the donut up so the bottom-anchored legend has the\n // vertical real estate to wrap to multiple rows for long\n // category lists — at exactly `50%` the bottom slices crowd\n // the chips and `type: 'plain'` legends can't expand upward\n // without overlapping the donut.\n center: ['50%', '38%'] as [string, string],\n encode: { itemName: 'name', value: 'value' },\n label: {\n ...templateLabel,\n formatter: labelTextFormatter,\n },\n itemStyle: {\n ...templateItemStyle,\n color: colorFn,\n },\n }\n }),\n // Legend always shows for pie (mirrors v1) — slice names drive the\n // entries, so even a single donut benefits from a category list.\n //\n // Exclusion is conveyed purely via `colorFn`/`labelTextFormatter`\n // dimming above, never via the legend's `selected` map: for a pie\n // series, ECharts treats `legend.selected[name] = false` as \"remove\n // this data point,\" which recomputes every remaining slice's angle —\n // the excluded slice disappears instead of rendering dimmed. Forcing\n // every name to `true` on every render also overrides ECharts' own\n // internal toggle state from a native legend click (which flips a\n // name to `false` and hides it before our `legendselectchanged`\n // handler gets a chance to react), so a legend click never leaves a\n // slice structurally removed — only the color/label dimming reflects\n // exclusion, and it stays in sync with the slice itself since both\n // read `selectionSet` on the same render.\n legend: {\n ...baseLegend,\n show: true,\n selectedMode: false,\n selected: Object.fromEntries(\n (seriesArr[0] ?? []).map((d) => [String(d.name), true]),\n ),\n },\n tooltip: {\n ...baseTooltip,\n formatter: buildPieTooltipFormatter(formatter, labelFormatter),\n },\n }\n}\n\n/**\n * Multi-series horizontal-bar fusion. Mirrors v1 pie's \"pie data with\n * >1 series collapses into a horizontal bar chart\" behavior — side-by-\n * side donuts don't read well when you're comparing the same categories\n * across cohorts, so swap to a value-on-x / category-on-y bar layout.\n *\n * Pie data shape is identical to bar's (`{ name, value }[][]`), so the\n * same dataset feeds either layout without transformation.\n */\nfunction buildMultiSeriesBarFusion(\n option: EChartsOption,\n seriesArr: PieWidgetData,\n theme: Theme,\n series: readonly WidgetSeries[] | undefined,\n ctx: OptionFactoryContext | undefined,\n selectionSet: Set<string | number> | null,\n): EChartsOption {\n const baseTooltip =\n typeof option.tooltip === 'object' && !Array.isArray(option.tooltip)\n ? option.tooltip\n : {}\n const baseLegend =\n typeof option.legend === 'object' && !Array.isArray(option.legend)\n ? option.legend\n : {}\n const baseGrid =\n typeof option.grid === 'object' && !Array.isArray(option.grid)\n ? option.grid\n : {}\n const formatter = ctx?.formatter\n const labelFormatter = ctx?.labelFormatter\n\n const { niceMinVal, niceMaxVal } = computeNiceBounds(seriesArr)\n\n // Per-series palette — multi-series bars take one color per series\n // (not per-data, unlike donut slices). Same anti-stale-callback rule:\n // always emit the callback so a transition to/from a selection\n // replaces the previous closure cleanly.\n const palette = Array.isArray(option.color)\n ? (option.color as readonly (string | undefined)[])\n : []\n const barColorFn = (params: CallbackDataParams): string => {\n const seriesIdx = params.seriesIndex ?? 0\n const seriesSwatch =\n palette.length > 0 ? palette[seriesIdx % palette.length] : undefined\n const base = (seriesSwatch ?? params.color) as string\n if (!selectionSet) return base\n const datum = params.value as { name?: string | number } | undefined\n const name = datum?.name ?? params.name\n return name != null && selectionSet.has(name)\n ? base\n : echarts.color.modifyAlpha(base, 0.15)\n }\n\n return {\n ...option,\n dataset: seriesArr.map((s) => ({ source: s as readonly object[] })),\n grid: {\n ...baseGrid,\n ...buildGridConfig(true, theme),\n right: parseInt(theme.spacing(4)),\n containLabel: true,\n },\n // Drop pie-specific structural keys that shouldn't render in the\n // bar fallback. ECharts ignores undefined keys, so this is a clean\n // override.\n series: seriesArr.map((_, i) => {\n const overrideColor = resolveThemeColor(theme, series?.[i]?.color)\n return {\n datasetIndex: i,\n type: 'bar' as const,\n name: series?.[i]?.name ?? `Series ${i + 1}`,\n barMaxWidth: 100,\n legendHoverLink: false,\n emphasis: { focus: 'series' },\n ...buildSeriesLabelConfig(formatter, 'x'),\n itemStyle: { color: barColorFn },\n ...(overrideColor ? { color: overrideColor } : {}),\n }\n }),\n xAxis: {\n type: 'value',\n // Closures over the pre-computed nice bounds — ECharts calls them\n // once per render to resolve the axis extents.\n min: () => niceMinVal,\n max: () => niceMaxVal,\n axisLine: { show: false },\n axisTick: { show: false },\n splitLine: {\n show: true,\n lineStyle: { color: theme.palette.black?.[4] ?? theme.palette.divider },\n },\n // Value labels render BELOW the axis line (default placement),\n // NOT inside the plot. Bar/histogram use `inside: true` +\n // `verticalAlign: 'bottom'` for their *vertical* y-axis where the\n // axis is the left wall — labels inside read like grid annotations.\n // A horizontal bar chart's value axis is the x-axis, and `inside`\n // there pushes the max label *behind* the bar (it visually\n // disappears once a bar reaches the right edge). Use the default\n // below-the-axis placement so the rounded extents stay readable.\n axisLabel: {\n fontSize: theme.typography.overlineDelicate?.fontSize,\n fontFamily: theme.typography.overlineDelicate?.fontFamily,\n margin: parseInt(theme.spacing(1)),\n showMaxLabel: true,\n showMinLabel: true,\n formatter: (value: number) => {\n if (value !== niceMaxVal && value !== niceMinVal) return ''\n if (value === 0) return ''\n return formatter ? formatter(value) : String(value)\n },\n },\n },\n yAxis: {\n type: 'category',\n axisLine: { show: false },\n axisTick: { show: false },\n axisLabel: {\n padding: [parseInt(theme.spacing(0.5)), 0, 0, 0],\n ...(labelFormatter && {\n formatter: (value: string | number) => String(labelFormatter(value)),\n }),\n },\n },\n // Mirrors the donut branch's `selected` reset above — `selectedMode:\n // false` blocks the native legend click that would otherwise undo an\n // ECharts-internal toggle, so without forcing every entry back to\n // `true` here a prior native toggle (from before `selectedMode` took\n // effect, or a stale `keepAlive` instance) would stay hidden forever\n // with no way to restore it.\n legend: {\n ...baseLegend,\n show: true,\n selectedMode: false,\n selected: Object.fromEntries(\n seriesArr.map((_, i) => [series?.[i]?.name ?? `Series ${i + 1}`, true]),\n ),\n },\n tooltip: {\n ...baseTooltip,\n trigger: 'axis',\n formatter: buildHorizontalBarTooltipFormatter(formatter, labelFormatter),\n },\n } as EChartsOption\n}\n\n/**\n * Tooltip formatter for the horizontal-bar fallback. Reads the value by\n * `encode.x` dimension index (v1 parity) so it stays robust to\n * downstream changes that rename dataset columns.\n */\nfunction buildHorizontalBarTooltipFormatter(\n formatter: ((value: number) => string) | undefined,\n labelFormatter: ((value: string | number) => string | number) | undefined,\n) {\n return createTooltipFormatter((item) => {\n const encodeIndex = item.encode?.x?.at(0)\n const dimName =\n encodeIndex !== undefined ? item.dimensionNames?.[encodeIndex] : undefined\n const row =\n item.value && typeof item.value === 'object' && !Array.isArray(item.value)\n ? (item.value as Record<string, string | number>)\n : undefined\n const raw = dimName && row ? row[dimName] : undefined\n const formattedValue =\n typeof raw === 'number' && formatter ? formatter(raw) : (raw ?? '')\n const marker = typeof item.marker === 'string' ? item.marker : ''\n const seriesName = item.seriesName ? `${item.seriesName}: ` : ''\n const name = labelFormatter\n ? String(labelFormatter(item.name ?? ''))\n : String(item.name ?? '')\n return { name, seriesName, marker, value: formattedValue }\n })\n}\n\n/**\n * Min/max bounds over every datum's `.value` across all series. Used by\n * the horizontal-bar fallback's x-axis label formatter so we only render\n * labels at the rounded extents (matches v1 + bar / histogram).\n */\nfunction computeNiceBounds(seriesArr: PieWidgetData): {\n niceMinVal: number\n niceMaxVal: number\n} {\n let min = 0\n let max = -Infinity\n for (const series of seriesArr) {\n for (const d of series) {\n if (typeof d?.value !== 'number' || !Number.isFinite(d.value)) continue\n if (d.value < min) min = d.value\n if (d.value > max) max = d.value\n }\n }\n return {\n niceMinVal: min < 0 ? niceNum(min) : 0,\n niceMaxVal: max <= 0 ? 1 : niceNum(max),\n }\n}\n\n/**\n * Tooltip formatter for pie slices. `item.value` is the dataset row\n * object (e.g. `{ name: 'A', value: 10 }`); we pull the value by\n * `encode.value`'s dimension index, formatted via the reactive `formatter`\n * if present. Slice name passes through `labelFormatter`.\n */\nfunction buildPieTooltipFormatter(\n formatter: ((value: number) => string) | undefined,\n labelFormatter: ((value: string | number) => string | number) | undefined,\n) {\n return createTooltipFormatter((item) => {\n const encodeIndex = item.encode?.value?.at(0) ?? 1\n const values =\n item.value && typeof item.value === 'object' && !Array.isArray(item.value)\n ? (Object.values(item.value) as (string | number)[])\n : []\n const raw = values[encodeIndex]\n const formattedValue =\n typeof raw === 'number' && formatter ? formatter(raw) : (raw ?? '')\n const marker = typeof item.marker === 'string' ? item.marker : ''\n const seriesName = item.seriesName ? `${item.seriesName}: ` : ''\n const name = labelFormatter\n ? String(labelFormatter(item.name ?? ''))\n : String(item.name ?? '')\n return { name, seriesName, marker, value: formattedValue }\n })\n}\n","import { Box, Skeleton } from '@mui/material'\nimport type { SxProps, Theme } from '@mui/material'\n\nconst OUTER_SIZE = 160\nconst HOLE_SIZE = 96\n\nconst styles = {\n root: {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n minHeight: 200,\n py: 1,\n gap: ({ spacing }) => spacing(2),\n },\n donut: {\n position: 'relative',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n },\n ring: {\n width: OUTER_SIZE,\n height: OUTER_SIZE,\n },\n hole: {\n position: 'absolute',\n zIndex: 1,\n width: HOLE_SIZE,\n height: HOLE_SIZE,\n borderRadius: '50%',\n bgcolor: 'background.paper',\n },\n label: {\n position: 'absolute',\n zIndex: 2,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n gap: ({ spacing }) => spacing(0.5),\n },\n legend: {\n display: 'flex',\n alignItems: 'center',\n gap: ({ spacing }) => spacing(2),\n },\n legendItem: {\n display: 'flex',\n alignItems: 'center',\n gap: ({ spacing }) => spacing(1.5),\n },\n} satisfies Record<string, SxProps<Theme>>\n\nexport interface PieSkeletonProps {\n count?: number\n}\n\n/**\n * Loading state for the Pie widget. Mirrors the donut silhouette — a ring\n * (gray circle with a background-coloured hole punched out), a stacked\n * value/name stub in the centre, and a centered legend stub below — so the\n * skeleton reads as \"a donut chart\" rather than a solid disc.\n *\n * Single donut only: multi-series pie loads as a horizontal bar chart, so\n * rendering one ring stays honest regardless of `count`.\n */\nexport function PieSkeleton({ count }: PieSkeletonProps) {\n // `count` is accepted for API compatibility but intentionally unused: the\n // skeleton always renders a single donut, since multi-series pie loads as a\n // horizontal bar chart rather than multiple donuts.\n void count\n return (\n <Box sx={styles.root}>\n <Box sx={styles.donut}>\n <Skeleton variant='circular' sx={styles.ring} />\n <Box sx={styles.hole} />\n <Box sx={styles.label}>\n <Skeleton width={56} height={18} />\n <Skeleton width={36} height={8} />\n </Box>\n </Box>\n <Box sx={styles.legend}>\n {[0, 1].map((i) => (\n <Box key={`legend-${i}`} sx={styles.legendItem}>\n <Skeleton variant='circular' width={8} height={8} />\n <Skeleton width={48} height={8} />\n </Box>\n ))}\n </Box>\n </Box>\n )\n}\n","import {\n buildCsvDownloadItem,\n buildPngDownloadItem,\n type DownloadItem,\n} from '../actions/download'\nimport type { PieWidgetData } from './types'\n\n/**\n * Download menu items for the Pie widget. Always includes a CSV item with\n * `series, name, value` columns (one row per slice; series labels come from\n * `seriesNames` if provided, else `series_<n>`). When `getCaptureEl` is\n * supplied, prepends a PNG item that rasterises the captured element via\n * `html2canvas`.\n */\nexport function createPieDownloadConfig(args: {\n filename: string\n getData: () => PieWidgetData\n seriesNames?: readonly string[]\n getCaptureEl?: () => HTMLElement | null\n pngPixelRatio?: number\n pngBackgroundColor?: string | null\n}): DownloadItem[] {\n const items: DownloadItem[] = []\n if (args.getCaptureEl) {\n items.push(\n buildPngDownloadItem({\n filename: args.filename,\n getCaptureEl: args.getCaptureEl,\n pixelRatio: args.pngPixelRatio,\n backgroundColor: args.pngBackgroundColor,\n }),\n )\n }\n items.push(\n buildCsvDownloadItem({\n filename: args.filename,\n getRows: () => {\n const data = args.getData()\n const rows: unknown[][] = [['series', 'name', 'value']]\n for (const [i, series] of data.entries()) {\n const seriesName = args.seriesNames?.[i] ?? `series_${i + 1}`\n for (const slice of series) {\n rows.push([seriesName, slice.name, slice.value])\n }\n }\n return rows\n },\n }),\n )\n return items\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pie.js","names":["Theme","EChartsOption","echarts","CallbackDataParams","buildGridConfig","buildLegendConfig","buildSeriesLabelConfig","createTooltipFormatter","createTooltipPositioner","niceNum","OptionFactory","OptionFactoryContext","mergeOptions","resolveThemeColor","WidgetSeries","PieEChartsOption","PieOptionFactoryInput","PieOptionsInput","PieWidgetData","DEFAULT_RADIUS","pieOptions","theme","formatter","labelFormatter","legend","hasLegend","left","type","itemGap","selectedMode","tooltip","trigger","backgroundColor","palette","grey","borderWidth","padding","parseInt","spacing","textStyle","color","common","white","fontSize","fontFamily","typography","caption","position","buildPieTooltipFormatter","Object","values","qualitative","bold","Record","series","colorBy","avoidLabelOverlap","selectedOffset","legendHoverLink","emphasis","disabled","itemStyle","borderColor","background","paper","label","show","rich","b","fontWeight","lineHeight","c","createPieOptionFactory","options","optionsOverride","radius","selection","selectionSet","undefined","length","Set","option","data","ctx","structural","Partial","seriesArr","Array","isArray","dataset","buildMultiSeriesBarFusion","buildSingleSeriesPieFusion","seriesTemplates","broadcastTemplate","baseTooltip","baseLegend","resolvePaletteColor","params","swatch","dataIndex","colorFn","base","datum","value","name","has","modifyAlpha","templateLabelPosition","isCenterLabel","centerData","centerMaxName","centerMaxValue","Infinity","d","labelTextFormatter","encodeIndex","encode","at","formattedValue","String","formattedName","separator","map","s","source","_","i","template","templateObj","templateLabel","templateItemStyle","const","datasetIndex","center","itemName","selected","fromEntries","baseGrid","grid","niceMinVal","niceMaxVal","computeNiceBounds","barColorFn","seriesIdx","seriesIndex","seriesSwatch","right","containLabel","overrideColor","barMaxWidth","focus","xAxis","min","max","axisLine","axisTick","splitLine","lineStyle","black","divider","axisLabel","overlineDelicate","margin","showMaxLabel","showMinLabel","yAxis","buildHorizontalBarTooltipFormatter","item","x","dimName","dimensionNames","row","raw","marker","seriesName","Number","isFinite","Box","Skeleton","SxProps","Theme","OUTER_SIZE","HOLE_SIZE","styles","root","display","flexDirection","alignItems","justifyContent","minHeight","py","gap","spacing","donut","position","ring","width","height","hole","zIndex","borderRadius","bgcolor","label","legend","legendItem","Record","PieSkeletonProps","count","PieSkeleton","t0","$","_c","t1","t2","Symbol","for","t3","t4","map","_temp","i","buildCsvDownloadItem","buildPngDownloadItem","DownloadItem","PieWidgetData","createPieDownloadConfig","args","filename","getData","seriesNames","getCaptureEl","HTMLElement","pngPixelRatio","pngBackgroundColor","items","push","pixelRatio","backgroundColor","getRows","data","rows","i","series","entries","seriesName","slice","name","value"],"sources":["../../src/widgets-v2/pie/options.ts","../../src/widgets-v2/pie/skeleton.tsx","../../src/widgets-v2/pie/download.ts"],"sourcesContent":["import type { Theme } from '@mui/material'\nimport type { EChartsOption } from 'echarts'\nimport * as echarts from 'echarts'\nimport type { CallbackDataParams } from 'echarts/types/dist/shared'\nimport {\n buildGridConfig,\n buildLegendConfig,\n buildSeriesLabelConfig,\n createTooltipFormatter,\n createTooltipPositioner,\n niceNum,\n} from '../../widgets/utils/chart-config'\nimport type { OptionFactory, OptionFactoryContext } from '../echart'\nimport { mergeOptions, resolveThemeColor } from '../utils'\nimport type { WidgetSeries } from '../types'\nimport type {\n PieEChartsOption,\n PieOptionFactoryInput,\n PieOptionsInput,\n PieWidgetData,\n} from './types'\n\nconst DEFAULT_RADIUS: readonly [string, string] = ['58%', '74%']\n\n/**\n * Builds the **structural** ECharts option for a pie / donut widget.\n * Mirrors v1's pie look-and-feel: themed legend (`buildLegendConfig`),\n * themed tooltip via `createTooltipPositioner` / `createTooltipFormatter`,\n * `qualitative.bold` color palette, slice borders against the paper\n * background, hover-emphasis disabled, and a centered rich-text label.\n *\n * Layered like Bar / Histogram:\n * - **Theme-aware bits** live here on a series template (slice border,\n * center-label rich style sizes, emphasis-disabled).\n * - **Reactive bits** (tooltip value formatter, center-label text,\n * selection-driven dim) are re-emitted by\n * {@link createPieOptionFactory} at fusion time so RelativeData's\n * percent override flows through.\n */\nexport function pieOptions({\n theme,\n formatter,\n labelFormatter,\n}: PieOptionsInput): PieEChartsOption {\n return {\n legend: {\n ...buildLegendConfig({ hasLegend: true, labelFormatter }),\n // Pie reads better with a centered legend (the donut is radially\n // symmetric — left-aligning the legend below it visually unbalances\n // the chart). Override `buildLegendConfig`'s `type: 'scroll'` with\n // `'plain'` so long category lists wrap to multiple rows instead\n // of clipping the last visible item against the chart container.\n // The wider `itemGap` gives chips breathing room in the typical\n // 3–6 category case.\n left: 'center',\n type: 'scroll',\n itemGap: 16,\n // The legend is presentational only here — the pie has its own\n // click-to-select affordance on the slices themselves, so legend\n // clicks toggling series visibility would be a second, redundant/\n // conflicting interaction model. Hover-highlight is disabled per\n // series via `legendHoverLink` (ECharts has no legend-level knob\n // for it).\n selectedMode: false,\n },\n tooltip: {\n // Pie uses item-trigger (no axis); the rest of the styling mirrors\n // bar/histogram so the dashboard reads consistently — dark\n // grey[900] bg, white caption-font text, padded, with the shared\n // overflow-aware positioner.\n trigger: 'item',\n backgroundColor: theme.palette.grey[900],\n borderWidth: 0,\n padding: [parseInt(theme.spacing(1)), parseInt(theme.spacing(1))],\n textStyle: {\n color: theme.palette.common.white,\n fontSize: 11,\n fontFamily: theme.typography.caption.fontFamily,\n },\n position: createTooltipPositioner(theme),\n formatter: buildPieTooltipFormatter(formatter, labelFormatter),\n },\n // V1 used `qualitative.bold` only (no `secondary.main` prefix) because\n // pie slices are categorical — each slice deserves a distinct palette\n // entry from the start, not a primary highlight.\n color: Object.values(\n (theme.palette as { qualitative?: { bold?: Record<string, string> } })\n .qualitative?.bold ?? {},\n ),\n // Pie template. The merger spreads this into each per-data series it\n // emits — borderColor / borderWidth / emphasis-disabled / label rich\n // sizes all survive through.\n series: [\n {\n type: 'pie',\n colorBy: 'data',\n avoidLabelOverlap: true,\n selectedOffset: 0,\n legendHoverLink: false,\n emphasis: { disabled: true },\n itemStyle: {\n borderColor: theme.palette.background.paper,\n borderWidth: 1,\n },\n label: {\n show: true,\n position: 'center',\n rich: {\n b: { fontSize: 16, fontWeight: 'normal', lineHeight: 20 },\n c: { fontSize: 28, fontWeight: 'bold', lineHeight: 27 },\n },\n },\n },\n ],\n }\n}\n\n/**\n * Returns the pie widget's {@link OptionFactory} — one closure that owns\n * BOTH phases of option construction:\n *\n * - **Structural phase** (`option == null`) — builds the theme-aware\n * structural option via {@link pieOptions}, optionally merging the\n * consumer-supplied `optionsOverride` on top. Called once by Provider\n * to seed `rawOptions` in the store.\n * - **Merge phase** (`option != null`) — fuses post-pipeline `state.data`\n * (`PieWidgetData`) into the option via the dataset API. Single-series\n * → donut (one dataset, `series[i].encode = { itemName: 'name', value: 'value' }`).\n * Multi-series → horizontal-bar fallback (mirrors v1 pie). Reactive\n * formatters from `ctx` drive the tooltip + center label at fusion\n * time so RelativeData's percent formatter flows through without a\n * structural rebuild.\n */\nexport function createPieOptionFactory(\n options: PieOptionFactoryInput,\n): OptionFactory {\n const { theme, formatter, labelFormatter, optionsOverride, series } = options\n const radius = options.radius ?? DEFAULT_RADIUS\n const selection = options.selection\n // An explicit `[]` (deselected down to zero via chart clicks) is treated\n // the same as no selection: the pie has no bar/histogram-style \"nothing\n // selected\" affordance, so dimming every slice would just look broken —\n // it renders fully active, same as the no-interaction state.\n const selectionSet =\n selection === undefined || selection === null || selection.length === 0\n ? null\n : new Set<string | number>(selection)\n return (option, data, ctx) => {\n if (option == null) {\n const structural = pieOptions({ theme, formatter, labelFormatter })\n return optionsOverride\n ? (mergeOptions(\n structural as unknown as Record<string, unknown>,\n optionsOverride as Partial<Record<string, unknown>>,\n ) as EChartsOption)\n : structural\n }\n\n const seriesArr = Array.isArray(data) ? (data as PieWidgetData) : []\n if (seriesArr.length === 0) {\n return { ...option, dataset: [], series: [] }\n }\n if (seriesArr.length > 1) {\n return buildMultiSeriesBarFusion(\n option,\n seriesArr,\n theme,\n series,\n ctx,\n selectionSet,\n )\n }\n return buildSingleSeriesPieFusion(\n option,\n seriesArr,\n radius,\n series,\n ctx,\n selectionSet,\n )\n }\n}\n\n/**\n * Single-series donut fusion. Spreads the structural pie series template\n * into per-data series with center/radius/encoding, wires the reactive\n * center-label / tooltip formatters and the per-data palette-aware\n * selection-dim callback.\n */\nfunction buildSingleSeriesPieFusion(\n option: EChartsOption,\n seriesArr: PieWidgetData,\n radius: readonly [string, string],\n series: readonly WidgetSeries[] | undefined,\n ctx: OptionFactoryContext | undefined,\n selectionSet: Set<string | number> | null,\n): EChartsOption {\n const seriesTemplates = Array.isArray(option.series) ? option.series : []\n const broadcastTemplate = seriesTemplates[0] ?? {}\n const baseTooltip =\n typeof option.tooltip === 'object' && !Array.isArray(option.tooltip)\n ? option.tooltip\n : {}\n const baseLegend =\n typeof option.legend === 'object' && !Array.isArray(option.legend)\n ? option.legend\n : {}\n const formatter = ctx?.formatter\n const labelFormatter = ctx?.labelFormatter\n\n // Pie wants `colorBy: 'data'` — each slice draws from the option's\n // `color` palette by data index. But installing an `itemStyle.color`\n // callback disables ECharts' automatic per-data cycling, and\n // `params.color` collapses to the series color (so every slice goes\n // the same color). We re-implement the per-data palette resolution\n // here so the multicolor look survives selection-driven dimming.\n const palette = Array.isArray(option.color)\n ? (option.color as readonly (string | undefined)[])\n : []\n const resolvePaletteColor = (params: CallbackDataParams): string => {\n const swatch =\n palette.length > 0\n ? palette[params.dataIndex % palette.length]\n : undefined\n return swatch ?? (params.color as string)\n }\n\n // Always emit `itemStyle.color` (passthrough when nothing is selected),\n // not conditionally — same anti-stale-callback rationale as bar /\n // histogram. The slice border + width come from the structural\n // template's `itemStyle` and survive via the spread below.\n //\n // `selectionSet` is the *included* set, same direct semantics as\n // bar/histogram/timeseries (no ADR-014 exclusion inversion). Dim a slice\n // when its name is NOT in the set. `selectionSet` is never a non-null\n // empty Set — the collapse above (`selection.length === 0 → null`) rules\n // that out — so there's no \"dim everything\" case here, unlike a widget\n // that gives `[]` its own \"selected down to nothing\" meaning.\n const colorFn = (params: CallbackDataParams): string => {\n const base = resolvePaletteColor(params)\n if (!selectionSet) return base\n const datum = params.value as { name?: string | number } | undefined\n const name = datum?.name ?? params.name\n return name != null && selectionSet.has(name)\n ? base\n : echarts.color.modifyAlpha(base, 0.15)\n }\n\n // ECharts anchors EVERY slice's `position: 'center'` label at the same\n // point, so at most one of them can ever be legible — the donut design\n // leans into that (one KPI inside the ring) and picks a single slice\n // below. A consumer that moves the labels off the centre gives each\n // slice its own anchor (`'outside'` with leader lines is what the PDF\n // export uses, `'inside'` / `'insideTop'` … likewise), and there the\n // single-label rule is simply wrong: every slice must render its own\n // label. Read the position off the structural template, which already\n // carries the consumer's `optionsOverride`.\n const templateLabelPosition = (\n broadcastTemplate as { label?: { position?: unknown } }\n ).label?.position\n const isCenterLabel =\n templateLabelPosition === undefined || templateLabelPosition === 'center'\n\n // Which slice renders the centre value+name: the greatest value among\n // the *included* slices (all of them when there's no active\n // selection), computed locally — no query round-trip. Only that one\n // slice's formatter call returns text; every other slice returns ''\n // so exactly one label ever renders at the shared centre anchor. Only\n // `typeof value === 'number'` participates — if every included slice's\n // value is non-numeric, `centerMaxName` stays `undefined` and no slice\n // matches it in `labelTextFormatter` below, so the chart renders with no\n // centre label at all (graceful no-op, not a crash). Skipped entirely\n // for off-centre labels, where every slice labels itself.\n const centerData = seriesArr[0] ?? []\n let centerMaxName: string | number | undefined\n let centerMaxValue = -Infinity\n for (const d of centerData) {\n if (selectionSet && !selectionSet.has(d.name)) continue\n if (typeof d.value === 'number' && d.value > centerMaxValue) {\n centerMaxValue = d.value\n centerMaxName = d.name\n }\n }\n\n // Slice label formatter — lives in the merger because it reads\n // reactive `formatter` / `labelFormatter` from ctx. The rich tags\n // `{c|…}` and `{b|…}` reference the rich styles baked into the\n // structural label template.\n const labelTextFormatter = (params: CallbackDataParams): string => {\n const { name } = params\n if (name == null) return ''\n if (isCenterLabel && name !== centerMaxName) return ''\n const encodeIndex = params.encode?.value?.[0]\n if (encodeIndex === undefined) return ''\n const value = (Object.values(params.data ?? {}) as unknown[]).at(\n encodeIndex,\n )\n // `value` here is the resolved dataset cell — for pie data it's a\n // `string | number` primitive. Anything else is a misuse we won't\n // dress up with `String(...)` (would render \"[object Object]\").\n const formattedValue =\n typeof value === 'number'\n ? formatter\n ? formatter(value)\n : String(value)\n : typeof value === 'string'\n ? value\n : ''\n const formattedName = labelFormatter\n ? String(labelFormatter(name ?? ''))\n : String(name ?? '')\n // The blank line is what separates the big centre KPI from its\n // caption. Off-centre labels sit next to their own slice and are\n // laid out against their neighbours, so the spacer only inflates\n // each label's bounding box — enough, with a hidden `{b|…}` block,\n // to make ECharts drop colliding labels altogether.\n const separator = isCenterLabel ? '\\n\\n' : '\\n'\n return `{c|${formattedValue}}${separator}{b|${formattedName}}`\n }\n\n return {\n ...option,\n dataset: seriesArr.map((s) => ({ source: s as readonly object[] })),\n series: seriesArr.map((_, i) => {\n const template =\n (seriesTemplates[i] as object | undefined) ??\n (broadcastTemplate as object)\n const templateObj = typeof template === 'object' ? template : {}\n const templateLabel = (templateObj as { label?: object }).label ?? {}\n const templateItemStyle =\n (templateObj as { itemStyle?: object }).itemStyle ?? {}\n return {\n ...templateObj,\n type: 'pie' as const,\n legendHoverLink: false,\n datasetIndex: i,\n name: series?.[i]?.name ?? `Series ${i + 1}`,\n radius: [...radius],\n // Lift the donut up so the bottom-anchored legend has the\n // vertical real estate to wrap to multiple rows for long\n // category lists — at exactly `50%` the bottom slices crowd\n // the chips and `type: 'plain'` legends can't expand upward\n // without overlapping the donut.\n center: ['50%', '38%'] as [string, string],\n encode: { itemName: 'name', value: 'value' },\n label: {\n ...templateLabel,\n formatter: labelTextFormatter,\n },\n itemStyle: {\n ...templateItemStyle,\n color: colorFn,\n },\n }\n }),\n // Legend always shows for pie (mirrors v1) — slice names drive the\n // entries, so even a single donut benefits from a category list.\n //\n // Exclusion is conveyed purely via `colorFn`/`labelTextFormatter`\n // dimming above, never via the legend's `selected` map: for a pie\n // series, ECharts treats `legend.selected[name] = false` as \"remove\n // this data point,\" which recomputes every remaining slice's angle —\n // the excluded slice disappears instead of rendering dimmed. Forcing\n // every name to `true` on every render also overrides ECharts' own\n // internal toggle state from a native legend click (which flips a\n // name to `false` and hides it before our `legendselectchanged`\n // handler gets a chance to react), so a legend click never leaves a\n // slice structurally removed — only the color/label dimming reflects\n // exclusion, and it stays in sync with the slice itself since both\n // read `selectionSet` on the same render.\n legend: {\n ...baseLegend,\n show: true,\n selectedMode: false,\n selected: Object.fromEntries(\n (seriesArr[0] ?? []).map((d) => [String(d.name), true]),\n ),\n },\n tooltip: {\n ...baseTooltip,\n formatter: buildPieTooltipFormatter(formatter, labelFormatter),\n },\n }\n}\n\n/**\n * Multi-series horizontal-bar fusion. Mirrors v1 pie's \"pie data with\n * >1 series collapses into a horizontal bar chart\" behavior — side-by-\n * side donuts don't read well when you're comparing the same categories\n * across cohorts, so swap to a value-on-x / category-on-y bar layout.\n *\n * Pie data shape is identical to bar's (`{ name, value }[][]`), so the\n * same dataset feeds either layout without transformation.\n */\nfunction buildMultiSeriesBarFusion(\n option: EChartsOption,\n seriesArr: PieWidgetData,\n theme: Theme,\n series: readonly WidgetSeries[] | undefined,\n ctx: OptionFactoryContext | undefined,\n selectionSet: Set<string | number> | null,\n): EChartsOption {\n const baseTooltip =\n typeof option.tooltip === 'object' && !Array.isArray(option.tooltip)\n ? option.tooltip\n : {}\n const baseLegend =\n typeof option.legend === 'object' && !Array.isArray(option.legend)\n ? option.legend\n : {}\n const baseGrid =\n typeof option.grid === 'object' && !Array.isArray(option.grid)\n ? option.grid\n : {}\n const formatter = ctx?.formatter\n const labelFormatter = ctx?.labelFormatter\n\n const { niceMinVal, niceMaxVal } = computeNiceBounds(seriesArr)\n\n // Per-series palette — multi-series bars take one color per series\n // (not per-data, unlike donut slices). Same anti-stale-callback rule:\n // always emit the callback so a transition to/from a selection\n // replaces the previous closure cleanly.\n const palette = Array.isArray(option.color)\n ? (option.color as readonly (string | undefined)[])\n : []\n const barColorFn = (params: CallbackDataParams): string => {\n const seriesIdx = params.seriesIndex ?? 0\n const seriesSwatch =\n palette.length > 0 ? palette[seriesIdx % palette.length] : undefined\n const base = (seriesSwatch ?? params.color) as string\n if (!selectionSet) return base\n const datum = params.value as { name?: string | number } | undefined\n const name = datum?.name ?? params.name\n return name != null && selectionSet.has(name)\n ? base\n : echarts.color.modifyAlpha(base, 0.15)\n }\n\n return {\n ...option,\n dataset: seriesArr.map((s) => ({ source: s as readonly object[] })),\n grid: {\n ...baseGrid,\n ...buildGridConfig(true, theme),\n right: parseInt(theme.spacing(4)),\n containLabel: true,\n },\n // Drop pie-specific structural keys that shouldn't render in the\n // bar fallback. ECharts ignores undefined keys, so this is a clean\n // override.\n series: seriesArr.map((_, i) => {\n const overrideColor = resolveThemeColor(theme, series?.[i]?.color)\n return {\n datasetIndex: i,\n type: 'bar' as const,\n name: series?.[i]?.name ?? `Series ${i + 1}`,\n barMaxWidth: 100,\n legendHoverLink: false,\n emphasis: { focus: 'series' },\n ...buildSeriesLabelConfig(formatter, 'x'),\n itemStyle: { color: barColorFn },\n ...(overrideColor ? { color: overrideColor } : {}),\n }\n }),\n xAxis: {\n type: 'value',\n // Closures over the pre-computed nice bounds — ECharts calls them\n // once per render to resolve the axis extents.\n min: () => niceMinVal,\n max: () => niceMaxVal,\n axisLine: { show: false },\n axisTick: { show: false },\n splitLine: {\n show: true,\n lineStyle: { color: theme.palette.black?.[4] ?? theme.palette.divider },\n },\n // Value labels render BELOW the axis line (default placement),\n // NOT inside the plot. Bar/histogram use `inside: true` +\n // `verticalAlign: 'bottom'` for their *vertical* y-axis where the\n // axis is the left wall — labels inside read like grid annotations.\n // A horizontal bar chart's value axis is the x-axis, and `inside`\n // there pushes the max label *behind* the bar (it visually\n // disappears once a bar reaches the right edge). Use the default\n // below-the-axis placement so the rounded extents stay readable.\n axisLabel: {\n fontSize: theme.typography.overlineDelicate?.fontSize,\n fontFamily: theme.typography.overlineDelicate?.fontFamily,\n margin: parseInt(theme.spacing(1)),\n showMaxLabel: true,\n showMinLabel: true,\n formatter: (value: number) => {\n if (value !== niceMaxVal && value !== niceMinVal) return ''\n if (value === 0) return ''\n return formatter ? formatter(value) : String(value)\n },\n },\n },\n yAxis: {\n type: 'category',\n axisLine: { show: false },\n axisTick: { show: false },\n axisLabel: {\n padding: [parseInt(theme.spacing(0.5)), 0, 0, 0],\n ...(labelFormatter && {\n formatter: (value: string | number) => String(labelFormatter(value)),\n }),\n },\n },\n // Mirrors the donut branch's `selected` reset above — `selectedMode:\n // false` blocks the native legend click that would otherwise undo an\n // ECharts-internal toggle, so without forcing every entry back to\n // `true` here a prior native toggle (from before `selectedMode` took\n // effect, or a stale `keepAlive` instance) would stay hidden forever\n // with no way to restore it.\n legend: {\n ...baseLegend,\n show: true,\n selectedMode: false,\n selected: Object.fromEntries(\n seriesArr.map((_, i) => [series?.[i]?.name ?? `Series ${i + 1}`, true]),\n ),\n },\n tooltip: {\n ...baseTooltip,\n trigger: 'axis',\n formatter: buildHorizontalBarTooltipFormatter(formatter, labelFormatter),\n },\n } as EChartsOption\n}\n\n/**\n * Tooltip formatter for the horizontal-bar fallback. Reads the value by\n * `encode.x` dimension index (v1 parity) so it stays robust to\n * downstream changes that rename dataset columns.\n */\nfunction buildHorizontalBarTooltipFormatter(\n formatter: ((value: number) => string) | undefined,\n labelFormatter: ((value: string | number) => string | number) | undefined,\n) {\n return createTooltipFormatter((item) => {\n const encodeIndex = item.encode?.x?.at(0)\n const dimName =\n encodeIndex !== undefined ? item.dimensionNames?.[encodeIndex] : undefined\n const row =\n item.value && typeof item.value === 'object' && !Array.isArray(item.value)\n ? (item.value as Record<string, string | number>)\n : undefined\n const raw = dimName && row ? row[dimName] : undefined\n const formattedValue =\n typeof raw === 'number' && formatter ? formatter(raw) : (raw ?? '')\n const marker = typeof item.marker === 'string' ? item.marker : ''\n const seriesName = item.seriesName ? `${item.seriesName}: ` : ''\n const name = labelFormatter\n ? String(labelFormatter(item.name ?? ''))\n : String(item.name ?? '')\n return { name, seriesName, marker, value: formattedValue }\n })\n}\n\n/**\n * Min/max bounds over every datum's `.value` across all series. Used by\n * the horizontal-bar fallback's x-axis label formatter so we only render\n * labels at the rounded extents (matches v1 + bar / histogram).\n */\nfunction computeNiceBounds(seriesArr: PieWidgetData): {\n niceMinVal: number\n niceMaxVal: number\n} {\n let min = 0\n let max = -Infinity\n for (const series of seriesArr) {\n for (const d of series) {\n if (typeof d?.value !== 'number' || !Number.isFinite(d.value)) continue\n if (d.value < min) min = d.value\n if (d.value > max) max = d.value\n }\n }\n return {\n niceMinVal: min < 0 ? niceNum(min) : 0,\n niceMaxVal: max <= 0 ? 1 : niceNum(max),\n }\n}\n\n/**\n * Tooltip formatter for pie slices. `item.value` is the dataset row\n * object (e.g. `{ name: 'A', value: 10 }`); we pull the value by\n * `encode.value`'s dimension index, formatted via the reactive `formatter`\n * if present. Slice name passes through `labelFormatter`.\n */\nfunction buildPieTooltipFormatter(\n formatter: ((value: number) => string) | undefined,\n labelFormatter: ((value: string | number) => string | number) | undefined,\n) {\n return createTooltipFormatter((item) => {\n const encodeIndex = item.encode?.value?.at(0) ?? 1\n const values =\n item.value && typeof item.value === 'object' && !Array.isArray(item.value)\n ? (Object.values(item.value) as (string | number)[])\n : []\n const raw = values[encodeIndex]\n const formattedValue =\n typeof raw === 'number' && formatter ? formatter(raw) : (raw ?? '')\n const marker = typeof item.marker === 'string' ? item.marker : ''\n const seriesName = item.seriesName ? `${item.seriesName}: ` : ''\n const name = labelFormatter\n ? String(labelFormatter(item.name ?? ''))\n : String(item.name ?? '')\n return { name, seriesName, marker, value: formattedValue }\n })\n}\n","import { Box, Skeleton } from '@mui/material'\nimport type { SxProps, Theme } from '@mui/material'\n\nconst OUTER_SIZE = 160\nconst HOLE_SIZE = 96\n\nconst styles = {\n root: {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n minHeight: 200,\n py: 1,\n gap: ({ spacing }) => spacing(2),\n },\n donut: {\n position: 'relative',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n },\n ring: {\n width: OUTER_SIZE,\n height: OUTER_SIZE,\n },\n hole: {\n position: 'absolute',\n zIndex: 1,\n width: HOLE_SIZE,\n height: HOLE_SIZE,\n borderRadius: '50%',\n bgcolor: 'background.paper',\n },\n label: {\n position: 'absolute',\n zIndex: 2,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n gap: ({ spacing }) => spacing(0.5),\n },\n legend: {\n display: 'flex',\n alignItems: 'center',\n gap: ({ spacing }) => spacing(2),\n },\n legendItem: {\n display: 'flex',\n alignItems: 'center',\n gap: ({ spacing }) => spacing(1.5),\n },\n} satisfies Record<string, SxProps<Theme>>\n\nexport interface PieSkeletonProps {\n count?: number\n}\n\n/**\n * Loading state for the Pie widget. Mirrors the donut silhouette — a ring\n * (gray circle with a background-coloured hole punched out), a stacked\n * value/name stub in the centre, and a centered legend stub below — so the\n * skeleton reads as \"a donut chart\" rather than a solid disc.\n *\n * Single donut only: multi-series pie loads as a horizontal bar chart, so\n * rendering one ring stays honest regardless of `count`.\n */\nexport function PieSkeleton({ count }: PieSkeletonProps) {\n // `count` is accepted for API compatibility but intentionally unused: the\n // skeleton always renders a single donut, since multi-series pie loads as a\n // horizontal bar chart rather than multiple donuts.\n void count\n return (\n <Box sx={styles.root}>\n <Box sx={styles.donut}>\n <Skeleton variant='circular' sx={styles.ring} />\n <Box sx={styles.hole} />\n <Box sx={styles.label}>\n <Skeleton width={56} height={18} />\n <Skeleton width={36} height={8} />\n </Box>\n </Box>\n <Box sx={styles.legend}>\n {[0, 1].map((i) => (\n <Box key={`legend-${i}`} sx={styles.legendItem}>\n <Skeleton variant='circular' width={8} height={8} />\n <Skeleton width={48} height={8} />\n </Box>\n ))}\n </Box>\n </Box>\n )\n}\n","import {\n buildCsvDownloadItem,\n buildPngDownloadItem,\n type DownloadItem,\n} from '../actions/download'\nimport type { PieWidgetData } from './types'\n\n/**\n * Download menu items for the Pie widget. Always includes a CSV item with\n * `series, name, value` columns (one row per slice; series labels come from\n * `seriesNames` if provided, else `series_<n>`). When `getCaptureEl` is\n * supplied, prepends a PNG item that rasterises the captured element via\n * `html2canvas`.\n */\nexport function createPieDownloadConfig(args: {\n filename: string\n getData: () => PieWidgetData\n seriesNames?: readonly string[]\n getCaptureEl?: () => HTMLElement | null\n pngPixelRatio?: number\n pngBackgroundColor?: string | null\n}): DownloadItem[] {\n const items: DownloadItem[] = []\n if (args.getCaptureEl) {\n items.push(\n buildPngDownloadItem({\n filename: args.filename,\n getCaptureEl: args.getCaptureEl,\n pixelRatio: args.pngPixelRatio,\n backgroundColor: args.pngBackgroundColor,\n }),\n )\n }\n items.push(\n buildCsvDownloadItem({\n filename: args.filename,\n getRows: () => {\n const data = args.getData()\n const rows: unknown[][] = [['series', 'name', 'value']]\n for (const [i, series] of data.entries()) {\n const seriesName = args.seriesNames?.[i] ?? `series_${i + 1}`\n for (const slice of series) {\n rows.push([seriesName, slice.name, slice.value])\n }\n }\n return rows\n },\n }),\n )\n return items\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@carto/ps-react-ui",
|
|
3
|
-
"version": "4.20.
|
|
3
|
+
"version": "4.20.2",
|
|
4
4
|
"description": "CARTO's Professional Service React Material library",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"devDependencies": {
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
"react-dom": "19.2.8",
|
|
18
18
|
"react-markdown": "10.1.0",
|
|
19
19
|
"zustand": "5.0.15",
|
|
20
|
-
"@carto/ps-
|
|
21
|
-
"@carto/ps-
|
|
20
|
+
"@carto/ps-utils": "2.1.0",
|
|
21
|
+
"@carto/ps-common-types": "1.0.0"
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {
|
|
24
24
|
"@carto/meridian-ds": "^2.0.0",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Box, IconButton } from '@mui/material'
|
|
2
|
-
import FirstPageIcon from '@mui/icons-material
|
|
3
|
-
import KeyboardArrowLeft from '@mui/icons-material
|
|
4
|
-
import KeyboardArrowRight from '@mui/icons-material
|
|
5
|
-
import LastPageIcon from '@mui/icons-material
|
|
2
|
+
import { FirstPage as FirstPageIcon } from '@mui/icons-material'
|
|
3
|
+
import { KeyboardArrowLeft } from '@mui/icons-material'
|
|
4
|
+
import { KeyboardArrowRight } from '@mui/icons-material'
|
|
5
|
+
import { LastPage as LastPageIcon } from '@mui/icons-material'
|
|
6
6
|
import type { PaginationActionsProps } from '../types'
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -391,6 +391,73 @@ describe('createPieOptionFactory — single-series (donut)', () => {
|
|
|
391
391
|
).toBe('')
|
|
392
392
|
})
|
|
393
393
|
|
|
394
|
+
it('label formatter renders EVERY slice when the label is moved off the centre (e.g. PDF outside labels)', () => {
|
|
395
|
+
// `position: 'center'` stacks every label on one anchor, so only the
|
|
396
|
+
// max-valued slice draws. An override that gives each slice its own
|
|
397
|
+
// anchor must label them all — otherwise a PDF/report export shows a
|
|
398
|
+
// single value and orphan leader lines for the rest.
|
|
399
|
+
const merge = createPieOptionFactory({ theme })
|
|
400
|
+
const out = merge(
|
|
401
|
+
{
|
|
402
|
+
series: [
|
|
403
|
+
{
|
|
404
|
+
type: 'pie' as const,
|
|
405
|
+
label: { show: true, position: 'outside' },
|
|
406
|
+
},
|
|
407
|
+
] as unknown as never,
|
|
408
|
+
},
|
|
409
|
+
[
|
|
410
|
+
[
|
|
411
|
+
{ name: 'A', value: 10 },
|
|
412
|
+
{ name: 'B', value: 25 },
|
|
413
|
+
],
|
|
414
|
+
],
|
|
415
|
+
) as {
|
|
416
|
+
series: { label: { formatter: (p: Record<string, unknown>) => string } }[]
|
|
417
|
+
}
|
|
418
|
+
const fmt = out.series[0]!.label.formatter
|
|
419
|
+
expect(
|
|
420
|
+
fmt({
|
|
421
|
+
name: 'A',
|
|
422
|
+
encode: { value: [1] },
|
|
423
|
+
data: { name: 'A', value: 10 },
|
|
424
|
+
}),
|
|
425
|
+
).toBe('{c|10}\n{b|A}')
|
|
426
|
+
expect(
|
|
427
|
+
fmt({
|
|
428
|
+
name: 'B',
|
|
429
|
+
encode: { value: [1] },
|
|
430
|
+
data: { name: 'B', value: 25 },
|
|
431
|
+
}),
|
|
432
|
+
).toBe('{c|25}\n{b|B}')
|
|
433
|
+
})
|
|
434
|
+
|
|
435
|
+
it('keeps the blank-line spacer for centre labels and drops it for off-centre ones', () => {
|
|
436
|
+
const data = [[{ name: 'A', value: 10 }]]
|
|
437
|
+
const params = {
|
|
438
|
+
name: 'A',
|
|
439
|
+
encode: { value: [1] },
|
|
440
|
+
data: { name: 'A', value: 10 },
|
|
441
|
+
}
|
|
442
|
+
interface Out {
|
|
443
|
+
series: { label: { formatter: (p: Record<string, unknown>) => string } }[]
|
|
444
|
+
}
|
|
445
|
+
const centered = createPieOptionFactory({ theme })(
|
|
446
|
+
{},
|
|
447
|
+
data,
|
|
448
|
+
) as unknown as Out
|
|
449
|
+
const outside = createPieOptionFactory({ theme })(
|
|
450
|
+
{
|
|
451
|
+
series: [
|
|
452
|
+
{ type: 'pie' as const, label: { position: 'inside' } },
|
|
453
|
+
] as unknown as never,
|
|
454
|
+
},
|
|
455
|
+
data,
|
|
456
|
+
) as unknown as Out
|
|
457
|
+
expect(centered.series[0]!.label.formatter(params)).toBe('{c|10}\n\n{b|A}')
|
|
458
|
+
expect(outside.series[0]!.label.formatter(params)).toBe('{c|10}\n{b|A}')
|
|
459
|
+
})
|
|
460
|
+
|
|
394
461
|
it('label formatter treats an explicit empty selection as no selection (renders the true max, not blank)', () => {
|
|
395
462
|
const merge = createPieOptionFactory({ theme, selection: [] })
|
|
396
463
|
const out = merge({}, [[{ name: 'A', value: 10 }]]) as {
|
|
@@ -246,6 +246,21 @@ function buildSingleSeriesPieFusion(
|
|
|
246
246
|
: echarts.color.modifyAlpha(base, 0.15)
|
|
247
247
|
}
|
|
248
248
|
|
|
249
|
+
// ECharts anchors EVERY slice's `position: 'center'` label at the same
|
|
250
|
+
// point, so at most one of them can ever be legible — the donut design
|
|
251
|
+
// leans into that (one KPI inside the ring) and picks a single slice
|
|
252
|
+
// below. A consumer that moves the labels off the centre gives each
|
|
253
|
+
// slice its own anchor (`'outside'` with leader lines is what the PDF
|
|
254
|
+
// export uses, `'inside'` / `'insideTop'` … likewise), and there the
|
|
255
|
+
// single-label rule is simply wrong: every slice must render its own
|
|
256
|
+
// label. Read the position off the structural template, which already
|
|
257
|
+
// carries the consumer's `optionsOverride`.
|
|
258
|
+
const templateLabelPosition = (
|
|
259
|
+
broadcastTemplate as { label?: { position?: unknown } }
|
|
260
|
+
).label?.position
|
|
261
|
+
const isCenterLabel =
|
|
262
|
+
templateLabelPosition === undefined || templateLabelPosition === 'center'
|
|
263
|
+
|
|
249
264
|
// Which slice renders the centre value+name: the greatest value among
|
|
250
265
|
// the *included* slices (all of them when there's no active
|
|
251
266
|
// selection), computed locally — no query round-trip. Only that one
|
|
@@ -254,7 +269,8 @@ function buildSingleSeriesPieFusion(
|
|
|
254
269
|
// `typeof value === 'number'` participates — if every included slice's
|
|
255
270
|
// value is non-numeric, `centerMaxName` stays `undefined` and no slice
|
|
256
271
|
// matches it in `labelTextFormatter` below, so the chart renders with no
|
|
257
|
-
// centre label at all (graceful no-op, not a crash).
|
|
272
|
+
// centre label at all (graceful no-op, not a crash). Skipped entirely
|
|
273
|
+
// for off-centre labels, where every slice labels itself.
|
|
258
274
|
const centerData = seriesArr[0] ?? []
|
|
259
275
|
let centerMaxName: string | number | undefined
|
|
260
276
|
let centerMaxValue = -Infinity
|
|
@@ -266,13 +282,14 @@ function buildSingleSeriesPieFusion(
|
|
|
266
282
|
}
|
|
267
283
|
}
|
|
268
284
|
|
|
269
|
-
//
|
|
285
|
+
// Slice label formatter — lives in the merger because it reads
|
|
270
286
|
// reactive `formatter` / `labelFormatter` from ctx. The rich tags
|
|
271
287
|
// `{c|…}` and `{b|…}` reference the rich styles baked into the
|
|
272
288
|
// structural label template.
|
|
273
289
|
const labelTextFormatter = (params: CallbackDataParams): string => {
|
|
274
290
|
const { name } = params
|
|
275
|
-
if (name == null
|
|
291
|
+
if (name == null) return ''
|
|
292
|
+
if (isCenterLabel && name !== centerMaxName) return ''
|
|
276
293
|
const encodeIndex = params.encode?.value?.[0]
|
|
277
294
|
if (encodeIndex === undefined) return ''
|
|
278
295
|
const value = (Object.values(params.data ?? {}) as unknown[]).at(
|
|
@@ -292,7 +309,13 @@ function buildSingleSeriesPieFusion(
|
|
|
292
309
|
const formattedName = labelFormatter
|
|
293
310
|
? String(labelFormatter(name ?? ''))
|
|
294
311
|
: String(name ?? '')
|
|
295
|
-
|
|
312
|
+
// The blank line is what separates the big centre KPI from its
|
|
313
|
+
// caption. Off-centre labels sit next to their own slice and are
|
|
314
|
+
// laid out against their neighbours, so the spacer only inflates
|
|
315
|
+
// each label's bounding box — enough, with a hidden `{b|…}` block,
|
|
316
|
+
// to make ECharts drop colliding labels altogether.
|
|
317
|
+
const separator = isCenterLabel ? '\n\n' : '\n'
|
|
318
|
+
return `{c|${formattedValue}}${separator}{b|${formattedName}}`
|
|
296
319
|
}
|
|
297
320
|
|
|
298
321
|
return {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, it, expect, vi } from 'vitest'
|
|
2
2
|
import { fireEvent, render, screen } from '@testing-library/react'
|
|
3
|
-
import StarIcon from '@mui/icons-material
|
|
3
|
+
import { Star as StarIcon } from '@mui/icons-material'
|
|
4
4
|
import { SelectionSummary } from './selection-summary'
|
|
5
5
|
|
|
6
6
|
describe('<SelectionSummary>', () => {
|
|
@@ -2,7 +2,7 @@ import { useEffect, useRef } from 'react'
|
|
|
2
2
|
import { describe, it, expect } from 'vitest'
|
|
3
3
|
import { fireEvent, render, screen } from '@testing-library/react'
|
|
4
4
|
import { IconButton } from '@mui/material'
|
|
5
|
-
import StarIcon from '@mui/icons-material
|
|
5
|
+
import { Star as StarIcon } from '@mui/icons-material'
|
|
6
6
|
import { Toolbox } from './toolbox'
|
|
7
7
|
|
|
8
8
|
function makeChildren(n: number) {
|