Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cea8cd4bc9 | ||
|
|
002381d294 | ||
|
|
9b406d5d83 |
No files matched your search
@@ -16,7 +16,7 @@ import beszelSystemGrid from "./img/beszel-system-grid.png";
|
||||
|
||||
<WidgetHeader widget={beszelSystemGridWidget} categories={["System Monitoring"]} />
|
||||
|
||||
This widget displays all your Beszel-monitored systems as a responsive card grid. Each card shows real-time metrics like CPU, memory, disk, network, temperature, and more. Cards adapt their layout based on available space. If Beszel reports multiple filesystems, the disk bar exposes a hover breakdown for the root disk and each extra mount.
|
||||
This widget displays all your Beszel-monitored systems as a responsive card grid. Each card shows real-time metrics like CPU, memory, disk, network, temperature, and more. Resizing the widget adjusts its rows and columns to keep the cards balanced. If Beszel reports multiple filesystems, the disk bar exposes a hover breakdown for the root disk and each extra mount.
|
||||
|
||||
Select a system card to open the complete statistics view, including system, filesystem, Docker, historical, and realtime charts.
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@ import advancedView from "./img/advanced-view.png";
|
||||
|
||||
### Interactions
|
||||
|
||||
- Colored dots directly below a date mark its events. They scale with the widget and are hidden when the calendar is too short.
|
||||
- Hover over a marked date to preview its events in a popover.
|
||||
- The advanced view replaces the month grid with a grouped event list, keeps every event attributed to its source integration, and expands titles, locations, and descriptions. Use its previous and next controls to change months.
|
||||
- If one selected integration is unavailable, its warning indicator remains visible while events from healthy integrations continue to load.
|
||||
|
||||
@@ -4836,70 +4836,70 @@
|
||||
},
|
||||
"items": {
|
||||
"actions": {
|
||||
"columnTitle": "Controls"
|
||||
"columnTitle": "Actions"
|
||||
},
|
||||
"added": {
|
||||
"columnTitle": "Added",
|
||||
"detailsTitle": "Date Added"
|
||||
"detailsTitle": "Added"
|
||||
},
|
||||
"category": {
|
||||
"columnTitle": "Extras",
|
||||
"detailsTitle": "Categories (Or extra information)"
|
||||
"columnTitle": "Category",
|
||||
"detailsTitle": "Category"
|
||||
},
|
||||
"downSpeed": {
|
||||
"columnTitle": "Down",
|
||||
"detailsTitle": "Download Speed"
|
||||
"detailsTitle": "Down"
|
||||
},
|
||||
"index": {
|
||||
"columnTitle": "#",
|
||||
"detailsTitle": "Current index within client"
|
||||
"detailsTitle": "Index"
|
||||
},
|
||||
"id": {
|
||||
"columnTitle": "Id",
|
||||
"detailsTitle": "Item ID"
|
||||
"columnTitle": "ID",
|
||||
"detailsTitle": "ID"
|
||||
},
|
||||
"integration": {
|
||||
"columnTitle": "Integration"
|
||||
"columnTitle": "Source"
|
||||
},
|
||||
"name": {
|
||||
"columnTitle": "Job name"
|
||||
"columnTitle": "Name"
|
||||
},
|
||||
"progress": {
|
||||
"columnTitle": "Progress",
|
||||
"detailsTitle": "Download Progress"
|
||||
"detailsTitle": "Progress"
|
||||
},
|
||||
"ratio": {
|
||||
"columnTitle": "Ratio",
|
||||
"detailsTitle": "Torrent ratio (received/sent)"
|
||||
"detailsTitle": "Ratio"
|
||||
},
|
||||
"received": {
|
||||
"columnTitle": "Total down",
|
||||
"detailsTitle": "Total downloaded"
|
||||
"columnTitle": "Down",
|
||||
"detailsTitle": "Downloaded"
|
||||
},
|
||||
"sent": {
|
||||
"columnTitle": "Total up",
|
||||
"detailsTitle": "Total Uploaded"
|
||||
"columnTitle": "Up",
|
||||
"detailsTitle": "Uploaded"
|
||||
},
|
||||
"size": {
|
||||
"columnTitle": "File Size",
|
||||
"detailsTitle": "Total Size of selection/files"
|
||||
"columnTitle": "Size",
|
||||
"detailsTitle": "Size"
|
||||
},
|
||||
"state": {
|
||||
"columnTitle": "State",
|
||||
"detailsTitle": "Job State"
|
||||
"detailsTitle": "State"
|
||||
},
|
||||
"time": {
|
||||
"columnTitle": "Finish time",
|
||||
"detailsTitle": "Time since/to completion",
|
||||
"columnTitle": "ETA",
|
||||
"detailsTitle": "ETA",
|
||||
"eta": "ETA"
|
||||
},
|
||||
"type": {
|
||||
"columnTitle": "Type",
|
||||
"detailsTitle": "Download Client type"
|
||||
"detailsTitle": "Type"
|
||||
},
|
||||
"upSpeed": {
|
||||
"columnTitle": "Up",
|
||||
"detailsTitle": "Upload Speed"
|
||||
"detailsTitle": "Up"
|
||||
}
|
||||
},
|
||||
"states": {
|
||||
|
||||
@@ -123,19 +123,12 @@ const MIN_CELL_HEIGHT = 80;
|
||||
const ADVANCED_MIN_CELL_WIDTH = 320;
|
||||
const ADVANCED_MIN_CELL_HEIGHT = 420;
|
||||
|
||||
const getColCount = (width: number, _height: number, itemCount: number, minCellWidth = MIN_CELL_WIDTH): number => {
|
||||
const getColCount = (width: number, height: number, itemCount: number, minCellWidth = MIN_CELL_WIDTH): number => {
|
||||
if (itemCount <= 1) return 1;
|
||||
const maxCols = Math.min(itemCount, Math.max(1, Math.floor(width / minCellWidth)));
|
||||
|
||||
let best = 1;
|
||||
for (let c = 1; c <= maxCols; c++) {
|
||||
const emptyCells = (c - (itemCount % c)) % c;
|
||||
const bestEmpty = (best - (itemCount % best)) % best;
|
||||
if (emptyCells < bestEmpty || (emptyCells === bestEmpty && c > best)) {
|
||||
best = c;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
const aspectRatio = width / Math.max(height, MIN_CELL_HEIGHT);
|
||||
const idealCols = Math.round(Math.sqrt(itemCount * aspectRatio));
|
||||
return Math.min(maxCols, Math.max(1, idealCols));
|
||||
};
|
||||
|
||||
interface MetricRowProps {
|
||||
|
||||
@@ -20,27 +20,29 @@ export const CalendarDay = ({ date, events, disabled, rootHeight, rootWidth }: C
|
||||
|
||||
const minAxisSize = Math.min(rootWidth, rootHeight);
|
||||
const shouldScaleDown = minAxisSize < 350;
|
||||
const isSmall = rootHeight < 256;
|
||||
const shouldShowIndicators = rootHeight >= 256;
|
||||
const indicatorSize = shouldScaleDown ? 3 : 4;
|
||||
|
||||
const cell = (
|
||||
<Container
|
||||
h="100%"
|
||||
w="100%"
|
||||
p={0}
|
||||
pt={isSmall ? 0 : 10}
|
||||
pb={isSmall ? 0 : 10}
|
||||
m={0}
|
||||
pos="relative"
|
||||
style={{
|
||||
alignContent: "center",
|
||||
alignItems: "center",
|
||||
borderRadius: actualItemRadius,
|
||||
cursor: disabled ? "default" : "pointer",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
<Text ta={"center"} size={shouldScaleDown ? "xs" : "md"} lh={1}>
|
||||
{date.getDate()}
|
||||
</Text>
|
||||
<NotificationIndicator events={events} isSmall={isSmall} />
|
||||
<NotificationIndicator events={events} size={indicatorSize} visible={shouldShowIndicators} />
|
||||
</Container>
|
||||
);
|
||||
|
||||
@@ -67,25 +69,34 @@ export const CalendarDay = ({ date, events, disabled, rootHeight, rootWidth }: C
|
||||
|
||||
interface NotificationIndicatorProps {
|
||||
events: CalendarEvent[];
|
||||
isSmall: boolean;
|
||||
size: number;
|
||||
visible: boolean;
|
||||
}
|
||||
|
||||
const NotificationIndicator = ({ events, isSmall }: NotificationIndicatorProps) => {
|
||||
const notificationEvents = [...new Set(events.map((event) => event.indicatorColor))].filter(String);
|
||||
const NotificationIndicator = ({ events, size, visible }: NotificationIndicatorProps) => {
|
||||
const notificationEvents = [...new Set(events.map((event) => event.indicatorColor))].filter(
|
||||
(color): color is string => Boolean(color),
|
||||
);
|
||||
|
||||
if (!visible) return null;
|
||||
|
||||
return (
|
||||
<Flex
|
||||
w="75%"
|
||||
mt={3}
|
||||
w="fit-content"
|
||||
maw="75%"
|
||||
h={size}
|
||||
align={"center"}
|
||||
pos={"absolute"}
|
||||
gap={3}
|
||||
bottom={isSmall ? 4 : 10}
|
||||
left={"12.5%"}
|
||||
gap={2}
|
||||
p={0}
|
||||
direction={"row"}
|
||||
justify={"center"}
|
||||
aria-hidden
|
||||
>
|
||||
{notificationEvents.map((notificationEvent) => {
|
||||
return <Box key={notificationEvent} bg={notificationEvent} h={4} w={4} p={0} style={{ borderRadius: 999 }} />;
|
||||
return (
|
||||
<Box key={notificationEvent} bg={notificationEvent} h={size} w={size} p={0} style={{ borderRadius: 999 }} />
|
||||
);
|
||||
})}
|
||||
</Flex>
|
||||
);
|
||||
|
||||
@@ -12,11 +12,18 @@
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.homarr-data-table .mantine-datatable-table {
|
||||
width: 100% !important;
|
||||
max-width: 100%;
|
||||
table-layout: fixed !important;
|
||||
}
|
||||
|
||||
.homarr-data-table .mantine-datatable-table tbody tr:hover {
|
||||
background-color: color-mix(in srgb, var(--mantine-color-default-hover) 40%, transparent) !important;
|
||||
}
|
||||
|
||||
.homarr-data-table th {
|
||||
padding: 0;
|
||||
white-space: nowrap;
|
||||
background-color: color-mix(in srgb, var(--mantine-color-body) 60%, transparent) !important;
|
||||
backdrop-filter: blur(8px);
|
||||
@@ -28,6 +35,13 @@
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
/* Lets a cell's content (e.g. an oversized action icon) visually overflow its own box without
|
||||
growing it - used to make a per-row icon look bigger without inflating row height, since the
|
||||
icon is pulled out of flow via absolute positioning rather than actually being a bigger cell. */
|
||||
.homarr-data-table td.docker-actions-cell {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.homarr-data-table td .mantine-Text-root,
|
||||
.homarr-data-table td .mantine-Group-root {
|
||||
white-space: nowrap;
|
||||
@@ -40,6 +54,25 @@
|
||||
transition: opacity 150ms ease-out;
|
||||
}
|
||||
|
||||
.homarr-data-table .mantine-datatable-header-cell-sortable-group {
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
.homarr-data-table .mantine-datatable-header-cell-draggable-action-icon {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.homarr-data-table .mantine-datatable-header-cell-sortable-unsorted-icon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.homarr-data-table .mantine-datatable-header-cell-draggable-action-icon svg,
|
||||
.homarr-data-table .mantine-datatable-header-cell-sortable-text svg,
|
||||
.homarr-data-table .mantine-datatable-header-cell-sortable-icon svg {
|
||||
width: var(--mantine-font-size-md);
|
||||
height: var(--mantine-font-size-md);
|
||||
}
|
||||
|
||||
.homarr-data-table th:hover .mantine-datatable-header-cell-sortable-icon,
|
||||
.homarr-data-table th:hover .mantine-datatable-header-cell-draggable-action-icon,
|
||||
.homarr-data-table .mantine-datatable-header-cell-draggable-action-icon:focus-visible,
|
||||
|
||||
@@ -2,10 +2,24 @@
|
||||
|
||||
import "./homarr-data-table.css";
|
||||
|
||||
import type { DataTableProps } from "mantine-datatable";
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import type { DataTableColumn, DataTableProps } from "mantine-datatable";
|
||||
import { DataTable } from "mantine-datatable";
|
||||
|
||||
const fallbackColumnWidth = 60;
|
||||
|
||||
const getColumnWidth = (width: string | number | undefined): number => {
|
||||
if (typeof width === "number" && Number.isFinite(width) && width > 0) return width;
|
||||
if (typeof width === "string") {
|
||||
const parsedWidth = Number.parseFloat(width);
|
||||
if (Number.isFinite(parsedWidth) && parsedWidth > 0) return parsedWidth;
|
||||
}
|
||||
return fallbackColumnWidth;
|
||||
};
|
||||
|
||||
type HomarrDataTableProps<T> = DataTableProps<T> & {
|
||||
columns: DataTableColumn<T>[];
|
||||
groups?: never;
|
||||
isEditMode: boolean;
|
||||
cellPadding: string;
|
||||
rowCursor?: "auto" | "default";
|
||||
@@ -16,11 +30,78 @@ export function HomarrDataTable<T>({
|
||||
cellPadding,
|
||||
rowCursor = "auto",
|
||||
className,
|
||||
columns,
|
||||
defaultColumnProps,
|
||||
onMouseDownCapture,
|
||||
scrollAreaProps,
|
||||
style,
|
||||
...props
|
||||
}: HomarrDataTableProps<T>) {
|
||||
const [resizePreviewWidths, setResizePreviewWidths] = useState<Record<string, number>>();
|
||||
const removeResizeListeners = useRef<() => void>(() => undefined);
|
||||
useEffect(() => () => removeResizeListeners.current(), []);
|
||||
|
||||
const handleMouseDownCapture = useCallback(
|
||||
(event: React.MouseEvent<HTMLTableElement>) => {
|
||||
onMouseDownCapture?.(event);
|
||||
const target = event.target;
|
||||
if (!(target instanceof Element)) return;
|
||||
|
||||
const handle = target.closest(".mantine-datatable-header-resizable-handle");
|
||||
const currentCell = handle?.closest<HTMLTableCellElement>("th[data-accessor]");
|
||||
const headerRow = currentCell?.parentElement;
|
||||
if (!currentCell || !headerRow) return;
|
||||
|
||||
const cells = Array.from(headerRow.querySelectorAll<HTMLTableCellElement>("th[data-accessor]"));
|
||||
const currentIndex = cells.indexOf(currentCell);
|
||||
const nextCell = cells[currentIndex + 1];
|
||||
const currentAccessor = currentCell.dataset.accessor;
|
||||
const nextAccessor = nextCell?.dataset.accessor;
|
||||
if (!nextCell || !currentAccessor || !nextAccessor) return;
|
||||
|
||||
const widths = Object.fromEntries(
|
||||
cells.flatMap((cell) => {
|
||||
const accessor = cell.dataset.accessor;
|
||||
if (!accessor) return [];
|
||||
return [[accessor, cell.getBoundingClientRect().width]];
|
||||
}),
|
||||
);
|
||||
const currentWidth = widths[currentAccessor];
|
||||
const nextWidth = widths[nextAccessor];
|
||||
if (currentWidth === undefined || nextWidth === undefined) return;
|
||||
|
||||
const visualScale = currentCell.getBoundingClientRect().width / currentCell.offsetWidth;
|
||||
const minimumWidth = fallbackColumnWidth * visualScale;
|
||||
const startX = event.clientX;
|
||||
|
||||
removeResizeListeners.current();
|
||||
const handleMouseMove = (moveEvent: MouseEvent) => {
|
||||
const delta = Math.min(
|
||||
nextWidth - minimumWidth,
|
||||
Math.max(minimumWidth - currentWidth, moveEvent.clientX - startX),
|
||||
);
|
||||
setResizePreviewWidths({
|
||||
...widths,
|
||||
[currentAccessor]: currentWidth + delta,
|
||||
[nextAccessor]: nextWidth - delta,
|
||||
});
|
||||
};
|
||||
const handleResizeEnd = () => {
|
||||
removeResizeListeners.current();
|
||||
requestAnimationFrame(() => requestAnimationFrame(() => setResizePreviewWidths(undefined)));
|
||||
};
|
||||
removeResizeListeners.current = () => {
|
||||
window.removeEventListener("mousemove", handleMouseMove);
|
||||
window.removeEventListener("mouseup", handleResizeEnd);
|
||||
window.removeEventListener("blur", handleResizeEnd);
|
||||
};
|
||||
window.addEventListener("mousemove", handleMouseMove);
|
||||
window.addEventListener("mouseup", handleResizeEnd);
|
||||
window.addEventListener("blur", handleResizeEnd);
|
||||
},
|
||||
[onMouseDownCapture],
|
||||
);
|
||||
|
||||
const mergedClassName = [
|
||||
"homarr-data-table",
|
||||
rowCursor === "default" ? "homarr-data-table-row-cursor-default" : undefined,
|
||||
@@ -28,6 +109,26 @@ export function HomarrDataTable<T>({
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(" ");
|
||||
const fittedColumns = useMemo(() => {
|
||||
const visibleColumns = columns.filter(({ hidden }) => !hidden);
|
||||
const getRenderedWidth = (column: DataTableColumn<T>) =>
|
||||
resizePreviewWidths?.[String(column.accessor)] ?? getColumnWidth(column.width);
|
||||
const totalWidth = visibleColumns.reduce((total, column) => total + getRenderedWidth(column), 0);
|
||||
if (totalWidth <= 0) return columns;
|
||||
|
||||
return columns.map((column) => {
|
||||
if (column.hidden) return column;
|
||||
|
||||
const width = `${(getRenderedWidth(column) / totalWidth) * 100}%`;
|
||||
const fittedWidth = { width, minWidth: width, maxWidth: width };
|
||||
const cellsStyle = column.cellsStyle ?? defaultColumnProps?.cellsStyle;
|
||||
return {
|
||||
...column,
|
||||
titleStyle: [column.titleStyle, fittedWidth],
|
||||
cellsStyle: (record: T, index: number) => [cellsStyle?.(record, index), fittedWidth, { padding: cellPadding }],
|
||||
};
|
||||
});
|
||||
}, [cellPadding, columns, defaultColumnProps?.cellsStyle, resizePreviewWidths]);
|
||||
|
||||
return (
|
||||
<DataTable<T>
|
||||
@@ -42,6 +143,8 @@ export function HomarrDataTable<T>({
|
||||
textSelectionDisabled
|
||||
height="100%"
|
||||
{...props}
|
||||
columns={fittedColumns}
|
||||
onMouseDownCapture={handleMouseDownCapture}
|
||||
className={mergedClassName}
|
||||
style={[{ pointerEvents: isEditMode ? "none" : undefined }, style]}
|
||||
defaultColumnProps={{
|
||||
|
||||
@@ -107,7 +107,7 @@ export const parseColumnWidths = (value: string, columnAccessors: readonly strin
|
||||
}
|
||||
};
|
||||
|
||||
export const usePersistedTableLayout = <T>({
|
||||
export const usePersistedTableLayout = <T,>({
|
||||
columns,
|
||||
columnAccessors,
|
||||
columnOrder,
|
||||
|
||||
@@ -39,7 +39,6 @@ describe("supportsAdvancedFocus", () => {
|
||||
beszelSystemStatsDefinition,
|
||||
beszelSystemTableDefinition,
|
||||
customApiDefinition,
|
||||
dockerDefinition,
|
||||
indexerManagerDefinition,
|
||||
notebookDefinition,
|
||||
])("keeps non-enhanced widgets compact", (widgetDefinition) => {
|
||||
@@ -49,6 +48,7 @@ describe("supportsAdvancedFocus", () => {
|
||||
test("requires an explicit opt-in", () => {
|
||||
expect(supportsAdvancedFocus({})).toBe(false);
|
||||
expect(supportsAdvancedFocus(clockDefinition)).toBe(true);
|
||||
expect(supportsAdvancedFocus(dockerDefinition)).toBe(true);
|
||||
expect(supportsAdvancedFocus(downloadsDefinition)).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -69,6 +69,18 @@ interface ContainerActionHandlers {
|
||||
const columnAccessors = ["name", "state", "host", "cpuUsage", "memoryUsage", "actions"] as const;
|
||||
const containerMenuWidth = 240;
|
||||
|
||||
// The *button* sizes stay small and fixed - row height is set by the tallest cell, and the
|
||||
// actions button is repeated once per row, so any growth here multiplies across every row and
|
||||
// tanks how many containers fit on screen. The *icon* sizes are rendered larger than their
|
||||
// button via absolute positioning (see ContainerMenuButton/footer refresh below) - an
|
||||
// absolutely-positioned element is removed from normal flow, so it doesn't count toward its
|
||||
// ancestor's height even though it visually overflows the button. This lets the icon look
|
||||
// properly sized without the button (and therefore the row) growing to match.
|
||||
const rowActionButtonSize = 22;
|
||||
const rowActionIconVisualSize = 32;
|
||||
const footerRefreshButtonSize = 24;
|
||||
const footerRefreshIconVisualSize = 30;
|
||||
|
||||
const createContainerLogsPath = (container: Pick<DockerContainer, "endpointId" | "id" | "name">) =>
|
||||
`/manage/tools/docker/logs/${container.id}?name=${encodeURIComponent(container.name)}&endpointId=${encodeURIComponent(container.endpointId)}`;
|
||||
|
||||
@@ -83,7 +95,13 @@ const ContainerStateBadge = ({ state }: { state: ContainerState }) => {
|
||||
const t = useScopedI18n("docker.field.state.option");
|
||||
|
||||
return (
|
||||
<Badge size="xs" radius="sm" variant="light" color={containerStateColorMap[state]}>
|
||||
<Badge
|
||||
size="xs"
|
||||
radius="sm"
|
||||
variant="light"
|
||||
color={containerStateColorMap[state]}
|
||||
styles={{ label: { lineHeight: 1.2 } }}
|
||||
>
|
||||
{t(state)}
|
||||
</Badge>
|
||||
);
|
||||
@@ -126,16 +144,15 @@ const createColumns = (
|
||||
<Group gap="xs" wrap="nowrap" style={{ overflow: "hidden" }}>
|
||||
{inlineState && <ContainerStateDot state={container.state} />}
|
||||
<Avatar
|
||||
variant="outline"
|
||||
radius="sm"
|
||||
size={20}
|
||||
radius="xl"
|
||||
size={24}
|
||||
styles={{ image: { objectFit: "contain" } }}
|
||||
src={container.iconUrl}
|
||||
style={{ flexShrink: 0 }}
|
||||
>
|
||||
{container.name.at(0)?.toUpperCase()}
|
||||
</Avatar>
|
||||
<Text size="sm" truncate>
|
||||
<Text size="sm" lh={1.2} truncate>
|
||||
{container.name}
|
||||
</Text>
|
||||
</Group>
|
||||
@@ -191,8 +208,12 @@ const createColumns = (
|
||||
{
|
||||
accessor: "actions",
|
||||
title: "",
|
||||
width: 44,
|
||||
width: rowActionButtonSize + 18,
|
||||
textAlign: "right",
|
||||
// The default `.homarr-data-table td { overflow: hidden }` (needed for name/host ellipsis
|
||||
// truncation) would clip the actions icon's intentional visual overflow - opt this one
|
||||
// cell out of it.
|
||||
cellsClassName: "docker-actions-cell",
|
||||
render: (container) => <ContainerMenuButton container={container} handlers={handlers} />,
|
||||
},
|
||||
];
|
||||
@@ -407,7 +428,7 @@ export default function DockerWidget({
|
||||
<Box style={{ flex: 1, minHeight: 0 }}>
|
||||
<HomarrDataTable
|
||||
isEditMode={isEditMode}
|
||||
cellPadding={width < 400 ? "2px 8px" : "4px 8px"}
|
||||
cellPadding="2px 8px"
|
||||
rowCursor="default"
|
||||
fetching={isFetching && containers.length === 0}
|
||||
fz={width < 400 ? "xs" : "sm"}
|
||||
@@ -431,38 +452,43 @@ export default function DockerWidget({
|
||||
style={{
|
||||
borderTop: "0.0625rem solid var(--border-color)",
|
||||
}}
|
||||
p={4}
|
||||
py={2}
|
||||
px={8}
|
||||
wrap="nowrap"
|
||||
>
|
||||
<Group gap={4} wrap="nowrap">
|
||||
<IconBrandDocker size="var(--mantine-font-size-xl)" style={{ flexShrink: 0 }} />
|
||||
<Text size="sm" truncate>
|
||||
<IconBrandDocker size="var(--mantine-font-size-md)" style={{ flexShrink: 0 }} />
|
||||
<Text size="xs" truncate>
|
||||
{t("table.footer", { count: containers.length.toString() })}
|
||||
</Text>
|
||||
</Group>
|
||||
|
||||
<Group gap="sm" wrap="nowrap" justify="flex-end" style={{ minWidth: 0 }}>
|
||||
{footerVisibility.cpu && (
|
||||
<Text size="sm" style={{ whiteSpace: "nowrap" }}>
|
||||
<Text size="xs" style={{ whiteSpace: "nowrap" }}>
|
||||
{t("table.totalCpu", { cpu: totals.cpu.toFixed(2) })}
|
||||
</Text>
|
||||
)}
|
||||
{footerVisibility.memory && (
|
||||
<Text size="sm" style={{ whiteSpace: "nowrap" }}>
|
||||
<Text size="xs" style={{ whiteSpace: "nowrap" }}>
|
||||
{t("table.totalMemory", { memory: formatBytes(totals.memory) })}
|
||||
</Text>
|
||||
)}
|
||||
<Tooltip label={t("table.refresh.lastUpdated", { when: relativeTime })}>
|
||||
<ActionIcon
|
||||
className={actionTargetClasses.root}
|
||||
size="sm"
|
||||
size={footerRefreshButtonSize}
|
||||
variant="transparent"
|
||||
c="var(--mantine-color-text)"
|
||||
loading={isFetching || refreshInventory.isPending}
|
||||
onClick={() => refreshInventory.mutate()}
|
||||
aria-label={t("table.refresh.lastUpdated", { when: relativeTime })}
|
||||
style={{ position: "relative", overflow: "visible" }}
|
||||
>
|
||||
<IconRefresh size="var(--mantine-font-size-md)" />
|
||||
<IconRefresh
|
||||
size={footerRefreshIconVisualSize}
|
||||
style={{ position: "absolute", top: "50%", left: "50%", transform: "translate(-50%, -50%)" }}
|
||||
/>
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
</Group>
|
||||
@@ -492,11 +518,18 @@ function ContainerMenuButton({
|
||||
className={actionTargetClasses.root}
|
||||
variant="subtle"
|
||||
color="gray"
|
||||
size="sm"
|
||||
size={rowActionButtonSize}
|
||||
aria-label={t("title")}
|
||||
onClick={(event) => event.stopPropagation()}
|
||||
style={{ position: "relative", overflow: "visible" }}
|
||||
>
|
||||
<IconDots size="var(--mantine-font-size-md)" />
|
||||
{/* Rendered larger than the button and pulled out of flow via absolute positioning,
|
||||
so it looks properly sized without the button - and therefore the row - growing
|
||||
to match (row height is set by the tallest cell, and this button repeats per row). */}
|
||||
<IconDots
|
||||
size={rowActionIconVisualSize}
|
||||
style={{ position: "absolute", top: "50%", left: "50%", transform: "translate(-50%, -50%)" }}
|
||||
/>
|
||||
</ActionIcon>
|
||||
</Menu.Target>
|
||||
<Menu.Dropdown w={containerMenuWidth} miw={containerMenuWidth} maw={containerMenuWidth}>
|
||||
|
||||
@@ -26,6 +26,7 @@ const columnTranslationKeyMap = {
|
||||
|
||||
export const { definition, componentLoader } = createWidgetDefinition("dockerContainers", {
|
||||
icon: IconBrandDocker,
|
||||
supportsAdvancedFocus: true,
|
||||
queryKey: [["docker", "getContainers"]],
|
||||
refetchInterval: 30,
|
||||
createOptions() {
|
||||
|
||||
@@ -793,7 +793,9 @@ export default function DownloadClientsWidget({
|
||||
animateOpacity: true,
|
||||
transitionTimingFunction: "ease-out",
|
||||
},
|
||||
content: ({ record, collapse }) => <ExpandedRow item={record} collapse={collapse} />,
|
||||
content: ({ record, collapse }) => (
|
||||
<ExpandedRow item={record} collapse={collapse} />
|
||||
),
|
||||
}}
|
||||
onScroll={() => {
|
||||
if (contextMenu) closeContextMenu();
|
||||
@@ -869,7 +871,13 @@ function buildHoverTooltip(record: ExtendedDownloadClientItem, t: DownloadsT): R
|
||||
);
|
||||
}
|
||||
|
||||
function ExpandedRow({ item, collapse }: { item: ExtendedDownloadClientItem; collapse: () => void }) {
|
||||
function ExpandedRow({
|
||||
item,
|
||||
collapse,
|
||||
}: {
|
||||
item: ExtendedDownloadClientItem;
|
||||
collapse: () => void;
|
||||
}) {
|
||||
const t = useScopedI18n("widget.downloads");
|
||||
const locale = useCurrentIntlLocale();
|
||||
const progressPercent = Math.floor(item.progress * 100);
|
||||
@@ -891,13 +899,13 @@ function ExpandedRow({ item, collapse }: { item: ExtendedDownloadClientItem; col
|
||||
thickness={5}
|
||||
roundCaps
|
||||
sections={[{ value: progressPercent, color: progressColor(item.state, item.progress) }]}
|
||||
label={<Text ta="center" fw={700} style={{ fontSize: 10 }}>{`${progressPercent}%`}</Text>}
|
||||
label={<Text size="xs" ta="center" fw={700}>{`${progressPercent}%`}</Text>}
|
||||
/>
|
||||
|
||||
<Stack gap={4} style={{ flex: 1 }}>
|
||||
<Group gap="xs" wrap="nowrap">
|
||||
<Avatar size={16} radius={0} src={getIconUrl(item.integration.kind)} />
|
||||
<Text size="xs" fw={600} truncate>
|
||||
<Stack gap="xs" style={{ flex: 1, minWidth: 0 }}>
|
||||
<Group gap="xs" wrap="nowrap" style={{ minWidth: 0 }}>
|
||||
<Avatar size="var(--mantine-font-size-md)" radius={0} src={getIconUrl(item.integration.kind)} />
|
||||
<Text size="sm" fw={600} truncate style={{ minWidth: 0 }}>
|
||||
{item.name}
|
||||
</Text>
|
||||
<Badge size="xs" variant="light" color={stateColorMap[item.state]} ml="auto" style={{ flexShrink: 0 }}>
|
||||
@@ -905,7 +913,7 @@ function ExpandedRow({ item, collapse }: { item: ExtendedDownloadClientItem; col
|
||||
</Badge>
|
||||
</Group>
|
||||
|
||||
<SimpleGrid cols={3} spacing={4} verticalSpacing={2}>
|
||||
<SimpleGrid cols={3} spacing="xs" verticalSpacing={4} style={{ minWidth: 0 }}>
|
||||
<DetailPair
|
||||
label={t("items.size.detailsTitle")}
|
||||
value={`${formatBytes(item.received)} / ${formatBytes(item.size)}`}
|
||||
@@ -957,17 +965,17 @@ function DetailPair({
|
||||
color?: string;
|
||||
}) {
|
||||
return (
|
||||
<Group gap={4} wrap="nowrap">
|
||||
<Text size="xs" c="dimmed" style={{ whiteSpace: "nowrap", fontSize: 10 }}>
|
||||
<Stack gap={0} style={{ minWidth: 0, overflow: "hidden" }}>
|
||||
<Text size="xs" c="dimmed" truncate>
|
||||
{label}:
|
||||
</Text>
|
||||
<Group gap={2} wrap="nowrap">
|
||||
<Group gap={2} wrap="nowrap" style={{ minWidth: 0 }}>
|
||||
{icon}
|
||||
<Text size="xs" fw={500} c={color} truncate style={{ fontSize: 10 }}>
|
||||
<Text size="sm" fw={500} c={color} truncate style={{ minWidth: 0 }}>
|
||||
{value}
|
||||
</Text>
|
||||
</Group>
|
||||
</Group>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { describe, expect, test } from "vitest";
|
||||
|
||||
import {
|
||||
DOWNLOAD_COLUMN_ACCESSORS,
|
||||
ADVANCED_DOWNLOAD_COLUMN_ACCESSORS,
|
||||
filterDownloadItemsByStatus,
|
||||
getAvailableDownloadStates,
|
||||
getDownloadColumnAccessors,
|
||||
@@ -25,8 +25,8 @@ describe("downloads filters", () => {
|
||||
});
|
||||
|
||||
describe("downloads advanced columns", () => {
|
||||
test("uses every column in advanced mode without changing the compact selection", () => {
|
||||
expect(getDownloadColumnAccessors(["name"], true)).toEqual(DOWNLOAD_COLUMN_ACCESSORS);
|
||||
test("uses summary columns in advanced mode without changing the compact selection", () => {
|
||||
expect(getDownloadColumnAccessors(["name"], true)).toEqual(ADVANCED_DOWNLOAD_COLUMN_ACCESSORS);
|
||||
expect(getDownloadColumnAccessors(["name"], false)).toEqual(["name"]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -20,6 +20,17 @@ export const DOWNLOAD_COLUMN_ACCESSORS = [
|
||||
"type",
|
||||
] as const satisfies readonly (keyof ExtendedDownloadClientItem)[];
|
||||
|
||||
export const ADVANCED_DOWNLOAD_COLUMN_ACCESSORS = [
|
||||
"name",
|
||||
"progress",
|
||||
"size",
|
||||
"downSpeed",
|
||||
"upSpeed",
|
||||
"time",
|
||||
"state",
|
||||
"integration",
|
||||
] as const satisfies readonly (typeof DOWNLOAD_COLUMN_ACCESSORS)[number][];
|
||||
|
||||
type DownloadColumnAccessor = (typeof DOWNLOAD_COLUMN_ACCESSORS)[number];
|
||||
|
||||
export function getDownloadsStatsDisplay(showCompactStats: boolean, isAdvanced: boolean) {
|
||||
@@ -33,7 +44,7 @@ export function getDownloadColumnAccessors(
|
||||
configuredColumns: readonly DownloadColumnAccessor[],
|
||||
isAdvanced: boolean,
|
||||
): readonly DownloadColumnAccessor[] {
|
||||
return isAdvanced ? DOWNLOAD_COLUMN_ACCESSORS : configuredColumns;
|
||||
return isAdvanced ? ADVANCED_DOWNLOAD_COLUMN_ACCESSORS : configuredColumns;
|
||||
}
|
||||
|
||||
export function filterDownloadItemsByStatus<T extends { state: DownloadState }>(
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
diff --git a/dist/index.js b/dist/index.js
|
||||
index 1ac8241b321236fb9f43feb9405151da1fd3d975..9fb5fff13b2bfd2d1db4a7d16003f1fa9e0fb699 100644
|
||||
--- a/dist/index.js
|
||||
+++ b/dist/index.js
|
||||
@@ -1,2 +1,2 @@
|
||||
-"use strict";"use client";var pr=Object.create;var Dt=Object.defineProperty;var fr=Object.getOwnPropertyDescriptor;var br=Object.getOwnPropertyNames;var gr=Object.getPrototypeOf,Tr=Object.prototype.hasOwnProperty;var hr=(e,t)=>{for(var n in t)Dt(e,n,{get:t[n],enumerable:!0})},Rn=(e,t,n,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of br(t))!Tr.call(e,a)&&a!==n&&Dt(e,a,{get:()=>t[a],enumerable:!(o=fr(t,a))||o.enumerable});return e};var q=(e,t,n)=>(n=e!=null?pr(gr(e)):{},Rn(t||!e||!e.__esModule?Dt(n,"default",{value:e,enumerable:!0}):n,e)),Cr=e=>Rn(Dt({},"__esModule",{value:!0}),e);var xr={};hr(xr,{DataTable:()=>ra,DataTableDraggableRow:()=>sa,calculateColSpan:()=>it,differenceBy:()=>an,flattenColumns:()=>Xe,getGroupsAtDepth:()=>vt,getMaxGroupDepth:()=>xt,getRecordId:()=>F,getValueAtPath:()=>Rt,hasStringAccessor:()=>rt,humanize:()=>Ie,needsRightBorder:()=>rn,reorderRecords:()=>yr,sanitizeStoredArray:()=>pe,swapRecords:()=>Pr,uniqBy:()=>lt,useDataTableColumns:()=>ln});module.exports=Cr(xr);var Bt=require("@mantine/core"),Wt=require("@mantine/hooks"),Tn=q(require("clsx")),J=require("react");var xn=require("@mantine/core");function V(e,t,n){return e?(0,xn.parseThemeColor)({color:typeof e=="object"?e[n]:e,theme:t}).value:void 0}function vn({theme:e,c:t,backgroundColor:n,borderColor:o,rowBorderColor:a,stripedColor:r,highlightOnHoverColor:l}){return{"--mantine-datatable-color-light":V(t,e,"light"),"--mantine-datatable-color-dark":V(t,e,"dark"),"--mantine-datatable-background-color-light":V(n,e,"light"),"--mantine-datatable-background-color-dark":V(n,e,"dark"),"--mantine-datatable-border-color-light":V(o,e,"light"),"--mantine-datatable-border-color-dark":V(o,e,"dark"),"--mantine-datatable-row-border-color-light":V(a,e,"light"),"--mantine-datatable-row-border-color-dark":V(a,e,"dark"),"--mantine-datatable-striped-color-light":V(r,e,"light"),"--mantine-datatable-striped-color-dark":V(r,e,"dark"),"--mantine-datatable-highlight-on-hover-color-light":V(l,e,"light"),"--mantine-datatable-highlight-on-hover-color-dark":V(l,e,"dark")}}function wt({theme:e,paginationActiveTextColor:t,paginationActiveBackgroundColor:n}){return{"--mantine-datatable-pagination-active-text-color-light":V(t,e,"light"),"--mantine-datatable-pagination-active-text-color-dark":V(t,e,"dark"),"--mantine-datatable-pagination-active-background-color-light":V(n,e,"light"),"--mantine-datatable-pagination-active-background-color-dark":V(n,e,"dark")}}function Mn({theme:e,color:t,backgroundColor:n}){return{"--mantine-datatable-row-color-light":V(t,e,"light"),"--mantine-datatable-row-color-dark":V(t,e,"dark"),"--mantine-datatable-row-background-color-light":V(n,e,"light"),"--mantine-datatable-row-background-color-dark":V(n,e,"dark")}}var en=require("react");var kn=require("@mantine/core"),[En,$e]=(0,kn.createSafeContext)("useDataTableColumnsContext must be used within DataTableColumnProvider");var Ln=require("react/jsx-runtime"),tn=e=>{let{children:t,columnsOrder:n,setColumnsOrder:o,columnsToggle:a,setColumnsToggle:r,columnsPinning:l,setColumnsPinning:s,resetColumnsOrder:c,resetColumnsToggle:m,resetColumnsPinning:i,setColumnWidth:u,setMultipleColumnWidths:p,resetColumnsWidth:T,beginResize:d,endResize:S,pinnedMap:b}=e,[C,E]=(0,en.useState)(""),[D,L]=(0,en.useState)("");return(0,Ln.jsx)(En,{value:{sourceColumn:C,setSourceColumn:E,targetColumn:D,setTargetColumn:L,columnsToggle:a,setColumnsToggle:r,columnsPinning:l,setColumnsPinning:s,swapColumns:()=>{if(!n||!o||!C||!D)return;let f=b.get(C),h=b.get(D);if(f?.logicalSide!==h?.logicalSide)return;let w=n.indexOf(C),M=n.indexOf(D);if(w!==-1&&M!==-1){let g=[...n],[R]=g.splice(w,1);g.splice(M,0,R),o(g)}},resetColumnsOrder:c,resetColumnsToggle:m,resetColumnsPinning:i,setColumnWidth:u,setMultipleColumnWidths:p,resetColumnsWidth:T,beginResize:d,endResize:S},children:t})};var nn=require("react/jsx-runtime");function In(){return(0,nn.jsx)("tr",{className:"mantine-datatable-empty-row",children:(0,nn.jsx)("td",{})})}var St=require("@mantine/core");var be=require("react/jsx-runtime");function Nn(){return(0,be.jsxs)("svg",{width:"24",height:"24",viewBox:"0 0 24 24",strokeWidth:"2",stroke:"currentColor",fill:"none",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,be.jsx)("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),(0,be.jsx)("path",{d:"M12.983 8.978c3.955 -.182 7.017 -1.446 7.017 -2.978c0 -1.657 -3.582 -3 -8 -3c-1.661 0 -3.204 .19 -4.483 .515m-2.783 1.228c-.471 .382 -.734 .808 -.734 1.257c0 1.22 1.944 2.271 4.734 2.74"}),(0,be.jsx)("path",{d:"M4 6v6c0 1.657 3.582 3 8 3c.986 0 1.93 -.067 2.802 -.19m3.187 -.82c1.251 -.53 2.011 -1.228 2.011 -1.99v-6"}),(0,be.jsx)("path",{d:"M4 12v6c0 1.657 3.582 3 8 3c3.217 0 5.991 -.712 7.261 -1.74m.739 -3.26v-4"}),(0,be.jsx)("path",{d:"M3 3l18 18"})]})}var me=require("react/jsx-runtime");function Hn({icon:e,text:t,active:n,children:o}){return(0,me.jsx)(St.Center,{className:"mantine-datatable-empty-state","data-active":n||void 0,children:o||(0,me.jsxs)(me.Fragment
Line truncated
|
||||
+"use strict";"use client";var pr=Object.create;var Dt=Object.defineProperty;var fr=Object.getOwnPropertyDescriptor;var br=Object.getOwnPropertyNames;var gr=Object.getPrototypeOf,Tr=Object.prototype.hasOwnProperty;var hr=(e,t)=>{for(var n in t)Dt(e,n,{get:t[n],enumerable:!0})},Rn=(e,t,n,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of br(t))!Tr.call(e,a)&&a!==n&&Dt(e,a,{get:()=>t[a],enumerable:!(o=fr(t,a))||o.enumerable});return e};var q=(e,t,n)=>(n=e!=null?pr(gr(e)):{},Rn(t||!e||!e.__esModule?Dt(n,"default",{value:e,enumerable:!0}):n,e)),Cr=e=>Rn(Dt({},"__esModule",{value:!0}),e);var xr={};hr(xr,{DataTable:()=>ra,DataTableDraggableRow:()=>sa,calculateColSpan:()=>it,differenceBy:()=>an,flattenColumns:()=>Xe,getGroupsAtDepth:()=>vt,getMaxGroupDepth:()=>xt,getRecordId:()=>F,getValueAtPath:()=>Rt,hasStringAccessor:()=>rt,humanize:()=>Ie,needsRightBorder:()=>rn,reorderRecords:()=>yr,sanitizeStoredArray:()=>pe,swapRecords:()=>Pr,uniqBy:()=>lt,useDataTableColumns:()=>ln});module.exports=Cr(xr);var Bt=require("@mantine/core"),Wt=require("@mantine/hooks"),Tn=q(require("clsx")),J=require("react");var xn=require("@mantine/core");function V(e,t,n){return e?(0,xn.parseThemeColor)({color:typeof e=="object"?e[n]:e,theme:t}).value:void 0}function vn({theme:e,c:t,backgroundColor:n,borderColor:o,rowBorderColor:a,stripedColor:r,highlightOnHoverColor:l}){return{"--mantine-datatable-color-light":V(t,e,"light"),"--mantine-datatable-color-dark":V(t,e,"dark"),"--mantine-datatable-background-color-light":V(n,e,"light"),"--mantine-datatable-background-color-dark":V(n,e,"dark"),"--mantine-datatable-border-color-light":V(o,e,"light"),"--mantine-datatable-border-color-dark":V(o,e,"dark"),"--mantine-datatable-row-border-color-light":V(a,e,"light"),"--mantine-datatable-row-border-color-dark":V(a,e,"dark"),"--mantine-datatable-striped-color-light":V(r,e,"light"),"--mantine-datatable-striped-color-dark":V(r,e,"dark"),"--mantine-datatable-highlight-on-hover-color-light":V(l,e,"light"),"--mantine-datatable-highlight-on-hover-color-dark":V(l,e,"dark")}}function wt({theme:e,paginationActiveTextColor:t,paginationActiveBackgroundColor:n}){return{"--mantine-datatable-pagination-active-text-color-light":V(t,e,"light"),"--mantine-datatable-pagination-active-text-color-dark":V(t,e,"dark"),"--mantine-datatable-pagination-active-background-color-light":V(n,e,"light"),"--mantine-datatable-pagination-active-background-color-dark":V(n,e,"dark")}}function Mn({theme:e,color:t,backgroundColor:n}){return{"--mantine-datatable-row-color-light":V(t,e,"light"),"--mantine-datatable-row-color-dark":V(t,e,"dark"),"--mantine-datatable-row-background-color-light":V(n,e,"light"),"--mantine-datatable-row-background-color-dark":V(n,e,"dark")}}var en=require("react");var kn=require("@mantine/core"),[En,$e]=(0,kn.createSafeContext)("useDataTableColumnsContext must be used within DataTableColumnProvider");var Ln=require("react/jsx-runtime"),tn=e=>{let{children:t,columnsOrder:n,setColumnsOrder:o,columnsToggle:a,setColumnsToggle:r,columnsPinning:l,setColumnsPinning:s,resetColumnsOrder:c,resetColumnsToggle:m,resetColumnsPinning:i,setColumnWidth:u,setMultipleColumnWidths:p,resetColumnsWidth:T,beginResize:d,endResize:S,pinnedMap:b}=e,[C,E]=(0,en.useState)(""),[D,L]=(0,en.useState)("");return(0,Ln.jsx)(En,{value:{sourceColumn:C,setSourceColumn:E,targetColumn:D,setTargetColumn:L,columnsToggle:a,setColumnsToggle:r,columnsPinning:l,setColumnsPinning:s,swapColumns:()=>{if(!n||!o||!C||!D)return;let f=b.get(C),h=b.get(D);if(f?.logicalSide!==h?.logicalSide)return;let w=n.indexOf(C),M=n.indexOf(D);if(w!==-1&&M!==-1){let g=[...n],[R]=g.splice(w,1);g.splice(M,0,R),o(g)}},resetColumnsOrder:c,resetColumnsToggle:m,resetColumnsPinning:i,setColumnWidth:u,setMultipleColumnWidths:p,resetColumnsWidth:T,beginResize:d,endResize:S},children:t})};var nn=require("react/jsx-runtime");function In(){return(0,nn.jsx)("tr",{className:"mantine-datatable-empty-row",children:(0,nn.jsx)("td",{})})}var St=require("@mantine/core");var be=require("react/jsx-runtime");function Nn(){return(0,be.jsxs)("svg",{width:"24",height:"24",viewBox:"0 0 24 24",strokeWidth:"2",stroke:"currentColor",fill:"none",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,be.jsx)("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),(0,be.jsx)("path",{d:"M12.983 8.978c3.955 -.182 7.017 -1.446 7.017 -2.978c0 -1.657 -3.582 -3 -8 -3c-1.661 0 -3.204 .19 -4.483 .515m-2.783 1.228c-.471 .382 -.734 .808 -.734 1.257c0 1.22 1.944 2.271 4.734 2.74"}),(0,be.jsx)("path",{d:"M4 6v6c0 1.657 3.582 3 8 3c.986 0 1.93 -.067 2.802 -.19m3.187 -.82c1.251 -.53 2.011 -1.228 2.011 -1.99v-6"}),(0,be.jsx)("path",{d:"M4 12v6c0 1.657 3.582 3 8 3c3.217 0 5.991 -.712 7.261 -1.74m.739 -3.26v-4"}),(0,be.jsx)("path",{d:"M3 3l18 18"})]})}var me=require("react/jsx-runtime");function Hn({icon:e,text:t,active:n,children:o}){return(0,me.jsx)(St.Center,{className:"mantine-datatable-empty-state","data-active":n||void 0,children:o||(0,me.jsxs)(me.Fragment
Line truncated
|
||||
//# sourceMappingURL=index.js.map
|
||||
\ No newline at end of file
|
||||
diff --git a/dist/index.mjs b/dist/index.mjs
|
||||
index bfbf1cdbdd176b5776f553075da709115855384a..9583f1c5db65568d77f2dc468ab2d9841175623b 100644
|
||||
--- a/dist/index.mjs
|
||||
+++ b/dist/index.mjs
|
||||
@@ -1,2 +1,2 @@
|
||||
-"use client";import{Box as Wl,Table as Bl}from"@mantine/core";import{useMergedRef as Ht}from"@mantine/hooks";import Co from"clsx";import{useCallback as At,useEffect as Vl,useLayoutEffect as Gl,useMemo as Fl,useRef as lt}from"react";import{parseThemeColor as Sa}from"@mantine/core";function W(e,t,n){return e?Sa({color:typeof e=="object"?e[n]:e,theme:t}).value:void 0}function Ft({theme:e,c:t,backgroundColor:n,borderColor:o,rowBorderColor:a,stripedColor:r,highlightOnHoverColor:l}){return{"--mantine-datatable-color-light":W(t,e,"light"),"--mantine-datatable-color-dark":W(t,e,"dark"),"--mantine-datatable-background-color-light":W(n,e,"light"),"--mantine-datatable-background-color-dark":W(n,e,"dark"),"--mantine-datatable-border-color-light":W(o,e,"light"),"--mantine-datatable-border-color-dark":W(o,e,"dark"),"--mantine-datatable-row-border-color-light":W(a,e,"light"),"--mantine-datatable-row-border-color-dark":W(a,e,"dark"),"--mantine-datatable-striped-color-light":W(r,e,"light"),"--mantine-datatable-striped-color-dark":W(r,e,"dark"),"--mantine-datatable-highlight-on-hover-color-light":W(l,e,"light"),"--mantine-datatable-highlight-on-hover-color-dark":W(l,e,"dark")}}function We({theme:e,paginationActiveTextColor:t,paginationActiveBackgroundColor:n}){return{"--mantine-datatable-pagination-active-text-color-light":W(t,e,"light"),"--mantine-datatable-pagination-active-text-color-dark":W(t,e,"dark"),"--mantine-datatable-pagination-active-background-color-light":W(n,e,"light"),"--mantine-datatable-pagination-active-background-color-dark":W(n,e,"dark")}}function $t({theme:e,color:t,backgroundColor:n}){return{"--mantine-datatable-row-color-light":W(t,e,"light"),"--mantine-datatable-row-color-dark":W(t,e,"dark"),"--mantine-datatable-row-background-color-light":W(n,e,"light"),"--mantine-datatable-row-background-color-dark":W(n,e,"dark")}}import{useState as Ut}from"react";import{createSafeContext as Ra}from"@mantine/core";var[Xt,Pe]=Ra("useDataTableColumnsContext must be used within DataTableColumnProvider");import{jsx as xa}from"react/jsx-runtime";var Ct=e=>{let{children:t,columnsOrder:n,setColumnsOrder:o,columnsToggle:a,setColumnsToggle:r,columnsPinning:l,setColumnsPinning:s,resetColumnsOrder:c,resetColumnsToggle:m,resetColumnsPinning:i,setColumnWidth:u,setMultipleColumnWidths:p,resetColumnsWidth:T,beginResize:d,endResize:S,pinnedMap:b}=e,[C,E]=Ut(""),[D,L]=Ut("");return xa(Xt,{value:{sourceColumn:C,setSourceColumn:E,targetColumn:D,setTargetColumn:L,columnsToggle:a,setColumnsToggle:r,columnsPinning:l,setColumnsPinning:s,swapColumns:()=>{if(!n||!o||!C||!D)return;let f=b.get(C),h=b.get(D);if(f?.logicalSide!==h?.logicalSide)return;let w=n.indexOf(C),M=n.indexOf(D);if(w!==-1&&M!==-1){let g=[...n],[R]=g.splice(w,1);g.splice(M,0,R),o(g)}},resetColumnsOrder:c,resetColumnsToggle:m,resetColumnsPinning:i,setColumnWidth:u,setMultipleColumnWidths:p,resetColumnsWidth:T,beginResize:d,endResize:S},children:t})};import{jsx as Qt}from"react/jsx-runtime";function Kt(){return Qt("tr",{className:"mantine-datatable-empty-row",children:Qt("td",{})})}import{Center as Ma,Text as ka}from"@mantine/core";import{jsx as Le,jsxs as va}from"react/jsx-runtime";function jt(){return va("svg",{width:"24",height:"24",viewBox:"0 0 24 24",strokeWidth:"2",stroke:"currentColor",fill:"none",strokeLinecap:"round",strokeLinejoin:"round",children:[Le("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),Le("path",{d:"M12.983 8.978c3.955 -.182 7.017 -1.446 7.017 -2.978c0 -1.657 -3.582 -3 -8 -3c-1.661 0 -3.204 .19 -4.483 .515m-2.783 1.228c-.471 .382 -.734 .808 -.734 1.257c0 1.22 1.944 2.271 4.734 2.74"}),Le("path",{d:"M4 6v6c0 1.657 3.582 3 8 3c.986 0 1.93 -.067 2.802 -.19m3.187 -.82c1.251 -.53 2.011 -1.228 2.011 -1.99v-6"}),Le("path",{d:"M4 12v6c0 1.657 3.582 3 8 3c3.217 0 5.991 -.712 7.261 -1.74m.739 -3.26v-4"}),Le("path",{d:"M3 3l18 18"})]})}import{Fragment as Ea,jsx as Be,jsxs as La}from"react/jsx-runtime";function Jt({icon:e,text:t,active:n,children:o}){return Be(Ma,{className:"mantine-datatable-empty-state","data-active":n||void 0,children:o||La(Ea,{children:[e||Be("div",{className:"mantine-datatable-empty-state-icon",children:Be(jt,{})}),Be(ka,{component:"div",size:"sm",c:"dimmed",children:t})]})})}import{TableTfoot as dr,TableTr as mr}from"@mantine/core";import pr from"clsx";import{TableTh as lr}from"@mantine/core";import ir from"clsx";import{useCallback as fi,useRef as bi,useState as gi}from"react";import{useLocalStorage as Ia}from"@mantine/hooks";import{useEffect as Na,useMemo as Yt}from"react";function De(e){let t=e.replace(/([a-z\d])([A-Z]+)/g,"$1 $2").replace(/\W|_/g," ").trim().toLowerCase();return`${t.charAt(0).toUpperCase()}${t.slice(1)}`}function Z(e,t,n){return!Array.isArray(e)||n&&!e.every(n)?t:e}function Ve(e){return typeof e=="object"&&e!==null&&typeof e.accessor=="string"}function qt(e,t,n){return e.filter(o=>!t.map(n).includes(n(o)))}function Ge(e,t){return e.filter((n,o,a)=>o===a.findIndex(r=>t(n)===t(r)))}function yt(e,t){return t?t.match(/
Line truncated
|
||||
+"use client";import{Box as Wl,Table as Bl}from"@mantine/core";import{useMergedRef as Ht}from"@mantine/hooks";import Co from"clsx";import{useCallback as At,useEffect as Vl,useLayoutEffect as Gl,useMemo as Fl,useRef as lt}from"react";import{parseThemeColor as Sa}from"@mantine/core";function W(e,t,n){return e?Sa({color:typeof e=="object"?e[n]:e,theme:t}).value:void 0}function Ft({theme:e,c:t,backgroundColor:n,borderColor:o,rowBorderColor:a,stripedColor:r,highlightOnHoverColor:l}){return{"--mantine-datatable-color-light":W(t,e,"light"),"--mantine-datatable-color-dark":W(t,e,"dark"),"--mantine-datatable-background-color-light":W(n,e,"light"),"--mantine-datatable-background-color-dark":W(n,e,"dark"),"--mantine-datatable-border-color-light":W(o,e,"light"),"--mantine-datatable-border-color-dark":W(o,e,"dark"),"--mantine-datatable-row-border-color-light":W(a,e,"light"),"--mantine-datatable-row-border-color-dark":W(a,e,"dark"),"--mantine-datatable-striped-color-light":W(r,e,"light"),"--mantine-datatable-striped-color-dark":W(r,e,"dark"),"--mantine-datatable-highlight-on-hover-color-light":W(l,e,"light"),"--mantine-datatable-highlight-on-hover-color-dark":W(l,e,"dark")}}function We({theme:e,paginationActiveTextColor:t,paginationActiveBackgroundColor:n}){return{"--mantine-datatable-pagination-active-text-color-light":W(t,e,"light"),"--mantine-datatable-pagination-active-text-color-dark":W(t,e,"dark"),"--mantine-datatable-pagination-active-background-color-light":W(n,e,"light"),"--mantine-datatable-pagination-active-background-color-dark":W(n,e,"dark")}}function $t({theme:e,color:t,backgroundColor:n}){return{"--mantine-datatable-row-color-light":W(t,e,"light"),"--mantine-datatable-row-color-dark":W(t,e,"dark"),"--mantine-datatable-row-background-color-light":W(n,e,"light"),"--mantine-datatable-row-background-color-dark":W(n,e,"dark")}}import{useState as Ut}from"react";import{createSafeContext as Ra}from"@mantine/core";var[Xt,Pe]=Ra("useDataTableColumnsContext must be used within DataTableColumnProvider");import{jsx as xa}from"react/jsx-runtime";var Ct=e=>{let{children:t,columnsOrder:n,setColumnsOrder:o,columnsToggle:a,setColumnsToggle:r,columnsPinning:l,setColumnsPinning:s,resetColumnsOrder:c,resetColumnsToggle:m,resetColumnsPinning:i,setColumnWidth:u,setMultipleColumnWidths:p,resetColumnsWidth:T,beginResize:d,endResize:S,pinnedMap:b}=e,[C,E]=Ut(""),[D,L]=Ut("");return xa(Xt,{value:{sourceColumn:C,setSourceColumn:E,targetColumn:D,setTargetColumn:L,columnsToggle:a,setColumnsToggle:r,columnsPinning:l,setColumnsPinning:s,swapColumns:()=>{if(!n||!o||!C||!D)return;let f=b.get(C),h=b.get(D);if(f?.logicalSide!==h?.logicalSide)return;let w=n.indexOf(C),M=n.indexOf(D);if(w!==-1&&M!==-1){let g=[...n],[R]=g.splice(w,1);g.splice(M,0,R),o(g)}},resetColumnsOrder:c,resetColumnsToggle:m,resetColumnsPinning:i,setColumnWidth:u,setMultipleColumnWidths:p,resetColumnsWidth:T,beginResize:d,endResize:S},children:t})};import{jsx as Qt}from"react/jsx-runtime";function Kt(){return Qt("tr",{className:"mantine-datatable-empty-row",children:Qt("td",{})})}import{Center as Ma,Text as ka}from"@mantine/core";import{jsx as Le,jsxs as va}from"react/jsx-runtime";function jt(){return va("svg",{width:"24",height:"24",viewBox:"0 0 24 24",strokeWidth:"2",stroke:"currentColor",fill:"none",strokeLinecap:"round",strokeLinejoin:"round",children:[Le("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),Le("path",{d:"M12.983 8.978c3.955 -.182 7.017 -1.446 7.017 -2.978c0 -1.657 -3.582 -3 -8 -3c-1.661 0 -3.204 .19 -4.483 .515m-2.783 1.228c-.471 .382 -.734 .808 -.734 1.257c0 1.22 1.944 2.271 4.734 2.74"}),Le("path",{d:"M4 6v6c0 1.657 3.582 3 8 3c.986 0 1.93 -.067 2.802 -.19m3.187 -.82c1.251 -.53 2.011 -1.228 2.011 -1.99v-6"}),Le("path",{d:"M4 12v6c0 1.657 3.582 3 8 3c3.217 0 5.991 -.712 7.261 -1.74m.739 -3.26v-4"}),Le("path",{d:"M3 3l18 18"})]})}import{Fragment as Ea,jsx as Be,jsxs as La}from"react/jsx-runtime";function Jt({icon:e,text:t,active:n,children:o}){return Be(Ma,{className:"mantine-datatable-empty-state","data-active":n||void 0,children:o||La(Ea,{children:[e||Be("div",{className:"mantine-datatable-empty-state-icon",children:Be(jt,{})}),Be(ka,{component:"div",size:"sm",c:"dimmed",children:t})]})})}import{TableTfoot as dr,TableTr as mr}from"@mantine/core";import pr from"clsx";import{TableTh as lr}from"@mantine/core";import ir from"clsx";import{useCallback as fi,useRef as bi,useState as gi}from"react";import{useLocalStorage as Ia}from"@mantine/hooks";import{useEffect as Na,useMemo as Yt}from"react";function De(e){let t=e.replace(/([a-z\d])([A-Z]+)/g,"$1 $2").replace(/\W|_/g," ").trim().toLowerCase();return`${t.charAt(0).toUpperCase()}${t.slice(1)}`}function Z(e,t,n){return!Array.isArray(e)||n&&!e.every(n)?t:e}function Ve(e){return typeof e=="object"&&e!==null&&typeof e.accessor=="string"}function qt(e,t,n){return e.filter(o=>!t.map(n).includes(n(o)))}function Ge(e,t){return e.filter((n,o,a)=>o===a.findIndex(r=>t(n)===t(r)))}function yt(e,t){return t?t.match(/
Line truncated
|
||||
//# sourceMappingURL=index.mjs.map
|
||||
Generated
+4
-3
@@ -704,6 +704,7 @@ overrides:
|
||||
|
||||
patchedDependencies:
|
||||
'@types/node-unifi': 5e6ae51e2a17a7f9729bfa30b0eb3d0842a5810ac6db47603ab4a6efa1ed84c5
|
||||
mantine-datatable@9.3.1: 8b83a773610215e619e3f5acbec2d26fb6f27b089852e2bc754d10d8515c1254
|
||||
trpc-to-openapi: 2ca3c16af0fcca0c736697ad4fe553a14f794524fa9ce0d5c3e8ee4aea76090c
|
||||
|
||||
importers:
|
||||
@@ -1209,7 +1210,7 @@ importers:
|
||||
version: 3.10.1
|
||||
mantine-datatable:
|
||||
specifier: 'catalog:'
|
||||
version: 9.3.1(@mantine/core@9.4.1(@mantine/hooks@9.4.1(react@19.2.7))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@mantine/hooks@9.4.1(react@19.2.7))(clsx@2.1.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
|
||||
version: 9.3.1(patch_hash=8b83a773610215e619e3f5acbec2d26fb6f27b089852e2bc754d10d8515c1254)(@mantine/core@9.4.1(@mantine/hooks@9.4.1(react@19.2.7))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@mantine/hooks@9.4.1(react@19.2.7))(clsx@2.1.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
|
||||
mantine-react-table:
|
||||
specifier: 'catalog:'
|
||||
version: mantine-react-table-open@9.0.3(@mantine/core@9.4.1(@mantine/hooks@9.4.1(react@19.2.7))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@mantine/dates@9.4.1(@mantine/core@9.4.1(@mantine/hooks@9.4.1(react@19.2.7))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@mantine/hooks@9.4.1(react@19.2.7))(dayjs@1.11.21)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@mantine/hooks@9.4.1(react@19.2.7))(@tabler/icons-react@3.44.0(react@19.2.7))(clsx@2.1.1)(dayjs@1.11.21)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
|
||||
@@ -2984,7 +2985,7 @@ importers:
|
||||
version: 1.24.0(react@19.2.7)
|
||||
mantine-datatable:
|
||||
specifier: 'catalog:'
|
||||
version: 9.3.1(@mantine/core@9.4.1(@mantine/hooks@9.4.1(react@19.2.7))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@mantine/hooks@9.4.1(react@19.2.7))(clsx@2.1.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
|
||||
version: 9.3.1(patch_hash=8b83a773610215e619e3f5acbec2d26fb6f27b089852e2bc754d10d8515c1254)(@mantine/core@9.4.1(@mantine/hooks@9.4.1(react@19.2.7))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@mantine/hooks@9.4.1(react@19.2.7))(clsx@2.1.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
|
||||
mantine-react-table:
|
||||
specifier: 'catalog:'
|
||||
version: mantine-react-table-open@9.0.3(@mantine/core@9.4.1(@mantine/hooks@9.4.1(react@19.2.7))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@mantine/dates@9.4.1(@mantine/core@9.4.1(@mantine/hooks@9.4.1(react@19.2.7))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@mantine/hooks@9.4.1(react@19.2.7))(dayjs@1.11.21)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@mantine/hooks@9.4.1(react@19.2.7))(@tabler/icons-react@3.44.0(react@19.2.7))(clsx@2.1.1)(dayjs@1.11.21)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
|
||||
@@ -28633,7 +28634,7 @@ snapshots:
|
||||
dependencies:
|
||||
semver: 7.8.5
|
||||
|
||||
mantine-datatable@9.3.1(@mantine/core@9.4.1(@mantine/hooks@9.4.1(react@19.2.7))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@mantine/hooks@9.4.1(react@19.2.7))(clsx@2.1.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7):
|
||||
mantine-datatable@9.3.1(patch_hash=8b83a773610215e619e3f5acbec2d26fb6f27b089852e2bc754d10d8515c1254)(@mantine/core@9.4.1(@mantine/hooks@9.4.1(react@19.2.7))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@mantine/hooks@9.4.1(react@19.2.7))(clsx@2.1.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7):
|
||||
dependencies:
|
||||
'@mantine/core': 9.4.1(@mantine/hooks@9.4.1(react@19.2.7))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
|
||||
'@mantine/hooks': 9.4.1(react@19.2.7)
|
||||
|
||||
@@ -280,6 +280,7 @@ overrides:
|
||||
"vite@>=5.0.0 <=5.4.18": ">=8.1.4"
|
||||
patchedDependencies:
|
||||
"@types/node-unifi": "patches/@types__node-unifi.patch"
|
||||
mantine-datatable@9.3.1: patches/mantine-datatable@9.3.1.patch
|
||||
"trpc-to-openapi": "patches/trpc-to-openapi.patch"
|
||||
|
||||
allowUnusedPatches: true
|
||||
|
||||
Reference in new issue
Block a user